0cb28b7269f29683b0e6229f4a6622adbc379d77
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIX11.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004-2006 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //
25 //
26
27 // NOTE:
28 //      This driver understands the following environment variables: (Set the var to enable feature)
29 //
30 //      MONO_XEXCEPTIONS        = throw an exception when a X11 error is encountered;
31 //                                by default a message is displayed but execution continues
32 //
33 //      MONO_XSYNC              = perform all X11 commands synchronous; this is slower but
34 //                                helps in debugging errors
35 //
36
37 // NOT COMPLETE
38
39 // define to log Window handles and relationships to stdout
40 #undef DriverDebug
41
42 // Extra detailed debug
43 #undef DriverDebugExtra
44 #undef DriverDebugParent
45 #undef DriverDebugCreate
46 #undef DriverDebugDestroy
47 #undef DriverDebugThreads
48 #undef DriverDebugXEmbed
49
50 using System;
51 using System.ComponentModel;
52 using System.Collections;
53 using System.Diagnostics;
54 using System.Drawing;
55 using System.Drawing.Drawing2D;
56 using System.Drawing.Imaging;
57 using System.IO;
58 using System.Net;
59 using System.Net.Sockets;
60 using System.Reflection;
61 using System.Runtime.InteropServices;
62 using System.Text;
63 using System.Threading;
64
65 // Only do the poll when building with mono for now
66 #if __MonoCS__
67 using Mono.Unix.Native;
68 #endif
69
70 /// X11 Version
71 namespace System.Windows.Forms {
72         internal class XplatUIX11 : XplatUIDriver {
73                 #region Local Variables
74                 // General
75                 static volatile XplatUIX11      Instance;
76                 private static int              RefCount;
77                 private static object           XlibLock;               // Our locking object
78                 private static bool             themes_enabled;
79
80                 // General X11
81                 private static IntPtr           DisplayHandle;          // X11 handle to display
82                 private static int              ScreenNo;               // Screen number used
83                 private static IntPtr           DefaultColormap;        // Colormap for screen
84                 private static IntPtr           CustomVisual;           // Visual for window creation
85                 private static IntPtr           CustomColormap;         // Colormap for window creation
86                 private static IntPtr           RootWindow;             // Handle of the root window for the screen/display
87                 private static IntPtr           FosterParent;           // Container to hold child windows until their parent exists
88                 private static XErrorHandler    ErrorHandler;           // Error handler delegate
89                 private static bool             ErrorExceptions;        // Throw exceptions on X errors
90                 private int                     render_major_opcode;
91                 private int                     render_first_event;
92                 private int                     render_first_error;
93
94                 // Clipboard
95                 private static IntPtr           ClipMagic;
96                 private static ClipboardStruct  Clipboard;              // Our clipboard
97
98                 // Communication
99                 private static IntPtr           PostAtom;               // PostMessage atom
100                 private static IntPtr           AsyncAtom;              // Support for async messages
101
102                 // Message Loop
103                 private static Hashtable        MessageQueues;          // Holds our thread-specific XEventQueues
104                 private static ArrayList        unattached_timer_list; // holds timers that are enabled but not attached to a window.
105                 #if __MonoCS__                                          //
106                 private static Pollfd[]         pollfds;                // For watching the X11 socket
107                 private static bool wake_waiting;
108                 private static object wake_waiting_lock = new object ();
109                 #endif                                                  //
110                 private static X11Keyboard      Keyboard;               //
111                 private static X11Dnd           Dnd;
112                 private static Socket           listen;                 //
113                 private static Socket           wake;                   //
114                 private static Socket           wake_receive;           //
115                 private static byte[]           network_buffer;         //
116                 private static bool             detectable_key_auto_repeat;
117
118                 // Focus tracking
119                 private static IntPtr           ActiveWindow;           // Handle of the active window
120                 private static IntPtr           FocusWindow;            // Handle of the window with keyboard focus (if any)
121
122                 // Modality support
123                 private static Stack            ModalWindows;           // Stack of our modal windows
124
125                 // Systray
126                 private static IntPtr           SystrayMgrWindow;       // Handle of the Systray Manager window
127
128                 // Cursors
129                 private static IntPtr           LastCursorWindow;       // The last window we set the cursor on
130                 private static IntPtr           LastCursorHandle;       // The handle that was last set on LastCursorWindow
131                 private static IntPtr           OverrideCursorHandle;   // The cursor that is set to override any other cursors
132
133                 // Caret
134                 private static CaretStruct      Caret;                  //
135
136                 // Our atoms
137                 private static IntPtr WM_PROTOCOLS;
138                 private static IntPtr WM_DELETE_WINDOW;
139                 private static IntPtr WM_TAKE_FOCUS;
140                 //private static IntPtr _NET_SUPPORTED;
141                 //private static IntPtr _NET_CLIENT_LIST;
142                 //private static IntPtr _NET_NUMBER_OF_DESKTOPS;
143                 private static IntPtr _NET_DESKTOP_GEOMETRY;
144                 //private static IntPtr _NET_DESKTOP_VIEWPORT;
145                 private static IntPtr _NET_CURRENT_DESKTOP;
146                 //private static IntPtr _NET_DESKTOP_NAMES;
147                 private static IntPtr _NET_ACTIVE_WINDOW;
148                 private static IntPtr _NET_WORKAREA;
149                 //private static IntPtr _NET_SUPPORTING_WM_CHECK;
150                 //private static IntPtr _NET_VIRTUAL_ROOTS;
151                 //private static IntPtr _NET_DESKTOP_LAYOUT;
152                 //private static IntPtr _NET_SHOWING_DESKTOP;
153                 //private static IntPtr _NET_CLOSE_WINDOW;
154                 //private static IntPtr _NET_MOVERESIZE_WINDOW;
155                 //private static IntPtr _NET_WM_MOVERESIZE;
156                 //private static IntPtr _NET_RESTACK_WINDOW;
157                 //private static IntPtr _NET_REQUEST_FRAME_EXTENTS;
158                 private static IntPtr _NET_WM_NAME;
159                 //private static IntPtr _NET_WM_VISIBLE_NAME;
160                 //private static IntPtr _NET_WM_ICON_NAME;
161                 //private static IntPtr _NET_WM_VISIBLE_ICON_NAME;
162                 //private static IntPtr _NET_WM_DESKTOP;
163                 private static IntPtr _NET_WM_WINDOW_TYPE;
164                 private static IntPtr _NET_WM_STATE;
165                 //private static IntPtr _NET_WM_ALLOWED_ACTIONS;
166                 //private static IntPtr _NET_WM_STRUT;
167                 //private static IntPtr _NET_WM_STRUT_PARTIAL;
168                 //private static IntPtr _NET_WM_ICON_GEOMETRY;
169                 private static IntPtr _NET_WM_ICON;
170                 //private static IntPtr _NET_WM_PID;
171                 //private static IntPtr _NET_WM_HANDLED_ICONS;
172                 private static IntPtr _NET_WM_USER_TIME;
173                 private static IntPtr _NET_FRAME_EXTENTS;
174                 //private static IntPtr _NET_WM_PING;
175                 //private static IntPtr _NET_WM_SYNC_REQUEST;
176                 private static IntPtr _NET_SYSTEM_TRAY_S;
177                 //private static IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
178                 private static IntPtr _NET_SYSTEM_TRAY_OPCODE;
179                 private static IntPtr _NET_WM_STATE_MAXIMIZED_HORZ;
180                 private static IntPtr _NET_WM_STATE_MAXIMIZED_VERT;
181                 private static IntPtr _XEMBED;
182                 private static IntPtr _XEMBED_INFO;
183                 private static IntPtr _MOTIF_WM_HINTS;
184                 private static IntPtr _NET_WM_STATE_SKIP_TASKBAR;
185                 private static IntPtr _NET_WM_STATE_ABOVE;
186                 private static IntPtr _NET_WM_STATE_MODAL;
187                 private static IntPtr _NET_WM_STATE_HIDDEN;
188                 private static IntPtr _NET_WM_CONTEXT_HELP;
189                 private static IntPtr _NET_WM_WINDOW_OPACITY;
190                 //private static IntPtr _NET_WM_WINDOW_TYPE_DESKTOP;
191                 //private static IntPtr _NET_WM_WINDOW_TYPE_DOCK;
192                 //private static IntPtr _NET_WM_WINDOW_TYPE_TOOLBAR;
193                 //private static IntPtr _NET_WM_WINDOW_TYPE_MENU;
194                 private static IntPtr _NET_WM_WINDOW_TYPE_UTILITY;
195                 //private static IntPtr _NET_WM_WINDOW_TYPE_SPLASH;
196                 private static IntPtr _NET_WM_WINDOW_TYPE_DIALOG;
197                 private static IntPtr _NET_WM_WINDOW_TYPE_NORMAL;
198                 private static IntPtr CLIPBOARD;
199                 private static IntPtr PRIMARY;
200                 //private static IntPtr DIB;
201                 private static IntPtr OEMTEXT;
202                 private static IntPtr UNICODETEXT;
203                 private static IntPtr TARGETS;
204
205                 // mouse hover message generation
206                 private static HoverStruct      HoverState;             //
207
208                 // double click message generation
209                 private static ClickStruct      ClickPending;           //
210
211                 // Support for mouse grab
212                 private static GrabStruct       Grab;                   //
213
214                 // State
215                 Point           mouse_position;         // Last position of mouse, in screen coords
216                 internal static MouseButtons    MouseState;             // Last state of mouse buttons
217
218                 // 'Constants'
219                 private static int              DoubleClickInterval;    // msec; max interval between clicks to count as double click
220
221                 const EventMask SelectInputMask = (EventMask.ButtonPressMask | 
222                                                    EventMask.ButtonReleaseMask | 
223                                                    EventMask.KeyPressMask | 
224                                                    EventMask.KeyReleaseMask | 
225                                                    EventMask.EnterWindowMask | 
226                                                    EventMask.LeaveWindowMask |
227                                                    EventMask.ExposureMask |
228                                                    EventMask.FocusChangeMask |
229                                                    EventMask.PointerMotionMask | 
230                                                    EventMask.PointerMotionHintMask | 
231                                                    EventMask.SubstructureNotifyMask);
232
233                 static readonly object lockobj = new object ();
234
235                 #endregion      // Local Variables
236                 #region Constructors
237                 private XplatUIX11() {
238                         // Handle singleton stuff first
239                         RefCount = 0;
240
241                         // Now regular initialization
242                         XlibLock = new object ();
243                         X11Keyboard.XlibLock = XlibLock;
244                         MessageQueues = Hashtable.Synchronized (new Hashtable(7));
245                         unattached_timer_list = ArrayList.Synchronized (new ArrayList (3));
246                         XInitThreads();
247
248                         ErrorExceptions = false;
249
250                         // X11 Initialization
251                         SetDisplay(XOpenDisplay(IntPtr.Zero));
252                         X11DesktopColors.Initialize();
253
254                         
255                         // Disable keyboard autorepeat
256                         try {
257                                 XkbSetDetectableAutoRepeat (DisplayHandle, true,  IntPtr.Zero);
258                                 detectable_key_auto_repeat = true;
259                         } catch {
260                                 Console.Error.WriteLine ("Could not disable keyboard auto repeat, will attempt to disable manually.");
261                                 detectable_key_auto_repeat = false;
262                         }
263
264                         // Handle any upcoming errors; we re-set it here, X11DesktopColor stuff might have stolen it (gtk does)
265                         ErrorHandler = new XErrorHandler(HandleError);
266                         XSetErrorHandler(ErrorHandler);
267                 }
268
269                 ~XplatUIX11() {
270                         // Remove our display handle from S.D
271                         Graphics.FromHdcInternal (IntPtr.Zero);
272                 }
273
274                 #endregion      // Constructors
275
276                 #region Singleton Specific Code
277                 public static XplatUIX11 GetInstance() {
278                         lock (lockobj) {
279                                 if (Instance == null) {
280                                         Instance=new XplatUIX11();
281                                 }
282                                 RefCount++;
283                         }
284                         return Instance;
285                 }
286
287                 public int Reference {
288                         get {
289                                 return RefCount;
290                         }
291                 }
292                 #endregion
293
294                 #region Internal Properties
295                 internal static IntPtr Display {
296                         get {
297                                 return DisplayHandle;
298                         }
299
300                         set {
301                                 XplatUIX11.GetInstance().SetDisplay(value);
302                         }
303                 }
304
305                 internal static int Screen {
306                         get {
307                                 return ScreenNo;
308                         }
309
310                         set {
311                                 ScreenNo = value;
312                         }
313                 }
314
315                 internal static IntPtr RootWindowHandle {
316                         get {
317                                 return RootWindow;
318                         }
319
320                         set {
321                                 RootWindow = value;
322                         }
323                 }
324
325                 internal static IntPtr Visual {
326                         get {
327                                 return CustomVisual;
328                         }
329
330                         set {
331                                 CustomVisual = value;
332                         }
333                 }
334
335                 internal static IntPtr ColorMap {
336                         get {
337                                 return CustomColormap;
338                         }
339
340                         set {
341                                 CustomColormap = value;
342                         }
343                 }
344                 #endregion
345
346                 #region XExceptionClass
347                 internal class XException : ApplicationException {
348                         IntPtr          Display;
349                         IntPtr          ResourceID;
350                         IntPtr          Serial;
351                         XRequest        RequestCode;
352                         byte            ErrorCode;
353                         byte            MinorCode;
354
355                         public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
356                                 this.Display = Display;
357                                 this.ResourceID = ResourceID;
358                                 this.Serial = Serial;
359                                 this.RequestCode = RequestCode;
360                                 this.ErrorCode = ErrorCode;
361                                 this.MinorCode = MinorCode;
362                         }
363
364                         public override string Message {
365                                 get {
366                                         return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
367                                 }
368                         }
369
370                         public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
371                                 StringBuilder   sb;
372                                 string          x_error_text;
373                                 string          error;
374                                 string          hwnd_text;
375                                 string          control_text;
376                                 Hwnd            hwnd;
377                                 Control         c;
378
379                                 sb = new StringBuilder(160);
380                                 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
381                                 x_error_text = sb.ToString();
382                                 hwnd = Hwnd.ObjectFromHandle(ResourceID);
383                                 if (hwnd != null) {
384                                         hwnd_text = hwnd.ToString();
385                                         c = Control.FromHandle(hwnd.Handle);
386                                         if (c != null) {
387                                                 control_text = c.ToString();
388                                         } else {
389                                                 control_text = String.Format("<handle {0:X} non-existant>", hwnd.Handle);
390                                         }
391                                 } else {
392                                         hwnd_text = "<null>";
393                                         control_text = "<null>";
394                                 }
395
396
397                                 error = String.Format("\n  Error: {0}\n  Request:     {1:D} ({2})\n  Resource ID: 0x{3:X}\n  Serial:      {4}\n  Hwnd:        {5}\n  Control:     {6}", x_error_text, RequestCode, MinorCode, ResourceID.ToInt32(), Serial, hwnd_text, control_text);
398                                 return error;
399                         }
400                 }
401                 #endregion      // XExceptionClass
402
403                 #region Internal Methods
404                 internal void SetDisplay(IntPtr display_handle) {
405                         if (display_handle != IntPtr.Zero) {
406                                 Hwnd    hwnd;
407
408                                 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
409                                         hwnd = Hwnd.ObjectFromHandle(FosterParent);
410                                         XDestroyWindow(DisplayHandle, FosterParent);
411                                         hwnd.Dispose();
412                                 }
413
414                                 if (DisplayHandle != IntPtr.Zero) {
415                                         XCloseDisplay(DisplayHandle);
416                                 }
417
418                                 DisplayHandle=display_handle;
419
420                                 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
421                                 // been hacked to do this for us.
422                                 Graphics.FromHdcInternal (DisplayHandle);
423
424                                 // query for the render extension so
425                                 // we can ignore the spurious
426                                 // BadPicture errors that are
427                                 // generated by cairo/render.
428                                 XQueryExtension (DisplayHandle, "RENDER",
429                                                  ref render_major_opcode, ref render_first_event, ref render_first_error);
430
431                                 // Debugging support
432                                 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
433                                         XSynchronize(DisplayHandle, true);
434                                 }
435
436                                 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
437                                         ErrorExceptions = true;
438                                 }
439
440                                 // Generic X11 setup
441                                 ScreenNo = XDefaultScreen(DisplayHandle);
442                                 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
443                                 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
444
445                                 // Create the foster parent
446                                 // it is important that border_width is kept in synch with the other XCreateWindow calls
447                                 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 0, UIntPtr.Zero, UIntPtr.Zero);
448                                 if (FosterParent==IntPtr.Zero) {
449                                         Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
450                                 }
451
452                                 hwnd = new Hwnd();
453                                 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
454                                 hwnd.WholeWindow = FosterParent;
455                                 hwnd.ClientWindow = FosterParent;
456
457                                 // Create a HWND for RootWIndow as well, so our queue doesn't eat the events
458                                 hwnd = new Hwnd();
459                                 hwnd.Queue = ThreadQueue(Thread.CurrentThread);
460                                 hwnd.whole_window = RootWindow;
461                                 hwnd.ClientWindow = RootWindow;
462
463                                 // For sleeping on the X11 socket
464                                 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
465                                 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
466                                 listen.Bind(ep);
467                                 listen.Listen(1);
468
469                                 // To wake up when a timer is ready
470                                 network_buffer = new byte[10];
471
472                                 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
473                                 wake.Connect(listen.LocalEndPoint);
474                                 wake_receive = listen.Accept();
475
476                                 #if __MonoCS__
477                                 pollfds = new Pollfd [2];
478                                 pollfds [0] = new Pollfd ();
479                                 pollfds [0].fd = XConnectionNumber (DisplayHandle);
480                                 pollfds [0].events = PollEvents.POLLIN;
481
482                                 pollfds [1] = new Pollfd ();
483                                 pollfds [1].fd = wake_receive.Handle.ToInt32 ();
484                                 pollfds [1].events = PollEvents.POLLIN;
485                                 #endif
486
487                                 Keyboard = new X11Keyboard(DisplayHandle, FosterParent);
488                                 Dnd = new X11Dnd (DisplayHandle, Keyboard);
489
490                                 DoubleClickInterval = 500;
491
492                                 HoverState.Interval = 500;
493                                 HoverState.Timer = new Timer();
494                                 HoverState.Timer.Enabled = false;
495                                 HoverState.Timer.Interval = HoverState.Interval;
496                                 HoverState.Timer.Tick += new EventHandler(MouseHover);
497                                 HoverState.Size = new Size(4, 4);
498                                 HoverState.X = -1;
499                                 HoverState.Y = -1;
500
501                                 ActiveWindow = IntPtr.Zero;
502                                 FocusWindow = IntPtr.Zero;
503                                 ModalWindows = new Stack(3);
504
505                                 MouseState = MouseButtons.None;
506                                 mouse_position = new Point(0, 0);
507
508                                 Caret.Timer = new Timer();
509                                 Caret.Timer.Interval = 500;             // FIXME - where should this number come from?
510                                 Caret.Timer.Tick += new EventHandler(CaretCallback);
511
512                                 SetupAtoms();
513
514                                 // Grab atom changes off the root window to catch certain WM events
515                                 XSelectInput(DisplayHandle, RootWindow, new IntPtr ((int) (EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
516
517                                 // Handle any upcoming errors
518                                 ErrorHandler = new XErrorHandler(HandleError);
519                                 XSetErrorHandler(ErrorHandler);
520                         } else {
521                                 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
522                         }
523                 }
524                 #endregion      // Internal Methods
525
526                 #region Private Methods
527                 private int unixtime() {
528                         TimeSpan t = (DateTime.UtcNow - new DateTime(1970, 1, 1));
529
530                         return (int) t.TotalSeconds;
531                 }
532
533                 private static void SetupAtoms() {
534                         // make sure this array stays in sync with the statements below
535                         string [] atom_names = new string[] {
536                                 "WM_PROTOCOLS",
537                                 "WM_DELETE_WINDOW",
538                                 "WM_TAKE_FOCUS",
539                                 //"_NET_SUPPORTED",
540                                 //"_NET_CLIENT_LIST",
541                                 //"_NET_NUMBER_OF_DESKTOPS",
542                                 "_NET_DESKTOP_GEOMETRY",
543                                 //"_NET_DESKTOP_VIEWPORT",
544                                 "_NET_CURRENT_DESKTOP",
545                                 //"_NET_DESKTOP_NAMES",
546                                 "_NET_ACTIVE_WINDOW",
547                                 "_NET_WORKAREA",
548                                 //"_NET_SUPPORTING_WM_CHECK",
549                                 //"_NET_VIRTUAL_ROOTS",
550                                 //"_NET_DESKTOP_LAYOUT",
551                                 //"_NET_SHOWING_DESKTOP",
552                                 //"_NET_CLOSE_WINDOW",
553                                 //"_NET_MOVERESIZE_WINDOW",
554                                 //"_NET_WM_MOVERESIZE",
555                                 //"_NET_RESTACK_WINDOW",
556                                 //"_NET_REQUEST_FRAME_EXTENTS",
557                                 "_NET_WM_NAME",
558                                 //"_NET_WM_VISIBLE_NAME",
559                                 //"_NET_WM_ICON_NAME",
560                                 //"_NET_WM_VISIBLE_ICON_NAME",
561                                 //"_NET_WM_DESKTOP",
562                                 "_NET_WM_WINDOW_TYPE",
563                                 "_NET_WM_STATE",
564                                 //"_NET_WM_ALLOWED_ACTIONS",
565                                 //"_NET_WM_STRUT",
566                                 //"_NET_WM_STRUT_PARTIAL",
567                                 //"_NET_WM_ICON_GEOMETRY",
568                                 "_NET_WM_ICON",
569                                 //"_NET_WM_PID",
570                                 //"_NET_WM_HANDLED_ICONS",
571                                 "_NET_WM_USER_TIME",
572                                 "_NET_FRAME_EXTENTS",
573                                 //"_NET_WM_PING",
574                                 //"_NET_WM_SYNC_REQUEST",
575                                 "_NET_SYSTEM_TRAY_OPCODE",
576                                 //"_NET_SYSTEM_TRAY_ORIENTATION",
577                                 "_NET_WM_STATE_MAXIMIZED_HORZ",
578                                 "_NET_WM_STATE_MAXIMIZED_VERT",
579                                 "_NET_WM_STATE_HIDDEN",
580                                 "_XEMBED",
581                                 "_XEMBED_INFO",
582                                 "_MOTIF_WM_HINTS",
583                                 "_NET_WM_STATE_SKIP_TASKBAR",
584                                 "_NET_WM_STATE_ABOVE",
585                                 "_NET_WM_STATE_MODAL",
586                                 "_NET_WM_CONTEXT_HELP",
587                                 "_NET_WM_WINDOW_OPACITY",
588                                 //"_NET_WM_WINDOW_TYPE_DESKTOP",
589                                 //"_NET_WM_WINDOW_TYPE_DOCK",
590                                 //"_NET_WM_WINDOW_TYPE_TOOLBAR",
591                                 //"_NET_WM_WINDOW_TYPE_MENU",
592                                 "_NET_WM_WINDOW_TYPE_UTILITY",
593                                 "_NET_WM_WINDOW_TYPE_DIALOG",
594                                 //"_NET_WM_WINDOW_TYPE_SPLASH",
595                                 "_NET_WM_WINDOW_TYPE_NORMAL",
596                                 "CLIPBOARD",
597                                 "PRIMARY",
598                                 "COMPOUND_TEXT",
599                                 "UTF8_STRING",
600                                 "TARGETS",
601                                 "_SWF_AsyncAtom",
602                                 "_SWF_PostMessageAtom",
603                                 "_SWF_HoverAtom" };
604
605                         IntPtr[] atoms = new IntPtr [atom_names.Length];;
606
607                         XInternAtoms (DisplayHandle, atom_names, atom_names.Length, false, atoms);
608
609                         int off = 0;
610                         WM_PROTOCOLS = atoms [off++];
611                         WM_DELETE_WINDOW = atoms [off++];
612                         WM_TAKE_FOCUS = atoms [off++];
613                         //_NET_SUPPORTED = atoms [off++];
614                         //_NET_CLIENT_LIST = atoms [off++];
615                         //_NET_NUMBER_OF_DESKTOPS = atoms [off++];
616                         _NET_DESKTOP_GEOMETRY = atoms [off++];
617                         //_NET_DESKTOP_VIEWPORT = atoms [off++];
618                         _NET_CURRENT_DESKTOP = atoms [off++];
619                         //_NET_DESKTOP_NAMES = atoms [off++];
620                         _NET_ACTIVE_WINDOW = atoms [off++];
621                         _NET_WORKAREA = atoms [off++];
622                         //_NET_SUPPORTING_WM_CHECK = atoms [off++];
623                         //_NET_VIRTUAL_ROOTS = atoms [off++];
624                         //_NET_DESKTOP_LAYOUT = atoms [off++];
625                         //_NET_SHOWING_DESKTOP = atoms [off++];
626                         //_NET_CLOSE_WINDOW = atoms [off++];
627                         //_NET_MOVERESIZE_WINDOW = atoms [off++];
628                         //_NET_WM_MOVERESIZE = atoms [off++];
629                         //_NET_RESTACK_WINDOW = atoms [off++];
630                         //_NET_REQUEST_FRAME_EXTENTS = atoms [off++];
631                         _NET_WM_NAME = atoms [off++];
632                         //_NET_WM_VISIBLE_NAME = atoms [off++];
633                         //_NET_WM_ICON_NAME = atoms [off++];
634                         //_NET_WM_VISIBLE_ICON_NAME = atoms [off++];
635                         //_NET_WM_DESKTOP = atoms [off++];
636                         _NET_WM_WINDOW_TYPE = atoms [off++];
637                         _NET_WM_STATE = atoms [off++];
638                         //_NET_WM_ALLOWED_ACTIONS = atoms [off++];
639                         //_NET_WM_STRUT = atoms [off++];
640                         //_NET_WM_STRUT_PARTIAL = atoms [off++];
641                         //_NET_WM_ICON_GEOMETRY = atoms [off++];
642                         _NET_WM_ICON = atoms [off++];
643                         //_NET_WM_PID = atoms [off++];
644                         //_NET_WM_HANDLED_ICONS = atoms [off++];
645                         _NET_WM_USER_TIME = atoms [off++];
646                         _NET_FRAME_EXTENTS = atoms [off++];
647                         //_NET_WM_PING = atoms [off++];
648                         //_NET_WM_SYNC_REQUEST = atoms [off++];
649                         _NET_SYSTEM_TRAY_OPCODE = atoms [off++];
650                         //_NET_SYSTEM_TRAY_ORIENTATION = atoms [off++];
651                         _NET_WM_STATE_MAXIMIZED_HORZ = atoms [off++];
652                         _NET_WM_STATE_MAXIMIZED_VERT = atoms [off++];
653                         _NET_WM_STATE_HIDDEN = atoms [off++];
654                         _XEMBED = atoms [off++];
655                         _XEMBED_INFO = atoms [off++];
656                         _MOTIF_WM_HINTS = atoms [off++];
657                         _NET_WM_STATE_SKIP_TASKBAR = atoms [off++];
658                         _NET_WM_STATE_ABOVE = atoms [off++];
659                         _NET_WM_STATE_MODAL = atoms [off++];
660                         _NET_WM_CONTEXT_HELP = atoms [off++];
661                         _NET_WM_WINDOW_OPACITY = atoms [off++];
662                         //_NET_WM_WINDOW_TYPE_DESKTOP = atoms [off++];
663                         //_NET_WM_WINDOW_TYPE_DOCK = atoms [off++];
664                         //_NET_WM_WINDOW_TYPE_TOOLBAR = atoms [off++];
665                         //_NET_WM_WINDOW_TYPE_MENU = atoms [off++];
666                         _NET_WM_WINDOW_TYPE_UTILITY = atoms [off++];
667                         _NET_WM_WINDOW_TYPE_DIALOG = atoms [off++];
668                         //_NET_WM_WINDOW_TYPE_SPLASH = atoms [off++];
669                         _NET_WM_WINDOW_TYPE_NORMAL = atoms [off++];
670                         CLIPBOARD = atoms [off++];
671                         PRIMARY = atoms [off++];
672                         OEMTEXT = atoms [off++];
673                         UNICODETEXT = atoms [off++];
674                         TARGETS = atoms [off++];
675                         AsyncAtom = atoms [off++];
676                         PostAtom = atoms [off++];
677                         HoverState.Atom = atoms [off++];
678
679                         //DIB = (IntPtr)Atom.XA_PIXMAP;
680                         _NET_SYSTEM_TRAY_S = XInternAtom (DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
681                 }
682
683                 private void GetSystrayManagerWindow() {
684                         XGrabServer(DisplayHandle);
685                         SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, _NET_SYSTEM_TRAY_S);
686                         XUngrabServer(DisplayHandle);
687                         XFlush(DisplayHandle);
688                 }
689
690                 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
691                         XEvent  xev;
692
693                         xev = new XEvent();
694                         xev.ClientMessageEvent.type = XEventName.ClientMessage;
695                         xev.ClientMessageEvent.send_event = true;
696                         xev.ClientMessageEvent.window = window;
697                         xev.ClientMessageEvent.message_type = message_type;
698                         xev.ClientMessageEvent.format = 32;
699                         xev.ClientMessageEvent.ptr1 = l0;
700                         xev.ClientMessageEvent.ptr2 = l1;
701                         xev.ClientMessageEvent.ptr3 = l2;
702                         XSendEvent(DisplayHandle, RootWindow, false, new IntPtr ((int) (EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask)), ref xev);
703                 }
704
705                 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
706                         XEvent  xev;
707
708                         xev = new XEvent();
709                         xev.ClientMessageEvent.type = XEventName.ClientMessage;
710                         xev.ClientMessageEvent.send_event = true;
711                         xev.ClientMessageEvent.window = window;
712                         xev.ClientMessageEvent.message_type = message_type;
713                         xev.ClientMessageEvent.format = 32;
714                         xev.ClientMessageEvent.ptr1 = l0;
715                         xev.ClientMessageEvent.ptr2 = l1;
716                         xev.ClientMessageEvent.ptr3 = l2;
717                         XSendEvent(DisplayHandle, window, false, new IntPtr ((int)EventMask.NoEventMask), ref xev);
718                 }
719
720                 // For WM_LBUTTONDOWN, WM_MBUTTONDOWN, WM_RBUTTONDOWN, WM_XBUTTONDOWN
721                 //     WM_CREATE and WM_DESTROY causes
722                 void SendParentNotify(IntPtr child, Msg cause, int x, int y)
723                 {       
724                         Hwnd hwnd;
725                         
726                         if (child == IntPtr.Zero) {
727                                 return;
728                         }
729                         
730                         hwnd = Hwnd.GetObjectFromWindow (child);
731                         
732                         if (hwnd == null) {
733                                 return;
734                         }
735                         
736                         if (hwnd.Handle == IntPtr.Zero) {
737                                 return;
738                         }
739                         
740                         if (ExStyleSet ((int) hwnd.initial_ex_style, WindowExStyles.WS_EX_NOPARENTNOTIFY)) {
741                                 return;
742                         }
743                         
744                         if (hwnd.Parent == null) {
745                                 return;
746                         }
747                         
748                         if (hwnd.Parent.Handle == IntPtr.Zero) {
749                                 return;
750                         }
751
752                         if (cause == Msg.WM_CREATE || cause == Msg.WM_DESTROY) {
753                                 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), child);
754                         } else {
755                                 SendMessage(hwnd.Parent.Handle, Msg.WM_PARENTNOTIFY, Control.MakeParam((int)cause, 0), Control.MakeParam(x, y));
756                         }
757                         
758                         SendParentNotify (hwnd.Parent.Handle, cause, x, y);
759                 }
760                 
761                 bool StyleSet (int s, WindowStyles ws)
762                 {
763                         return (s & (int)ws) == (int)ws;
764                 }
765
766                 bool ExStyleSet (int ex, WindowExStyles exws)
767                 {
768                         return (ex & (int)exws) == (int)exws;
769                 }
770
771                 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd)
772                 {
773                         return TranslateClientRectangleToXClientRectangle (hwnd, Control.FromHandle (hwnd.Handle));
774                 }
775                 
776                 internal static Rectangle TranslateClientRectangleToXClientRectangle (Hwnd hwnd, Control ctrl)
777                 {
778                         /* 
779                          * If this is a form with no window manager, X is handling all the border and caption painting
780                          * so remove that from the area (since the area we set of the window here is the part of the window 
781                          * we're painting in only)
782                          */
783                         Rectangle rect = hwnd.ClientRect;
784                         Form form = ctrl as Form;
785                         CreateParams cp = null;
786
787                         if (form != null)
788                                 cp = form.GetCreateParams ();
789
790                         if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
791                                 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
792                                 Rectangle xrect = rect;
793
794                                 xrect.Y -= borders.top;
795                                 xrect.X -= borders.left;
796                                 xrect.Width += borders.left + borders.right;
797                                 xrect.Height += borders.top + borders.bottom;
798
799                                 rect = xrect;
800                         }
801                         
802                         if (rect.Width < 1 || rect.Height < 1) {
803                                 rect.Width = 1;
804                                 rect.Height = 1;
805                                 rect.X = -5;
806                                 rect.Y = -5;
807                         }
808                         
809                         return rect;
810                 }
811
812                 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp)
813                 {
814                         return TranslateWindowSizeToXWindowSize (cp, new Size (cp.Width, cp.Height));
815                 }
816
817                 internal static Size TranslateWindowSizeToXWindowSize (CreateParams cp, Size size)
818                 {
819                         /* 
820                          * If this is a form with no window manager, X is handling all the border and caption painting
821                          * so remove that from the area (since the area we set of the window here is the part of the window 
822                          * we're painting in only)
823                          */
824                         Form form = cp.control as Form;
825                         if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
826                                 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
827                                 Size xrect = size;
828
829                                 xrect.Width -= borders.left + borders.right;
830                                 xrect.Height -= borders.top + borders.bottom;
831
832                                 size = xrect;
833                         }
834                         if (size.Height == 0)
835                                 size.Height = 1;
836                         if (size.Width == 0)
837                                 size.Width = 1;
838                         return size;
839                 }
840
841                 internal static Size TranslateXWindowSizeToWindowSize (CreateParams cp, int xWidth, int xHeight)
842                 {
843                         /* 
844                          * If this is a form with no window manager, X is handling all the border and caption painting
845                          * so remove that from the area (since the area we set of the window here is the part of the window 
846                          * we're painting in only)
847                          */
848                         Size rect = new Size (xWidth, xHeight);
849                         Form form = cp.control as Form;
850                         if (form != null && (form.window_manager == null && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW))) {
851                                 Hwnd.Borders borders = Hwnd.GetBorders (cp, null);
852                                 Size xrect = rect;
853
854                                 xrect.Width += borders.left + borders.right;
855                                 xrect.Height += borders.top + borders.bottom;
856
857                                 rect = xrect;
858                         }
859                         return rect;
860                 }
861                 
862                 internal static Point GetTopLevelWindowLocation (Hwnd hwnd)
863                 {
864                         IntPtr dummy; 
865                         int x, y;
866                         Hwnd.Borders frame;
867
868                         XTranslateCoordinates (DisplayHandle, hwnd.whole_window, RootWindow, 0, 0, out x, out y, out dummy);
869                         frame = FrameExtents (hwnd.whole_window);
870
871                         x -= frame.left;
872                         y -= frame.top;
873                         
874                         return new Point (x, y);
875                 }
876                 
877                 private void DeriveStyles(int Style, int ExStyle, out FormBorderStyle border_style, out bool border_static, out TitleStyle title_style, out int caption_height, out int tool_caption_height) {
878
879                         caption_height = 0;
880                         tool_caption_height = 19;
881                         border_static = false;
882
883                         if (StyleSet (Style, WindowStyles.WS_CHILD)) {
884                                 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
885                                         border_style = FormBorderStyle.Fixed3D;
886                                 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
887                                         border_style = FormBorderStyle.Fixed3D;
888                                         border_static = true;
889                                 } else if (!StyleSet (Style, WindowStyles.WS_BORDER)) {
890                                         border_style = FormBorderStyle.None;
891                                 } else {
892                                         border_style = FormBorderStyle.FixedSingle;
893                                 }
894                                 title_style = TitleStyle.None;
895                                 
896                                 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
897                                         caption_height = 19;
898                                         if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
899                                                 title_style = TitleStyle.Tool;
900                                         } else {
901                                                 title_style = TitleStyle.Normal;
902                                         }
903                                 }
904
905                                 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_MDICHILD)) {
906                                         caption_height = 19;
907
908                                         if (StyleSet (Style, WindowStyles.WS_OVERLAPPEDWINDOW) ||
909                                             ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
910                                                 border_style = (FormBorderStyle) 0xFFFF;
911                                         } else {
912                                                 border_style = FormBorderStyle.None;
913                                         }
914                                 }
915
916                         } else {
917                                 title_style = TitleStyle.None;
918                                 if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
919                                         if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
920                                                 title_style = TitleStyle.Tool;
921                                         } else {
922                                                 title_style = TitleStyle.Normal;
923                                         }
924                                 }
925
926                                 border_style = FormBorderStyle.None;
927
928                                 if (StyleSet (Style, WindowStyles.WS_THICKFRAME)) {
929                                         if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
930                                                 border_style = FormBorderStyle.SizableToolWindow;
931                                         } else {
932                                                 border_style = FormBorderStyle.Sizable;
933                                         }
934                                 } else {
935                                         if (StyleSet (Style, WindowStyles.WS_CAPTION)) {
936                                                 if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_CLIENTEDGE)) {
937                                                         border_style = FormBorderStyle.Fixed3D;
938                                                 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_STATICEDGE)) {
939                                                         border_style = FormBorderStyle.Fixed3D;
940                                                         border_static = true;
941                                                 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
942                                                         border_style = FormBorderStyle.FixedDialog;
943                                                 } else if (ExStyleSet (ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
944                                                         border_style = FormBorderStyle.FixedToolWindow;
945                                                 } else if (StyleSet (Style, WindowStyles.WS_BORDER)) {
946                                                         border_style = FormBorderStyle.FixedSingle;
947                                                 }
948                                         } else {
949                                                 if (StyleSet (Style, WindowStyles.WS_BORDER)) {
950                                                         border_style = FormBorderStyle.FixedSingle;
951                                                 }
952                                         }
953                                 }
954                         }
955                 }
956
957                 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
958                         DeriveStyles(cp.Style, cp.ExStyle, out hwnd.border_style, out hwnd.border_static, out hwnd.title_style, out hwnd.caption_height, out hwnd.tool_caption_height);
959                 }
960
961                 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
962                         MotifWmHints            mwmHints;
963                         MotifFunctions          functions;
964                         MotifDecorations        decorations;
965                         int[]                   atoms;
966                         int                     atom_count;
967                         Rectangle               client_rect;
968                         Form                    form;
969                         IntPtr                  window_type;
970                         bool                    hide_from_taskbar;
971                         IntPtr                  transient_for_parent;
972                         
973                         // Windows we manage ourselves don't need WM window styles.
974                         if (cp.HasWindowManager && !cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
975                                 return;
976                         }
977
978                         atoms = new int[8];
979                         mwmHints = new MotifWmHints();
980                         functions = 0;
981                         decorations = 0;
982                         window_type = _NET_WM_WINDOW_TYPE_NORMAL;
983                         transient_for_parent = IntPtr.Zero;
984
985                         mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
986                         mwmHints.functions = (IntPtr)0;
987                         mwmHints.decorations = (IntPtr)0;
988
989                         form = cp.control as Form;
990
991                         if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
992                                 /* tool windows get no window manager
993                                    decorations.
994                                 */
995
996                                 /* just because the window doesn't get any decorations doesn't
997                                    mean we should disable the functions.  for instance, without
998                                    MotifFunctions.Maximize, changing the windowstate to Maximized
999                                    is ignored by metacity. */
1000                                 functions |= MotifFunctions.Move | MotifFunctions.Resize | MotifFunctions.Minimize | MotifFunctions.Maximize;
1001                         } else if (form != null && form.FormBorderStyle == FormBorderStyle.None) {
1002                                 functions |= MotifFunctions.All;
1003                         } else {
1004                                 if (StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
1005                                         functions |= MotifFunctions.Move;
1006                                         decorations |= MotifDecorations.Title | MotifDecorations.Menu;
1007                                 }
1008
1009                                 if (StyleSet (cp.Style, WindowStyles.WS_THICKFRAME)) {
1010                                         functions |= MotifFunctions.Move | MotifFunctions.Resize;
1011                                         decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
1012                                 }
1013
1014                                 if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZEBOX)) {
1015                                         functions |= MotifFunctions.Minimize;
1016                                         decorations |= MotifDecorations.Minimize;
1017                                 }
1018
1019                                 if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZEBOX)) {
1020                                         functions |= MotifFunctions.Maximize;
1021                                         decorations |= MotifDecorations.Maximize;
1022                                 }
1023
1024                                 if (StyleSet (cp.Style, WindowStyles.WS_SIZEBOX)) {
1025                                         functions |= MotifFunctions.Resize;
1026                                         decorations |= MotifDecorations.ResizeH;
1027                                 }
1028
1029                                 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_DLGMODALFRAME)) {
1030                                         decorations |= MotifDecorations.Border;
1031                                 }
1032
1033                                 if (StyleSet (cp.Style, WindowStyles.WS_BORDER)) {
1034                                         decorations |= MotifDecorations.Border;
1035                                 }
1036                         
1037                                 if (StyleSet (cp.Style, WindowStyles.WS_DLGFRAME)) {
1038                                         decorations |= MotifDecorations.Border;
1039                                 }
1040
1041                                 if (StyleSet (cp.Style, WindowStyles.WS_SYSMENU)) {
1042                                         functions |= MotifFunctions.Close;
1043                                 }
1044                                 else {
1045                                         functions &= ~(MotifFunctions.Maximize | MotifFunctions.Minimize | MotifFunctions.Close);
1046                                         decorations &= ~(MotifDecorations.Menu | MotifDecorations.Maximize | MotifDecorations.Minimize);
1047                                         if (cp.Caption == "") {
1048                                                 functions &= ~MotifFunctions.Move;
1049                                                 decorations &= ~(MotifDecorations.Title | MotifDecorations.ResizeH);
1050                                         }
1051                                 }
1052                         }
1053
1054                         if ((functions & MotifFunctions.Resize) == 0) {
1055                                 hwnd.fixed_size = true;
1056                                 Rectangle fixed_rectangle = new Rectangle (cp.X, cp.Y, cp.Width, cp.Height);
1057                                 SetWindowMinMax(hwnd.Handle, fixed_rectangle, fixed_rectangle.Size, fixed_rectangle.Size, cp);
1058                         } else {
1059                                 hwnd.fixed_size = false;
1060                         }
1061
1062                         mwmHints.functions = (IntPtr)functions;
1063                         mwmHints.decorations = (IntPtr)decorations;
1064
1065 #if debug
1066                         Console.WriteLine ("SetWMStyles ({0}, {1}) functions = {2}, decorations = {3}", hwnd, cp, functions, decorations);
1067 #endif
1068
1069                         if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
1070                                 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
1071                                 // and get those windows in front of their parents
1072                                 window_type = _NET_WM_WINDOW_TYPE_UTILITY;
1073                         } else if (form != null && form.Modal) {
1074                                 window_type = _NET_WM_WINDOW_TYPE_DIALOG;
1075                         } else {
1076                                 window_type = _NET_WM_WINDOW_TYPE_NORMAL;
1077                         }
1078                         
1079                         if (!cp.IsSet (WindowExStyles.WS_EX_APPWINDOW)) {
1080                                 hide_from_taskbar = true;
1081                         } else if (cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW) &&  form != null && form.Parent != null && !form.ShowInTaskbar) {
1082                                 hide_from_taskbar = true;
1083                         } else {
1084                                 hide_from_taskbar = false;
1085                         }
1086
1087                         if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
1088                                 if (form != null && !hwnd.reparented) {
1089                                         if (form.Owner != null && form.Owner.Handle != IntPtr.Zero) {
1090                                                 Hwnd owner_hwnd = Hwnd.ObjectFromHandle (form.Owner.Handle);
1091                                                 if (owner_hwnd != null)
1092                                                         transient_for_parent = owner_hwnd.whole_window;
1093                                         }
1094                                 }
1095                         } 
1096                         if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
1097                                 transient_for_parent = hwnd.parent.whole_window;
1098                         }
1099                         
1100                         FormWindowState current_state = GetWindowState (hwnd.Handle);
1101                         if (current_state == (FormWindowState)(-1))
1102                                 current_state = FormWindowState.Normal;
1103
1104                         client_rect = TranslateClientRectangleToXClientRectangle (hwnd);
1105
1106                         lock (XlibLock) {
1107                                 atom_count = 0;
1108
1109                                 atoms [0] = window_type.ToInt32 ();
1110                                 XChangeProperty (DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
1111
1112                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
1113
1114                                 if (transient_for_parent != IntPtr.Zero) {
1115                                         XSetTransientForHint (DisplayHandle, hwnd.whole_window, transient_for_parent);
1116                                 }
1117
1118                                 MoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
1119
1120                                 if (hide_from_taskbar) {
1121                                         /* this line keeps the window from showing up in gnome's taskbar */
1122                                         atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
1123                                 }
1124                                 /* we need to add these atoms in the
1125                                  * event we're maximized, since we're
1126                                  * replacing the existing
1127                                  * _NET_WM_STATE here.  If we don't
1128                                  * add them, future calls to
1129                                  * GetWindowState will return Normal
1130                                  * for a window which is maximized. */
1131                                 if (current_state == FormWindowState.Maximized) {
1132                                         atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_HORZ.ToInt32();
1133                                         atoms[atom_count++] = _NET_WM_STATE_MAXIMIZED_VERT.ToInt32();
1134                                 }
1135                                 
1136                                 if (form != null && form.Modal) {
1137                                         atoms[atom_count++] = _NET_WM_STATE_MODAL.ToInt32 ();
1138                                 }
1139                                 
1140                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
1141
1142                                 atom_count = 0;
1143                                 IntPtr[] atom_ptrs = new IntPtr[2];
1144                                 atom_ptrs[atom_count++] = WM_DELETE_WINDOW;
1145                                 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_CONTEXTHELP)) {
1146                                         atom_ptrs[atom_count++] = _NET_WM_CONTEXT_HELP;
1147                                 }
1148
1149                                 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atom_ptrs, atom_count);
1150                         }
1151                 }
1152
1153                 private void SetIcon(Hwnd hwnd, Icon icon)
1154                 {
1155                         if (icon == null) {
1156                                 // XXX
1157
1158                                 // This really needs to do whatever it
1159                                 // takes to remove the window manager
1160                                 // menu, not just delete the ICON
1161                                 // property.  This will cause metacity
1162                                 // to use the "no icon set" icon, and
1163                                 // we'll still have an icon.
1164                                 XDeleteProperty (DisplayHandle, hwnd.whole_window, _NET_WM_ICON);
1165                         }
1166                         else {
1167                                 Bitmap          bitmap;
1168                                 int             size;
1169                                 IntPtr[]        data;
1170                                 int             index;
1171
1172                                 bitmap = icon.ToBitmap();
1173                                 index = 0;
1174                                 size = bitmap.Width * bitmap.Height + 2;
1175                                 data = new IntPtr[size];
1176
1177                                 data[index++] = (IntPtr)bitmap.Width;
1178                                 data[index++] = (IntPtr)bitmap.Height;
1179
1180                                 for (int y = 0; y < bitmap.Height; y++) {
1181                                         for (int x = 0; x < bitmap.Width; x++) {
1182                                                 data[index++] = (IntPtr)bitmap.GetPixel (x, y).ToArgb ();
1183                                         }
1184                                 }
1185
1186                                 XChangeProperty (DisplayHandle, hwnd.whole_window,
1187                                                  _NET_WM_ICON, (IntPtr)Atom.XA_CARDINAL, 32,
1188                                                  PropertyMode.Replace, data, size);
1189                         }
1190                 }
1191
1192                 private void WakeupMain () {
1193                         wake.Send (new byte [] { 0xFF });
1194                 }
1195
1196                 private XEventQueue ThreadQueue(Thread thread) {
1197                         XEventQueue     queue;
1198
1199                         queue = (XEventQueue)MessageQueues[thread];
1200                         if (queue == null) {
1201                                 queue = new XEventQueue(thread);
1202                                 MessageQueues[thread] = queue;
1203                         }
1204
1205                         return queue;
1206                 }
1207
1208                 private void TranslatePropertyToClipboard(IntPtr property) {
1209                         IntPtr                  actual_atom;
1210                         int                     actual_format;
1211                         IntPtr                  nitems;
1212                         IntPtr                  bytes_after;
1213                         IntPtr                  prop = IntPtr.Zero;
1214
1215                         Clipboard.Item = null;
1216
1217                         XGetWindowProperty(DisplayHandle, FosterParent, property, IntPtr.Zero, new IntPtr (0x7fffffff), true, (IntPtr)Atom.AnyPropertyType, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1218
1219                         if ((long)nitems > 0) {
1220                                 if (property == (IntPtr)Atom.XA_STRING) {
1221                                         Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1222                                 } else if (property == (IntPtr)Atom.XA_BITMAP) {
1223                                         // FIXME - convert bitmap to image
1224                                 } else if (property == (IntPtr)Atom.XA_PIXMAP) {
1225                                         // FIXME - convert pixmap to image
1226                                 } else if (property == OEMTEXT) {
1227                                         Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1228                                 } else if (property == UNICODETEXT) {
1229                                         Clipboard.Item = Marshal.PtrToStringAnsi(prop);
1230                                 }
1231
1232                                 XFree(prop);
1233                         }
1234                 }
1235
1236                 private void AddExpose (Hwnd hwnd, bool client, int x, int y, int width, int height) {
1237                         // Don't waste time
1238                         if ((hwnd == null) || (x > hwnd.Width) || (y > hwnd.Height) || ((x + width) < 0) || ((y + height) < 0)) {
1239                                 return;
1240                         }
1241
1242                         // Keep the invalid area as small as needed
1243                         if ((x + width) > hwnd.width) {
1244                                 width = hwnd.width - x;
1245                         }
1246
1247                         if ((y + height) > hwnd.height) {
1248                                 height = hwnd.height - y;
1249                         }
1250
1251                         if (client) {
1252                                 hwnd.AddInvalidArea(x, y, width, height);
1253                                 if (!hwnd.expose_pending) {
1254                                         if (!hwnd.nc_expose_pending) {
1255                                                 hwnd.Queue.Paint.Enqueue(hwnd);
1256                                         }
1257                                         hwnd.expose_pending = true;
1258                                 }
1259                         } else {
1260                                 hwnd.AddNcInvalidArea (x, y, width, height);
1261                                 
1262                                 if (!hwnd.nc_expose_pending) {
1263                                         if (!hwnd.expose_pending) {
1264                                                 hwnd.Queue.Paint.Enqueue(hwnd);
1265                                         }
1266                                         hwnd.nc_expose_pending = true;
1267                                 }
1268                         }
1269                 }
1270
1271                 private static Hwnd.Borders FrameExtents (IntPtr window)
1272                 {
1273                         IntPtr actual_atom;
1274                         int actual_format;
1275                         IntPtr nitems;
1276                         IntPtr bytes_after;
1277                         IntPtr prop = IntPtr.Zero;
1278                         Hwnd.Borders rect = new Hwnd.Borders ();
1279
1280                         XGetWindowProperty (DisplayHandle, window, _NET_FRAME_EXTENTS, IntPtr.Zero, new IntPtr (16), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1281                         if (prop != IntPtr.Zero) {
1282                                 if (nitems.ToInt32 () == 4) {
1283                                         rect.left = Marshal.ReadInt32 (prop, 0);
1284                                         rect.right = Marshal.ReadInt32 (prop, IntPtr.Size);
1285                                         rect.top = Marshal.ReadInt32 (prop, 2 * IntPtr.Size);
1286                                         rect.bottom = Marshal.ReadInt32 (prop, 3 * IntPtr.Size);
1287                                 }
1288                                 XFree (prop);
1289                         }
1290                         
1291                         return rect;
1292                 }
1293
1294                 private void AddConfigureNotify (XEvent xevent) {
1295                         Hwnd    hwnd;
1296
1297                         hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
1298
1299                         // Don't waste time
1300                         if (hwnd == null || hwnd.zombie) {
1301                                 return;
1302                         }
1303                         if ((xevent.ConfigureEvent.window == hwnd.whole_window)/* && (xevent.ConfigureEvent.window == xevent.ConfigureEvent.xevent)*/) {
1304                                 if (hwnd.parent == null) {
1305                                         // The location given by the event is not reliable between different wm's, 
1306                                         // so use an alternative way of getting it.
1307                                         Point location = GetTopLevelWindowLocation (hwnd);
1308                                         hwnd.x = location.X;
1309                                         hwnd.y = location.Y;
1310                                 }
1311
1312                                 // XXX this sucks.  this isn't thread safe
1313                                 Control ctrl = Control.FromHandle (hwnd.Handle);
1314                                 Size TranslatedSize;
1315                                 if (ctrl != null) {
1316                                         TranslatedSize = TranslateXWindowSizeToWindowSize (ctrl.GetCreateParams (), xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1317                                 } else {
1318                                         TranslatedSize = new Size (xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
1319                                 }
1320                                 hwnd.width = TranslatedSize.Width;
1321                                 hwnd.height = TranslatedSize.Height;
1322                                 hwnd.ClientRect = Rectangle.Empty;
1323
1324 #if debug
1325                                 Console.WriteLine ("AddConfigureNotify (hwnd.Handle = {1}, final hwnd.rect = {0}, reported rect={2})", new Rectangle (hwnd.x, hwnd.y, hwnd.width, hwnd.height), hwnd.Handle, new Rectangle (xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.width));
1326 #endif                  
1327                                 lock (hwnd.configure_lock) {
1328                                         if (!hwnd.configure_pending) {
1329                                                 hwnd.Queue.EnqueueLocked (xevent);
1330                                                 hwnd.configure_pending = true;
1331                                         }
1332                                 }
1333                         }
1334                         // We drop configure events for Client windows
1335                 }
1336
1337                 private void ShowCaret() {
1338                         if ((Caret.gc == IntPtr.Zero) || Caret.On) {
1339                                 return;
1340                         }
1341                         Caret.On = true;
1342
1343                         lock (XlibLock) {
1344                                 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1345                         }
1346                 }
1347
1348                 private void HideCaret() {
1349                         if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
1350                                 return;
1351                         }
1352                         Caret.On = false;
1353
1354                         lock (XlibLock) {
1355                                 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1356                         }
1357                 }
1358
1359                 private int NextTimeout (ArrayList timers, DateTime now) {
1360                         int timeout = 0; 
1361
1362                         foreach (Timer timer in timers) {
1363                                 int next = (int) (timer.Expires - now).TotalMilliseconds;
1364                                 if (next < 0) {
1365                                         return 0; // Have a timer that has already expired
1366                                 }
1367
1368                                 if (next < timeout) {
1369                                         timeout = next;
1370                                 }
1371                         }
1372                         if (timeout < Timer.Minimum) {
1373                                 timeout = Timer.Minimum;
1374                         }
1375
1376                         if (timeout > 1000)
1377                                 timeout = 1000;
1378                         return timeout;
1379                 }
1380
1381                 private void CheckTimers (ArrayList timers, DateTime now) {
1382                         int count;
1383
1384                         count = timers.Count;
1385
1386                         if (count == 0)
1387                                 return;
1388
1389                         for (int i = 0; i < timers.Count; i++) {
1390                                 Timer timer;
1391
1392                                 timer = (Timer) timers [i];
1393
1394                                 if (timer.Enabled && timer.Expires <= now && !timer.Busy) {
1395                                         timer.Busy = true;
1396                                         timer.Update (now);
1397                                         timer.FireTick ();
1398                                         timer.Busy = false;
1399                                 }
1400                         }
1401                 }
1402
1403                 private void WaitForHwndMessage (Hwnd hwnd, Msg message) {
1404                         MSG msg = new MSG ();
1405                         XEventQueue queue;
1406
1407                         queue = ThreadQueue(Thread.CurrentThread);
1408
1409                         queue.DispatchIdle = false;
1410
1411                         bool done = false;
1412                         do {
1413                                 if (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1414                                         if ((Msg)msg.message == Msg.WM_QUIT) {
1415                                                 PostQuitMessage (0);
1416                                                 done = true;
1417                                         }
1418                                         else {
1419                                                 if (msg.hwnd == hwnd.Handle) {
1420                                                         if ((Msg)msg.message == message)
1421                                                                 break;
1422                                                         else if ((Msg)msg.message == Msg.WM_DESTROY)
1423                                                                 done = true;
1424                                                 }
1425
1426                                                 TranslateMessage (ref msg);
1427                                                 DispatchMessage (ref msg);
1428                                         }
1429                                 }
1430                         } while (!done);
1431
1432                         queue.DispatchIdle = true;
1433
1434                 }
1435
1436                 private void MapWindow(Hwnd hwnd, WindowType windows) {
1437                         if (!hwnd.mapped) {
1438                                 Form f = Control.FromHandle(hwnd.Handle) as Form;
1439                                 if (f != null) {
1440                                         if (f.WindowState == FormWindowState.Normal) {
1441                                                 f.waiting_showwindow = true;
1442                                                 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
1443                                         }
1444                                 }
1445
1446                                 // it's possible that our Hwnd is no
1447                                 // longer valid after making that
1448                                 // SendMessage call, so check here.
1449                                 if (hwnd.zombie)
1450                                         return;
1451
1452                                 if ((windows & WindowType.Whole) != 0) {
1453                                         XMapWindow(DisplayHandle, hwnd.whole_window);
1454                                 }
1455                                 if ((windows & WindowType.Client) != 0) {
1456                                         XMapWindow(DisplayHandle, hwnd.client_window);
1457                                 }
1458
1459                                 hwnd.mapped = true;
1460
1461                                 if (f != null && f.waiting_showwindow)
1462                                         WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1463                         }
1464                 }
1465
1466                 private void UnmapWindow(Hwnd hwnd, WindowType windows) {
1467                         if (hwnd.mapped) {
1468                                 Form f = null;
1469                                 if (Control.FromHandle(hwnd.Handle) is Form) {
1470                                         f = Control.FromHandle(hwnd.Handle) as Form;
1471                                         if (f.WindowState == FormWindowState.Normal) {
1472                                                 f.waiting_showwindow = true;
1473                                                 SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, IntPtr.Zero, IntPtr.Zero);
1474                                         }
1475                                 }
1476
1477                                 // it's possible that our Hwnd is no
1478                                 // longer valid after making that
1479                                 // SendMessage call, so check here.
1480                                 // FIXME: it is likely wrong, as it has already sent WM_SHOWWINDOW
1481                                 if (hwnd.zombie)
1482                                         return;
1483
1484                                 if ((windows & WindowType.Client) != 0) {
1485                                         XUnmapWindow(DisplayHandle, hwnd.client_window);
1486                                 }
1487                                 if ((windows & WindowType.Whole) != 0) {
1488                                         XUnmapWindow(DisplayHandle, hwnd.whole_window);
1489                                 }
1490
1491                                 hwnd.mapped = false;
1492
1493                                 if (f != null && f.waiting_showwindow)
1494                                         WaitForHwndMessage (hwnd, Msg.WM_SHOWWINDOW);
1495                         }
1496                 }
1497
1498                 private void UpdateMessageQueue (XEventQueue queue) {
1499                         DateTime        now;
1500                         int             pending;
1501                         Hwnd            hwnd;
1502
1503                         now = DateTime.UtcNow;
1504
1505                         lock (XlibLock) {
1506                                 pending = XPending (DisplayHandle);
1507                         }
1508
1509                         if (pending == 0) {
1510                                 if ((queue == null || queue.DispatchIdle) && Idle != null) {
1511                                         Idle (this, EventArgs.Empty);
1512                                 }
1513
1514                                 lock (XlibLock) {
1515                                         pending = XPending (DisplayHandle);
1516                                 }
1517                         }
1518
1519                         if (pending == 0) {
1520                                 int     timeout = 0;
1521
1522                                 if (queue != null) {
1523                                         if (queue.Paint.Count > 0)
1524                                                 return;
1525
1526                                         timeout = NextTimeout (queue.timer_list, now);
1527                                 }
1528
1529                                 if (timeout > 0) {
1530                                         #if __MonoCS__
1531                                         int length = pollfds.Length - 1;
1532                                         lock (wake_waiting_lock) {
1533                                                 if (wake_waiting == false) {
1534                                                         length ++;
1535                                                         wake_waiting = true;
1536                                                 }
1537                                         }
1538
1539                                         Syscall.poll (pollfds, (uint)length, timeout);
1540                                         // Clean out buffer, so we're not busy-looping on the same data
1541                                         if (length == pollfds.Length) {
1542                                                 if (pollfds[1].revents != 0)
1543                                                         wake_receive.Receive(network_buffer, 0, 1, SocketFlags.None);
1544                                                 lock (wake_waiting_lock) {
1545                                                         wake_waiting = false;
1546                                                 }
1547                                         }
1548                                         #endif
1549                                         lock (XlibLock) {
1550                                                 pending = XPending (DisplayHandle);
1551                                         }
1552                                 }
1553                         }
1554
1555                         if (queue != null)
1556                                 CheckTimers (queue.timer_list, now);
1557
1558                         while (true) {
1559                                 XEvent xevent = new XEvent ();
1560
1561                                 lock (XlibLock) {
1562                                         if (XPending (DisplayHandle) == 0)
1563                                                 break;
1564
1565                                         XNextEvent (DisplayHandle, ref xevent);
1566
1567                                         if (xevent.AnyEvent.type == XEventName.KeyPress ||
1568                                             xevent.AnyEvent.type == XEventName.KeyRelease) {
1569                                                 // PreFilter() handles "shift key state updates.
1570                                                 Keyboard.PreFilter (xevent);
1571                                                 if (XFilterEvent (ref xevent, Keyboard.ClientWindow)) {
1572                                                         // probably here we could raise WM_IME_KEYDOWN and
1573                                                         // WM_IME_KEYUP, but I'm not sure it is worthy.
1574                                                         continue;
1575                                                 }
1576                                         }
1577                                         else if (XFilterEvent (ref xevent, IntPtr.Zero))
1578                                                 continue;
1579                                 }
1580
1581                                 hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1582                                 if (hwnd == null)
1583                                         continue;
1584
1585 #if debug
1586                                 Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1587 #endif
1588                                 switch (xevent.type) {
1589                                 case XEventName.Expose:
1590                                         AddExpose (hwnd, xevent.ExposeEvent.window == hwnd.ClientWindow, xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
1591                                         break;
1592
1593                                 case XEventName.SelectionClear: {
1594                                         // Should we do something?
1595                                         break;
1596                                 }
1597
1598                                 case XEventName.SelectionRequest: {
1599                                         if (Dnd.HandleSelectionRequestEvent (ref xevent))
1600                                                 break;
1601                                         XEvent sel_event;
1602
1603                                         sel_event = new XEvent();
1604                                         sel_event.SelectionEvent.type = XEventName.SelectionNotify;
1605                                         sel_event.SelectionEvent.send_event = true;
1606                                         sel_event.SelectionEvent.display = DisplayHandle;
1607                                         sel_event.SelectionEvent.selection = xevent.SelectionRequestEvent.selection;
1608                                         sel_event.SelectionEvent.target = xevent.SelectionRequestEvent.target;
1609                                         sel_event.SelectionEvent.requestor = xevent.SelectionRequestEvent.requestor;
1610                                         sel_event.SelectionEvent.time = xevent.SelectionRequestEvent.time;
1611                                         sel_event.SelectionEvent.property = IntPtr.Zero;
1612
1613                                         // Seems that some apps support asking for supported types
1614                                         if (xevent.SelectionEvent.target == TARGETS) {
1615                                                 int[]   atoms;
1616                                                 int     atom_count;
1617
1618                                                 atoms = new int[5];
1619                                                 atom_count = 0;
1620
1621                                                 if (Clipboard.Item is String) {
1622                                                         atoms[atom_count++] = (int)Atom.XA_STRING;
1623                                                         atoms[atom_count++] = (int)OEMTEXT;
1624                                                         atoms[atom_count++] = (int)UNICODETEXT;
1625                                                 } else if (Clipboard.Item is Image) {
1626                                                         atoms[atom_count++] = (int)Atom.XA_PIXMAP;
1627                                                         atoms[atom_count++] = (int)Atom.XA_BITMAP;
1628                                                 } else {
1629                                                         // FIXME - handle other types
1630                                                 }
1631
1632                                                 XChangeProperty(DisplayHandle, xevent.SelectionEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 32, PropertyMode.Replace, atoms, atom_count);
1633                                         } else if (Clipboard.Item is string) {
1634                                                 IntPtr  buffer;
1635                                                 int     buflen;
1636
1637                                                 buflen = 0;
1638
1639                                                 if (xevent.SelectionRequestEvent.target == (IntPtr)Atom.XA_STRING) {
1640                                                         Byte[] bytes;
1641
1642                                                         bytes = new ASCIIEncoding().GetBytes((string)Clipboard.Item);
1643                                                         buffer = Marshal.AllocHGlobal(bytes.Length);
1644                                                         buflen = bytes.Length;
1645
1646                                                         for (int i = 0; i < buflen; i++) {
1647                                                                 Marshal.WriteByte(buffer, i, bytes[i]);
1648                                                         }
1649                                                 } else if (xevent.SelectionRequestEvent.target == OEMTEXT) {
1650                                                         // FIXME - this should encode into ISO2022
1651                                                         buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1652                                                         while (Marshal.ReadByte(buffer, buflen) != 0) {
1653                                                                 buflen++;
1654                                                         }
1655                                                 } else if (xevent.SelectionRequestEvent.target == UNICODETEXT) {
1656                                                         buffer = Marshal.StringToHGlobalAnsi((string)Clipboard.Item);
1657                                                         while (Marshal.ReadByte(buffer, buflen) != 0) {
1658                                                                 buflen++;
1659                                                         }
1660                                                 } else {
1661                                                         buffer = IntPtr.Zero;
1662                                                 }
1663
1664                                                 if (buffer != IntPtr.Zero) {
1665                                                         XChangeProperty(DisplayHandle, xevent.SelectionRequestEvent.requestor, (IntPtr)xevent.SelectionRequestEvent.property, (IntPtr)xevent.SelectionRequestEvent.target, 8, PropertyMode.Replace, buffer, buflen);
1666                                                         sel_event.SelectionEvent.property = xevent.SelectionRequestEvent.property;
1667                                                         Marshal.FreeHGlobal(buffer);
1668                                                 }
1669                                         } else if (Clipboard.Item is Image) {
1670                                                 if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1671                                                         // FIXME - convert image and store as property
1672                                                 } else if (xevent.SelectionEvent.target == (IntPtr)Atom.XA_PIXMAP) {
1673                                                         // FIXME - convert image and store as property
1674                                                 }
1675                                         }
1676
1677                                         XSendEvent(DisplayHandle, xevent.SelectionRequestEvent.requestor, false, new IntPtr ((int)EventMask.NoEventMask), ref sel_event);
1678                                         break;
1679                                 }
1680
1681                                 case XEventName.SelectionNotify: {
1682                                         if (Clipboard.Enumerating) {
1683                                                 Clipboard.Enumerating = false;
1684                                                 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1685                                                         XDeleteProperty(DisplayHandle, FosterParent, (IntPtr)xevent.SelectionEvent.property);
1686                                                         if (!Clipboard.Formats.Contains(xevent.SelectionEvent.property)) {
1687                                                                 Clipboard.Formats.Add(xevent.SelectionEvent.property);
1688                                                                 #if DriverDebugExtra
1689                                                                 Console.WriteLine("Got supported clipboard atom format: {0}", xevent.SelectionEvent.property);
1690                                                                 #endif
1691                                                         }
1692                                                 }
1693                                         } else if (Clipboard.Retrieving) {
1694                                                 Clipboard.Retrieving = false;
1695                                                 if (xevent.SelectionEvent.property != IntPtr.Zero) {
1696                                                         TranslatePropertyToClipboard(xevent.SelectionEvent.property);
1697                                                 } else {
1698                                                         Clipboard.Item = null;
1699                                                 }
1700                                         } else {
1701                                                 Dnd.HandleSelectionNotifyEvent (ref xevent);
1702                                         }
1703                                         break;
1704                                 }
1705
1706                                 case XEventName.KeyRelease:
1707                                         if (!detectable_key_auto_repeat && XPending (DisplayHandle) != 0) {
1708                                                 XEvent nextevent = new XEvent ();
1709
1710                                                 XPeekEvent (DisplayHandle, ref nextevent);
1711
1712                                                 if (nextevent.type == XEventName.KeyPress &&
1713                                                     nextevent.KeyEvent.keycode == xevent.KeyEvent.keycode &&
1714                                                     nextevent.KeyEvent.time == xevent.KeyEvent.time) {
1715                                                         continue;
1716                                                 }
1717                                         }
1718                                         goto case XEventName.KeyPress;
1719                                         
1720                                 case XEventName.MotionNotify: {
1721                                         XEvent peek;
1722
1723                                         /* we can't do motion compression across threads, so just punt if we don't match up */
1724                                         if (Thread.CurrentThread == hwnd.Queue.Thread && hwnd.Queue.Count > 0) {
1725                                                 peek = hwnd.Queue.Peek();
1726                                                 if (peek.AnyEvent.type == XEventName.MotionNotify) {
1727                                                         continue;
1728                                                 }
1729                                         }
1730                                         goto case XEventName.KeyPress;
1731                                 }
1732
1733                                 case XEventName.KeyPress:
1734                                         hwnd.Queue.EnqueueLocked (xevent);
1735                                         /* Process KeyPresses immediately. Otherwise multiple Compose messages as a result of a
1736                                          * single physical keypress are not processed correctly */
1737                                         return;
1738                                 case XEventName.ButtonPress:
1739                                 case XEventName.ButtonRelease:
1740                                 case XEventName.EnterNotify:
1741                                 case XEventName.LeaveNotify:
1742                                 case XEventName.CreateNotify:
1743                                 case XEventName.DestroyNotify:
1744                                 case XEventName.FocusIn:
1745                                 case XEventName.FocusOut:
1746                                 case XEventName.ClientMessage:
1747                                 case XEventName.ReparentNotify:
1748                                 case XEventName.MapNotify:
1749                                 case XEventName.UnmapNotify:
1750                                         hwnd.Queue.EnqueueLocked (xevent);
1751                                         break;
1752
1753                                 case XEventName.ConfigureNotify:
1754                                         AddConfigureNotify(xevent);
1755                                         break;
1756
1757                                 case XEventName.PropertyNotify:
1758 #if debug
1759                                         Console.WriteLine ("UpdateMessageQueue (), got Event: {0}", xevent.ToString ());
1760 #endif
1761                                         if (xevent.PropertyEvent.atom == _NET_ACTIVE_WINDOW) {
1762                                                 IntPtr  actual_atom;
1763                                                 int     actual_format;
1764                                                 IntPtr  nitems;
1765                                                 IntPtr  bytes_after;
1766                                                 IntPtr  prop = IntPtr.Zero;
1767                                                 IntPtr  prev_active;
1768
1769                                                 prev_active = ActiveWindow;
1770                                                 XGetWindowProperty(DisplayHandle, RootWindow, _NET_ACTIVE_WINDOW, IntPtr.Zero, new IntPtr (1), false, (IntPtr)Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1771                                                 if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
1772                                                         ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
1773                                                         XFree(prop);
1774
1775                                                         if (prev_active != ActiveWindow) {
1776                                                                 if (prev_active != IntPtr.Zero) {
1777                                                                         PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1778                                                                 }
1779                                                                 if (ActiveWindow != IntPtr.Zero) {
1780                                                                         PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
1781                                                                 }
1782                                                         }
1783                                                         if (ModalWindows.Count == 0) {
1784                                                                 break;
1785                                                         } else {
1786                                                                 // Modality handling, if we are modal and the new active window is one
1787                                                                 // of ours but not the modal one, switch back to the modal window
1788
1789                                                                 if (NativeWindow.FromHandle(ActiveWindow) != null) {
1790                                                                         if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
1791                                                                                 Activate((IntPtr)ModalWindows.Peek());
1792                                                                         }
1793                                                                 }
1794                                                                 break;
1795                                                         }
1796                                                 }
1797                                         }
1798                                         else if (xevent.PropertyEvent.atom == _NET_WM_STATE) {
1799                                                 // invalidate our cache - we'll query again the next time someone does GetWindowState.
1800                                                 hwnd.cached_window_state = (FormWindowState)(-1);
1801                                                 PostMessage (hwnd.Handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
1802                                         }
1803                                         break;
1804
1805                                 }
1806                         }
1807                 }
1808
1809                 private IntPtr GetMousewParam(int Delta) {
1810                         int     result = 0;
1811
1812                         if ((MouseState & MouseButtons.Left) != 0) {
1813                                 result |= (int)MsgButtons.MK_LBUTTON;
1814                         }
1815
1816                         if ((MouseState & MouseButtons.Middle) != 0) {
1817                                 result |= (int)MsgButtons.MK_MBUTTON;
1818                         }
1819
1820                         if ((MouseState & MouseButtons.Right) != 0) {
1821                                 result |= (int)MsgButtons.MK_RBUTTON;
1822                         }
1823
1824                         Keys mods = ModifierKeys;
1825                         if ((mods & Keys.Control) != 0) {
1826                                 result |= (int)MsgButtons.MK_CONTROL;
1827                         }
1828
1829                         if ((mods & Keys.Shift) != 0) {
1830                                 result |= (int)MsgButtons.MK_SHIFT;
1831                         }
1832
1833                         result |= Delta << 16;
1834
1835                         return (IntPtr)result;
1836                 }
1837                 private IntPtr XGetParent(IntPtr handle) {
1838                         IntPtr  Root;
1839                         IntPtr  Parent;
1840                         IntPtr  Children;
1841                         int     ChildCount;
1842
1843                         lock (XlibLock) {
1844                                 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
1845                         }
1846
1847                         if (Children!=IntPtr.Zero) {
1848                                 lock (XlibLock) {
1849                                         XFree(Children);
1850                                 }
1851                         }
1852                         return Parent;
1853                 }
1854
1855                 private int HandleError (IntPtr display, ref XErrorEvent error_event)
1856                 {
1857                         // we need to workaround a problem with the
1858                         // ordering of destruction of Drawables and
1859                         // Pictures that exists between cairo and
1860                         // RENDER on the server.
1861                         if (error_event.request_code == (XRequest)render_major_opcode
1862                             && error_event.minor_code == 7 /* X_RenderFreePicture from render.h */
1863                             && error_event.error_code == render_first_error + 1 /* BadPicture from render.h */) {
1864                                 return 0;
1865                         }
1866
1867                         if (ErrorExceptions) {
1868                                 XUngrabPointer (display, IntPtr.Zero);
1869                                 throw new XException (error_event.display, error_event.resourceid,
1870                                                       error_event.serial, error_event.error_code,
1871                                                       error_event.request_code, error_event.minor_code);
1872                         } else {
1873                                 Console.WriteLine("X11 Error encountered: {0}{1}\n",
1874                                                   XException.GetMessage (error_event.display, error_event.resourceid,
1875                                                                          error_event.serial, error_event.error_code,
1876                                                                          error_event.request_code, error_event.minor_code),
1877                                                   Environment.StackTrace);
1878                         }
1879                         return 0;
1880                 }
1881
1882                 private void AccumulateDestroyedHandles (Control c, ArrayList list)
1883                 {
1884                         if (c != null) {
1885                                 Control[] controls = c.Controls.GetAllControls ();
1886
1887                                 if (c.IsHandleCreated && !c.IsDisposed) {
1888                                         Hwnd hwnd = Hwnd.ObjectFromHandle(c.Handle);
1889
1890                                         #if DriverDebug || DriverDebugDestroy
1891                                         Console.WriteLine (" + adding {0} to the list of zombie windows", XplatUI.Window (hwnd.Handle));
1892                                         Console.WriteLine (" + parent X window is {0:X}", XGetParent (hwnd.whole_window).ToInt32());
1893                                         #endif
1894
1895                                         list.Add (hwnd);
1896                                         CleanupCachedWindows (hwnd);
1897                                 }
1898
1899                                 for (int  i = 0; i < controls.Length; i ++) {
1900                                         AccumulateDestroyedHandles (controls[i], list);
1901                                 }
1902                         }
1903                         
1904                 }
1905
1906                 void CleanupCachedWindows (Hwnd hwnd)
1907                 {
1908                         if (ActiveWindow == hwnd.Handle) {
1909                                 SendMessage(hwnd.client_window, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
1910                                 ActiveWindow = IntPtr.Zero;
1911                         }
1912
1913                         if (FocusWindow == hwnd.Handle) {
1914                                 SendMessage(hwnd.client_window, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
1915                                 FocusWindow = IntPtr.Zero;
1916                         }
1917
1918                         if (Grab.Hwnd == hwnd.Handle) {
1919                                 Grab.Hwnd = IntPtr.Zero;
1920                                 Grab.Confined = false;
1921                         }
1922
1923                         DestroyCaret (hwnd.Handle);
1924                 }
1925
1926                 private void PerformNCCalc(Hwnd hwnd) {
1927                         XplatUIWin32.NCCALCSIZE_PARAMS  ncp;
1928                         IntPtr                          ptr;
1929                         Rectangle                       rect;
1930
1931                         rect = new Rectangle (0, 0, hwnd.Width, hwnd.Height);
1932
1933                         ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1934                         ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1935
1936                         ncp.rgrc1.left = rect.Left;
1937                         ncp.rgrc1.top = rect.Top;
1938                         ncp.rgrc1.right = rect.Right;
1939                         ncp.rgrc1.bottom = rect.Bottom;
1940
1941                         Marshal.StructureToPtr(ncp, ptr, true);
1942                         NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1943                         ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1944                         Marshal.FreeHGlobal(ptr);
1945
1946
1947                         rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1948                         hwnd.ClientRect = rect;
1949                 
1950                         rect = TranslateClientRectangleToXClientRectangle (hwnd);
1951
1952                         if (hwnd.visible) {
1953                                 MoveResizeWindow (DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1954                         }
1955
1956                         AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
1957                 }
1958                 #endregion      // Private Methods
1959
1960                 #region Callbacks
1961                 private void MouseHover(object sender, EventArgs e) {
1962                         XEvent  xevent;
1963                         Hwnd    hwnd;
1964
1965                         HoverState.Timer.Enabled = false;
1966
1967                         if (HoverState.Window != IntPtr.Zero) {
1968                                 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1969                                 if (hwnd != null) {
1970                                         xevent = new XEvent ();
1971
1972                                         xevent.type = XEventName.ClientMessage;
1973                                         xevent.ClientMessageEvent.display = DisplayHandle;
1974                                         xevent.ClientMessageEvent.window = HoverState.Window;
1975                                         xevent.ClientMessageEvent.message_type = HoverState.Atom;
1976                                         xevent.ClientMessageEvent.format = 32;
1977                                         xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1978
1979                                         hwnd.Queue.EnqueueLocked (xevent);
1980
1981                                         WakeupMain ();
1982                                 }
1983                         }
1984                 }
1985
1986                 private void CaretCallback(object sender, EventArgs e) {
1987                         if (Caret.Paused) {
1988                                 return;
1989                         }
1990                         Caret.On = !Caret.On;
1991
1992                         XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1993                 }
1994                 #endregion      // Callbacks
1995
1996                 #region Public Properties
1997
1998                 internal override int CaptionHeight {
1999                         get {
2000                                 return 19;
2001                         }
2002                 }
2003
2004                 internal override  Size CursorSize {
2005                         get {
2006                                 int     x;
2007                                 int     y;
2008
2009                                 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
2010                                         return new Size(x, y);
2011                                 } else {
2012                                         return new Size(16, 16);
2013                                 }
2014                         }
2015                 } 
2016
2017                 internal override  bool DragFullWindows {
2018                         get {
2019                                 return true;
2020                         }
2021                 } 
2022
2023                 internal override  Size DragSize {
2024                         get {
2025                                 return new Size(4, 4);
2026                         }
2027                 }
2028
2029                 internal override  Size FrameBorderSize { 
2030                         get {
2031                                 return new Size (4, 4);
2032                         }
2033                 }
2034
2035                 internal override  Size IconSize {
2036                         get {
2037                                 IntPtr          list;
2038                                 XIconSize       size;
2039                                 int             count;
2040
2041                                 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2042                                         long            current;
2043                                         int             largest;
2044
2045                                         current = (long)list;
2046                                         largest = 0;
2047
2048                                         size = new XIconSize();
2049
2050                                         for (int i = 0; i < count; i++) {
2051                                                 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2052                                                 current += Marshal.SizeOf(size);
2053
2054                                                 // Look for our preferred size
2055                                                 if (size.min_width == 32) {
2056                                                         XFree(list);
2057                                                         return new Size(32, 32);
2058                                                 }
2059
2060                                                 if (size.max_width == 32) {
2061                                                         XFree(list);
2062                                                         return new Size(32, 32);
2063                                                 }
2064
2065                                                 if (size.min_width < 32 && size.max_width > 32) {
2066                                                         int     x;
2067
2068                                                         // check if we can fit one
2069                                                         x = size.min_width;
2070                                                         while (x < size.max_width) {
2071                                                                 x += size.width_inc;
2072                                                                 if (x == 32) {
2073                                                                         XFree(list);
2074                                                                         return new Size(32, 32);
2075                                                                 }
2076                                                         }
2077                                                 }
2078
2079                                                 if (largest < size.max_width) {
2080                                                         largest = size.max_width;
2081                                                 }
2082                                         }
2083
2084                                         // We didn't find a match or we wouldn't be here
2085                                         return new Size(largest, largest);
2086
2087                                 } else {
2088                                         return new Size(32, 32);
2089                                 }
2090                         }
2091                 } 
2092
2093                 internal override int KeyboardSpeed {
2094                         get{
2095                                 //
2096                                 // A lot harder: need to do:
2097                                 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)       = 1
2098                                 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)        = 0x080517a8
2099                                 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58)                   = 0
2100                                 //
2101                                 // And from that we can tell the repetition rate
2102                                 //
2103                                 // Notice, the values must map to:
2104                                 //   [0, 31] which maps to 2.5 to 30 repetitions per second.
2105                                 //
2106                                 return 0;
2107                         }
2108                 }
2109
2110                 internal override int KeyboardDelay {
2111                         get {
2112                                 //
2113                                 // Return values must range from 0 to 4, 0 meaning 250ms,
2114                                 // and 4 meaning 1000 ms.
2115                                 //
2116                                 return 1; // ie, 500 ms
2117                         }
2118                 } 
2119
2120                 internal override  Size MaxWindowTrackSize {
2121                         get {
2122                                 return new Size (WorkingArea.Width, WorkingArea.Height);
2123                         }
2124                 }
2125
2126                 internal override bool MenuAccessKeysUnderlined {
2127                         get {
2128                                 return false;
2129                         }
2130                 }
2131
2132                 internal override  Size MinimizedWindowSpacingSize {
2133                         get {
2134                                 return new Size(1, 1);
2135                         }
2136                 } 
2137
2138                 internal override  Size MinimumWindowSize {
2139                         get {
2140                                 return new Size(110, 22);
2141                         }
2142                 } 
2143
2144                 internal override Size MinimumFixedToolWindowSize {
2145                         get { return new Size (27, 22); }
2146                 }
2147
2148                 internal override Size MinimumSizeableToolWindowSize {
2149                         get { return new Size (37, 22); }
2150                 }
2151
2152                 internal override Size MinimumNoBorderWindowSize {
2153                         get { return new Size (2, 2); }
2154                 }
2155                 
2156                 internal override Keys ModifierKeys {
2157                         get {
2158                                 return Keyboard.ModifierKeys;
2159                         }
2160                 }
2161
2162                 internal override  Size SmallIconSize {
2163                         get {
2164                                 IntPtr          list;
2165                                 XIconSize       size;
2166                                 int             count;
2167
2168                                 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2169                                         long            current;
2170                                         int             smallest;
2171
2172                                         current = (long)list;
2173                                         smallest = 0;
2174
2175                                         size = new XIconSize();
2176
2177                                         for (int i = 0; i < count; i++) {
2178                                                 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2179                                                 current += Marshal.SizeOf(size);
2180
2181                                                 // Look for our preferred size
2182                                                 if (size.min_width == 16) {
2183                                                         XFree(list);
2184                                                         return new Size(16, 16);
2185                                                 }
2186
2187                                                 if (size.max_width == 16) {
2188                                                         XFree(list);
2189                                                         return new Size(16, 16);
2190                                                 }
2191
2192                                                 if (size.min_width < 16 && size.max_width > 16) {
2193                                                         int     x;
2194
2195                                                         // check if we can fit one
2196                                                         x = size.min_width;
2197                                                         while (x < size.max_width) {
2198                                                                 x += size.width_inc;
2199                                                                 if (x == 16) {
2200                                                                         XFree(list);
2201                                                                         return new Size(16, 16);
2202                                                                 }
2203                                                         }
2204                                                 }
2205
2206                                                 if (smallest == 0 || smallest > size.min_width) {
2207                                                         smallest = size.min_width;
2208                                                 }
2209                                         }
2210
2211                                         // We didn't find a match or we wouldn't be here
2212                                         return new Size(smallest, smallest);
2213
2214                                 } else {
2215                                         return new Size(16, 16);
2216                                 }
2217                         }
2218                 } 
2219
2220                 internal override  int MouseButtonCount {
2221                         get {
2222                                 return 3;
2223                         }
2224                 } 
2225
2226                 internal override  bool MouseButtonsSwapped {
2227                         get {
2228                                 return false;   // FIXME - how to detect?
2229                         }
2230                 } 
2231
2232                 internal override Point MousePosition {
2233                         get {
2234                                 return mouse_position;
2235                         }
2236                 }
2237
2238                 internal override Size MouseHoverSize {
2239                         get {
2240                                 return new Size (1, 1);
2241                         }
2242                 }
2243
2244                 internal override int MouseHoverTime {
2245                         get {
2246                                 return HoverState.Interval;
2247                         }
2248                 }
2249
2250
2251
2252                 internal override  bool MouseWheelPresent {
2253                         get {
2254                                 return true;    // FIXME - how to detect?
2255                         }
2256                 } 
2257
2258                 internal override  Rectangle VirtualScreen {
2259                         get {
2260                                 IntPtr                  actual_atom;
2261                                 int                     actual_format;
2262                                 IntPtr                  nitems;
2263                                 IntPtr                  bytes_after;
2264                                 IntPtr                  prop = IntPtr.Zero;
2265                                 int                     width;
2266                                 int                     height;
2267
2268                                 XGetWindowProperty(DisplayHandle, RootWindow, _NET_DESKTOP_GEOMETRY, IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
2269                                 if ((long)nitems < 2)
2270                                         goto failsafe;
2271
2272                                 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2273                                 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2274
2275                                 XFree(prop);
2276
2277                                 return new Rectangle(0, 0, width, height);
2278
2279                         failsafe:
2280                                 XWindowAttributes       attributes=new XWindowAttributes();
2281
2282                                 lock (XlibLock) {
2283                                         XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2284                                 }
2285
2286                                 return new Rectangle(0, 0, attributes.width, attributes.height);
2287                         }
2288                 } 
2289
2290                 internal override  Rectangle WorkingArea {
2291                         get {
2292                                 IntPtr                  actual_atom;
2293                                 int                     actual_format;
2294                                 IntPtr                  nitems;
2295                                 IntPtr                  bytes_after;
2296                                 IntPtr                  prop = IntPtr.Zero;
2297                                 int                     width;
2298                                 int                     height;
2299                                 int                     current_desktop;
2300                                 int                     x;
2301                                 int                     y;
2302
2303                                 XGetWindowProperty(DisplayHandle, RootWindow, _NET_CURRENT_DESKTOP, IntPtr.Zero, new IntPtr(1), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
2304                                 if ((long)nitems < 1) {
2305                                         goto failsafe;
2306                                 }
2307
2308                                 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2309                                 XFree(prop);
2310
2311                                 XGetWindowProperty(DisplayHandle, RootWindow, _NET_WORKAREA, IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
2312                                 if ((long)nitems < 4 * current_desktop) {
2313                                         goto failsafe;
2314                                 }
2315
2316                                 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2317                                 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2318                                 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2319                                 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2320                                 XFree(prop);
2321
2322                                 return new Rectangle(x, y, width, height);
2323
2324                         failsafe:
2325                                 XWindowAttributes       attributes=new XWindowAttributes();
2326
2327                                 lock (XlibLock) {
2328                                         XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2329                                 }
2330
2331                                 return new Rectangle(0, 0, attributes.width, attributes.height);
2332                         }
2333                 }
2334
2335                 internal override bool ThemesEnabled {
2336                         get {
2337                                 return XplatUIX11.themes_enabled;
2338                         }
2339                 }
2340  
2341
2342                 #endregion      // Public properties
2343
2344                 #region Public Static Methods
2345                 internal override void RaiseIdle (EventArgs e)
2346                 {
2347                         if (Idle != null)
2348                                 Idle (this, e);
2349                 }
2350                 
2351                 internal override IntPtr InitializeDriver() {
2352                         lock (this) {
2353                                 if (DisplayHandle==IntPtr.Zero) {
2354                                         SetDisplay(XOpenDisplay(IntPtr.Zero));
2355                                 }
2356                         }
2357                         return IntPtr.Zero;
2358                 }
2359
2360                 internal override void ShutdownDriver(IntPtr token) {
2361                         lock (this) {
2362                                 if (DisplayHandle!=IntPtr.Zero) {
2363                                         XCloseDisplay(DisplayHandle);
2364                                         DisplayHandle=IntPtr.Zero;
2365                                 }
2366                         }
2367                 }
2368
2369                 internal override void EnableThemes() {
2370                         themes_enabled = true;
2371                 }
2372
2373
2374                 internal override void Activate(IntPtr handle) {
2375                         Hwnd hwnd;
2376
2377                         hwnd = Hwnd.ObjectFromHandle(handle);
2378
2379                         if (hwnd != null) {
2380                                 lock (XlibLock) {
2381                                         if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2382                                                 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2383                                                 XEventQueue q = null;
2384                                                 lock (unattached_timer_list) {
2385                                                         foreach (Timer t in unattached_timer_list) {
2386                                                                 if (q == null)
2387                                                                         q= (XEventQueue) MessageQueues [Thread.CurrentThread];
2388                                                                 t.thread = q.Thread;
2389                                                                 q.timer_list.Add (t);
2390                                                         }
2391                                                         unattached_timer_list.Clear ();
2392                                                 }
2393                                         }
2394 //                                      else {
2395 //                                              XRaiseWindow(DisplayHandle, handle);
2396 //                                      }
2397                                 }
2398                         }
2399                 }
2400
2401                 internal override void AudibleAlert() {
2402                         XBell(DisplayHandle, 0);
2403                         return;
2404                 }
2405
2406
2407                 internal override void CaretVisible(IntPtr handle, bool visible) {
2408                         if (Caret.Hwnd == handle) {
2409                                 if (visible) {
2410                                         if (!Caret.Visible) {
2411                                                 Caret.Visible = true;
2412                                                 ShowCaret();
2413                                                 Caret.Timer.Start();
2414                                         }
2415                                 } else {
2416                                         Caret.Visible = false;
2417                                         Caret.Timer.Stop();
2418                                         HideCaret();
2419                                 }
2420                         }
2421                 }
2422
2423                 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2424                         WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2425                         return true;
2426                 }
2427
2428                 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2429                         int     dest_x_return;
2430                         int     dest_y_return;
2431                         IntPtr  child;
2432                         Hwnd    hwnd;
2433
2434                         hwnd = Hwnd.ObjectFromHandle(handle);
2435
2436                         lock (XlibLock) {
2437                                 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2438                         }
2439
2440                         x = dest_x_return;
2441                         y = dest_y_return;
2442                 }
2443
2444                 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2445                         DataFormats.Format      f;
2446                         int[]                   result;
2447
2448                         f = DataFormats.Format.List;
2449
2450                         if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2451                                 return null;
2452                         }
2453
2454                         Clipboard.Formats = new ArrayList();
2455
2456                         while (f != null) {
2457                                 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2458
2459                                 Clipboard.Enumerating = true;
2460                                 while (Clipboard.Enumerating) {
2461                                         UpdateMessageQueue(null);
2462                                 }
2463                                 f = f.Next;
2464                         }
2465
2466                         result = new int[Clipboard.Formats.Count];
2467
2468                         for (int i = 0; i < Clipboard.Formats.Count; i++) {
2469                                 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2470                         }
2471
2472                         Clipboard.Formats = null;
2473                         return result;
2474                 }
2475
2476                 internal override void ClipboardClose(IntPtr handle) {
2477                         if (handle != ClipMagic) {
2478                                 throw new ArgumentException("handle is not a valid clipboard handle");
2479                         }
2480                         return;
2481                 }
2482
2483                 internal override int ClipboardGetID(IntPtr handle, string format) {
2484                         if (handle != ClipMagic) {
2485                                 throw new ArgumentException("handle is not a valid clipboard handle");
2486                         }
2487
2488                         if (format == "Text" ) return (int)Atom.XA_STRING;
2489                         else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2490                         //else if (format == "MetaFilePict" ) return 3;
2491                         //else if (format == "SymbolicLink" ) return 4;
2492                         //else if (format == "DataInterchangeFormat" ) return 5;
2493                         //else if (format == "Tiff" ) return 6;
2494                         else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2495                         else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2496                         else if (format == "Palette" ) return (int)Atom.XA_COLORMAP;    // Useless
2497                         //else if (format == "PenData" ) return 10;
2498                         //else if (format == "RiffAudio" ) return 11;
2499                         //else if (format == "WaveAudio" ) return 12;
2500                         else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2501                         //else if (format == "EnhancedMetafile" ) return 14;
2502                         //else if (format == "FileDrop" ) return 15;
2503                         //else if (format == "Locale" ) return 16;
2504
2505                         return XInternAtom(DisplayHandle, format, false).ToInt32();
2506                 }
2507
2508                 internal override IntPtr ClipboardOpen(bool primary_selection) {
2509                         if (!primary_selection)
2510                                 ClipMagic = CLIPBOARD;
2511                         else
2512                                 ClipMagic = PRIMARY;
2513                         return ClipMagic;
2514                 }
2515
2516                 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2517                         XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2518
2519                         Clipboard.Retrieving = true;
2520                         while (Clipboard.Retrieving) {
2521                                 UpdateMessageQueue(null);
2522                         }
2523
2524                         return Clipboard.Item;
2525                 }
2526
2527                 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2528                         Clipboard.Item = obj;
2529                         Clipboard.Type = type;
2530                         Clipboard.Converter = converter;
2531
2532                         if (obj != null) {
2533                                 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2534                         } else {
2535                                 // Clearing the selection
2536                                 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2537                         }
2538                 }
2539
2540                 internal override void CreateCaret (IntPtr handle, int width, int height)
2541                 {
2542                         XGCValues       gc_values;
2543                         Hwnd            hwnd;
2544
2545                         hwnd = Hwnd.ObjectFromHandle(handle);
2546
2547                         if (Caret.Hwnd != IntPtr.Zero) {
2548                                 DestroyCaret(Caret.Hwnd);
2549                         }
2550
2551                         Caret.Hwnd = handle;
2552                         Caret.Window = hwnd.client_window;
2553                         Caret.Width = width;
2554                         Caret.Height = height;
2555                         Caret.Visible = false;
2556                         Caret.On = false;
2557
2558                         gc_values = new XGCValues();
2559                         gc_values.line_width = width;
2560
2561                         Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2562                         if (Caret.gc == IntPtr.Zero) {
2563                                 Caret.Hwnd = IntPtr.Zero;
2564                                 return;
2565                         }
2566
2567                         XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2568                 }
2569
2570                 internal override IntPtr CreateWindow (CreateParams cp)
2571                 {
2572                         XSetWindowAttributes    Attributes;
2573                         Hwnd                    hwnd;
2574                         Hwnd                    parent_hwnd = null;
2575                         int                     X;
2576                         int                     Y;
2577                         int                     Width;
2578                         int                     Height;
2579                         IntPtr                  ParentHandle;
2580                         IntPtr                  WholeWindow;
2581                         IntPtr                  ClientWindow;
2582                         SetWindowValuemask      ValueMask;
2583                         int[]                   atoms;
2584
2585                         hwnd = new Hwnd();
2586
2587                         Attributes = new XSetWindowAttributes();
2588                         X = cp.X;
2589                         Y = cp.Y;
2590                         Width = cp.Width;
2591                         Height = cp.Height;
2592
2593                         if (Width<1) Width=1;
2594                         if (Height<1) Height=1;
2595
2596                         if (cp.Parent != IntPtr.Zero) {
2597                                 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2598                                 ParentHandle = parent_hwnd.client_window;
2599                         } else {
2600                                 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2601                                         // We need to use our foster parent window until this poor child gets it's parent assigned
2602                                         ParentHandle=FosterParent;
2603                                 } else {
2604                                         ParentHandle=RootWindow;
2605                                 }
2606                         }
2607
2608                         // Set the default location location for forms.
2609                         Point next;
2610                         if (cp.control is Form) {
2611                                 next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
2612                                 X = next.X;
2613                                 Y = next.Y;
2614                         }
2615                         ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2616
2617                         Attributes.bit_gravity = Gravity.NorthWestGravity;
2618                         Attributes.win_gravity = Gravity.NorthWestGravity;
2619
2620                         // Save what's under the toolwindow
2621                         if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2622                                 Attributes.save_under = true;
2623                                 ValueMask |= SetWindowValuemask.SaveUnder;
2624                         }
2625
2626
2627                         // If we're a popup without caption we override the WM
2628                         if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2629                                 Attributes.override_redirect = true;
2630                                 ValueMask |= SetWindowValuemask.OverrideRedirect;
2631                         }
2632
2633                         hwnd.x = X;
2634                         hwnd.y = Y;
2635                         hwnd.width = Width;
2636                         hwnd.height = Height;
2637                         hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2638                         hwnd.initial_style = cp.WindowStyle;
2639                         hwnd.initial_ex_style = cp.WindowExStyle;
2640
2641                         if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2642                                 hwnd.enabled = false;
2643                         }
2644
2645                         ClientWindow = IntPtr.Zero;
2646
2647                         Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
2648                         Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
2649                                 
2650                         lock (XlibLock) {
2651                                 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, XWindowSize.Width, XWindowSize.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2652                                 if (WholeWindow != IntPtr.Zero) {
2653                                         ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2654
2655                                         if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2656                                                 ValueMask = SetWindowValuemask.ColorMap;
2657                                                 Attributes.colormap = CustomColormap;
2658                                         }
2659                                         ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, XClientRect.X, XClientRect.Y, XClientRect.Width, XClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, CustomVisual, new UIntPtr ((uint)ValueMask), ref Attributes);
2660                                 }
2661                         }
2662
2663                         if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2664                                 throw new Exception("Could not create X11 windows");
2665                         }
2666
2667                         hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2668                         hwnd.WholeWindow = WholeWindow;
2669                         hwnd.ClientWindow = ClientWindow;
2670
2671                         #if DriverDebug || DriverDebugCreate
2672                                 Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}, Style {3}, ExStyle {4}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, (WindowStyles)cp.Style, (WindowExStyles)cp.ExStyle);
2673                         #endif
2674                         
2675                         if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2676                                 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2677                                         XSizeHints      hints;
2678
2679                                         hints = new XSizeHints();
2680                                         hints.x = X;
2681                                         hints.y = Y;
2682                                         hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2683                                         XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2684                                 }
2685                         }
2686
2687                         lock (XlibLock) {
2688                                 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
2689                                 if (hwnd.whole_window != hwnd.client_window)
2690                                         XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | Keyboard.KeyEventMask)));
2691                         }
2692
2693                         if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2694                                 atoms = new int[2];
2695                                 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2696                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2697
2698                                 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2699                         }
2700
2701                         SetWMStyles(hwnd, cp);
2702                         
2703                         // set the group leader
2704                         XWMHints wm_hints = new XWMHints ();
2705                         
2706                         wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2707                         wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2708                         wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2709                         
2710                         if (ParentHandle != RootWindow) {
2711                                 wm_hints.window_group = hwnd.whole_window;
2712                         } else {
2713                                 wm_hints.window_group = ParentHandle;
2714                         }
2715                         
2716                         lock (XlibLock) {
2717                                 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2718                         }
2719
2720                         if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2721                                 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2722                         } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2723                                 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2724                         }
2725
2726                         // for now make all windows dnd enabled
2727                         Dnd.SetAllowDrop (hwnd, true);
2728
2729                         // Set caption/window title
2730                         Text(hwnd.Handle, cp.Caption);
2731
2732                         SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2733                         SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2734
2735                         if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2736                                 hwnd.visible = true;
2737                                 MapWindow(hwnd, WindowType.Both);
2738                                 if (!(Control.FromHandle(hwnd.Handle) is Form))
2739                                         SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2740                         }
2741
2742                         return hwnd.Handle;
2743                 }
2744
2745                 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2746                         CreateParams create_params = new CreateParams();
2747
2748                         create_params.Caption = "";
2749                         create_params.X = X;
2750                         create_params.Y = Y;
2751                         create_params.Width = Width;
2752                         create_params.Height = Height;
2753
2754                         create_params.ClassName=XplatUI.DefaultClassName;
2755                         create_params.ClassStyle = 0;
2756                         create_params.ExStyle=0;
2757                         create_params.Parent=IntPtr.Zero;
2758                         create_params.Param=0;
2759
2760                         return CreateWindow(create_params);
2761                 }
2762
2763                 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2764                         IntPtr  cursor;
2765                         Bitmap  cursor_bitmap;
2766                         Bitmap  cursor_mask;
2767                         Byte[]  cursor_bits;
2768                         Byte[]  mask_bits;
2769                         Color   c_pixel;
2770                         Color   m_pixel;
2771                         int     width;
2772                         int     height;
2773                         IntPtr  cursor_pixmap;
2774                         IntPtr  mask_pixmap;
2775                         XColor  fg;
2776                         XColor  bg;
2777                         bool    and;
2778                         bool    xor;
2779
2780                         if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2781                                 return IntPtr.Zero;
2782                         }
2783
2784                         // Win32 only allows creation cursors of a certain size
2785                         if ((bitmap.Width != width) || (bitmap.Width != height)) {
2786                                 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2787                                 cursor_mask = new Bitmap(mask, new Size(width, height));
2788                         } else {
2789                                 cursor_bitmap = bitmap;
2790                                 cursor_mask = mask;
2791                         }
2792
2793                         width = cursor_bitmap.Width;
2794                         height = cursor_bitmap.Height;
2795
2796                         cursor_bits = new Byte[(width / 8) * height];
2797                         mask_bits = new Byte[(width / 8) * height];
2798
2799                         for (int y = 0; y < height; y++) {
2800                                 for (int x = 0; x < width; x++) {
2801                                         c_pixel = cursor_bitmap.GetPixel(x, y);
2802                                         m_pixel = cursor_mask.GetPixel(x, y);
2803
2804                                         and = c_pixel == cursor_pixel;
2805                                         xor = m_pixel == mask_pixel;
2806
2807                                         if (!and && !xor) {
2808                                                 // Black
2809                                                 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));       // The bit already is 0
2810                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2811                                         } else if (and && !xor) {
2812                                                 // White
2813                                                 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2814                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2815 #if notneeded
2816                                         } else if (and && !xor) {
2817                                                 // Screen
2818                                         } else if (and && xor) {
2819                                                 // Inverse Screen
2820
2821                                                 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2822                                                 // we want both to be 0 so nothing to be done
2823                                                 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2824                                                 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2825 #endif
2826                                         }
2827                                 }
2828                         }
2829
2830                         cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2831                         mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2832                         fg = new XColor();
2833                         bg = new XColor();
2834
2835                         fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2836                         fg.red = (ushort)65535;
2837                         fg.green = (ushort)65535;
2838                         fg.blue = (ushort)65535;
2839
2840                         bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2841
2842                         cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2843
2844                         XFreePixmap(DisplayHandle, cursor_pixmap);
2845                         XFreePixmap(DisplayHandle, mask_pixmap);
2846
2847                         return cursor;
2848                 }
2849
2850                 internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
2851                         CursorFontShape shape;
2852                         string name;
2853                         IntPtr theme;
2854                         int size;
2855                         Bitmap bmp = null;
2856                         
2857                         try {
2858                                 shape = StdCursorToFontShape (id);
2859                                 name = shape.ToString ().Replace ("XC_", string.Empty);
2860                                 size = XcursorGetDefaultSize (DisplayHandle);
2861                                 theme = XcursorGetTheme (DisplayHandle);
2862                                 IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
2863 #if debug
2864                                 Console.WriteLine ("DefineStdCursorBitmap, id={0}, #id={1}, name{2}, size={3}, theme: {4}, images_ptr={5}", id, (int) id, name, size, Marshal.PtrToStringAnsi (theme), images_ptr);
2865 #endif
2866
2867                                 if (images_ptr == IntPtr.Zero) {
2868                                         return null;
2869                                 }
2870
2871                                 XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
2872 #if debug
2873                                 Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
2874 #endif
2875
2876                                 if (images.nimage > 0) {                        
2877                                         // We only care about the first image.
2878                                         XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
2879                                         
2880 #if debug
2881                                         Console.WriteLine ("DefineStdCursorBitmap, loaded image <size={0}, height={1}, width={2}, xhot={3}, yhot={4}, pixels={5}", image.size, image.height, image.width, image.xhot, image.yhot, image.pixels);
2882 #endif
2883                                         // A sanity check
2884                                         if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
2885                                                 int [] pixels = new int [image.width * image.height];
2886                                                 Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
2887                                                 bmp = new Bitmap (image.width, image.height);
2888                                                 for (int w = 0; w < image.width; w++) {
2889                                                         for (int h = 0; h < image.height; h++) {
2890                                                                 bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
2891                                                         }
2892                                                 }
2893                                         }
2894                                 }
2895                                 
2896                                 XcursorImagesDestroy (images_ptr);
2897                                 
2898                         } catch (DllNotFoundException ex) {
2899                                 Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
2900                                 return null;
2901                         }
2902                         
2903                         return bmp;
2904                 }
2905
2906                 
2907                 internal override IntPtr DefineStdCursor(StdCursor id) {
2908                         CursorFontShape shape;
2909                         IntPtr          cursor;
2910
2911                         shape = StdCursorToFontShape (id);
2912
2913                         lock (XlibLock) {
2914                                 cursor = XCreateFontCursor(DisplayHandle, shape);
2915                         }
2916                         return cursor;
2917                 }
2918
2919                 internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
2920                         CursorFontShape shape;
2921                         // FIXME - define missing shapes
2922
2923                         switch (id) {
2924                                 case StdCursor.AppStarting: {
2925                                         shape = CursorFontShape.XC_watch;
2926                                         break;
2927                                 }
2928
2929                                 case StdCursor.Arrow: {
2930                                         shape = CursorFontShape.XC_top_left_arrow;
2931                                         break;
2932                                 }
2933
2934                                 case StdCursor.Cross: {
2935                                         shape = CursorFontShape.XC_crosshair;
2936                                         break;
2937                                 }
2938
2939                                 case StdCursor.Default: {
2940                                         shape = CursorFontShape.XC_top_left_arrow;
2941                                         break;
2942                                 }
2943
2944                                 case StdCursor.Hand: {
2945                                         shape = CursorFontShape.XC_hand1;
2946                                         break;
2947                                 }
2948
2949                                 case StdCursor.Help: {
2950                                         shape = CursorFontShape.XC_question_arrow;
2951                                         break;
2952                                 }
2953
2954                                 case StdCursor.HSplit: {
2955                                         shape = CursorFontShape.XC_sb_v_double_arrow; 
2956                                         break;
2957                                 }
2958
2959                                 case StdCursor.IBeam: {
2960                                         shape = CursorFontShape.XC_xterm; 
2961                                         break;
2962                                 }
2963
2964                                 case StdCursor.No: {
2965                                         shape = CursorFontShape.XC_circle; 
2966                                         break;
2967                                 }
2968
2969                                 case StdCursor.NoMove2D: {
2970                                         shape = CursorFontShape.XC_fleur; 
2971                                         break;
2972                                 }
2973
2974                                 case StdCursor.NoMoveHoriz: {
2975                                         shape = CursorFontShape.XC_fleur; 
2976                                         break;
2977                                 }
2978
2979                                 case StdCursor.NoMoveVert: {
2980                                         shape = CursorFontShape.XC_fleur; 
2981                                         break;
2982                                 }
2983
2984                                 case StdCursor.PanEast: {
2985                                         shape = CursorFontShape.XC_fleur; 
2986                                         break;
2987                                 }
2988
2989                                 case StdCursor.PanNE: {
2990                                         shape = CursorFontShape.XC_fleur; 
2991                                         break;
2992                                 }
2993
2994                                 case StdCursor.PanNorth: {
2995                                         shape = CursorFontShape.XC_fleur; 
2996                                         break;
2997                                 }
2998
2999                                 case StdCursor.PanNW: {
3000                                         shape = CursorFontShape.XC_fleur; 
3001                                         break;
3002                                 }
3003
3004                                 case StdCursor.PanSE: {
3005                                         shape = CursorFontShape.XC_fleur; 
3006                                         break;
3007                                 }
3008
3009                                 case StdCursor.PanSouth: {
3010                                         shape = CursorFontShape.XC_fleur; 
3011                                         break;
3012                                 }
3013
3014                                 case StdCursor.PanSW: {
3015                                         shape = CursorFontShape.XC_fleur; 
3016                                         break;
3017                                 }
3018
3019                                 case StdCursor.PanWest: {
3020                                         shape = CursorFontShape.XC_sizing; 
3021                                         break;
3022                                 }
3023
3024                                 case StdCursor.SizeAll: {
3025                                         shape = CursorFontShape.XC_fleur; 
3026                                         break;
3027                                 }
3028
3029                                 case StdCursor.SizeNESW: {
3030                                         shape = CursorFontShape.XC_top_right_corner; 
3031                                         break;
3032                                 }
3033
3034                                 case StdCursor.SizeNS: {
3035                                         shape = CursorFontShape.XC_sb_v_double_arrow;
3036                                         break;
3037                                 }
3038
3039                                 case StdCursor.SizeNWSE: {
3040                                         shape = CursorFontShape.XC_top_left_corner; 
3041                                         break;
3042                                 }
3043
3044                                 case StdCursor.SizeWE: {
3045                                         shape = CursorFontShape.XC_sb_h_double_arrow; 
3046                                         break;
3047                                 }
3048
3049                                 case StdCursor.UpArrow: {
3050                                         shape = CursorFontShape.XC_center_ptr; 
3051                                         break;
3052                                 }
3053
3054                                 case StdCursor.VSplit: {
3055                                         shape = CursorFontShape.XC_sb_h_double_arrow;
3056                                         break;
3057                                 }
3058
3059                                 case StdCursor.WaitCursor: {
3060                                         shape = CursorFontShape.XC_watch; 
3061                                         break;
3062                                 }
3063
3064                                 default: {
3065                                         shape = (CursorFontShape) 0;
3066                                         break;
3067                                 }
3068                         }
3069                         
3070                         return shape;
3071                 }
3072
3073                 internal override IntPtr DefWndProc(ref Message msg) {
3074                         switch ((Msg)msg.Msg) {
3075                                 
3076                                 case Msg.WM_IME_COMPOSITION:
3077                                         string s = Keyboard.GetCompositionString ();
3078                                         foreach (char c in s)
3079                                                 SendMessage (msg.HWnd, Msg.WM_IME_CHAR, (IntPtr) c, msg.LParam);
3080                                         return IntPtr.Zero;
3081
3082                                 case Msg.WM_IME_CHAR:
3083                                         // On Windows API it sends two WM_CHAR messages for each byte, but
3084                                         // I wonder if it is worthy to emulate it (also no idea how to 
3085                                         // reconstruct those bytes into chars).
3086                                         SendMessage (msg.HWnd, Msg.WM_CHAR, msg.WParam, msg.LParam);
3087                                         return IntPtr.Zero;
3088
3089                                 case Msg.WM_PAINT: {
3090                                         Hwnd hwnd;
3091
3092                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3093                                         if (hwnd != null) {
3094                                                 hwnd.expose_pending = false;
3095                                         }
3096
3097                                         return IntPtr.Zero;
3098                                 }
3099
3100                                 case Msg.WM_NCPAINT: {
3101                                         Hwnd hwnd;
3102
3103                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3104                                         if (hwnd != null) {
3105                                                 hwnd.nc_expose_pending = false;
3106                                         }
3107
3108                                         return IntPtr.Zero;
3109                                 }
3110
3111                                 case Msg.WM_NCCALCSIZE: {
3112                                         Hwnd hwnd;
3113
3114                                         if (msg.WParam == (IntPtr)1) {
3115                                                 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3116                                                 
3117                                                 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3118                                                 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3119
3120                                                 // Add all the stuff X is supposed to draw.
3121                                                 Control ctrl = Control.FromHandle (hwnd.Handle);
3122                                                 
3123                                                 if (ctrl != null) {
3124                                                         Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3125                                                         
3126                                                         ncp.rgrc1.top += rect.top;
3127                                                         ncp.rgrc1.bottom -= rect.bottom;
3128                                                         ncp.rgrc1.left += rect.left;
3129                                                         ncp.rgrc1.right -= rect.right;
3130                                                         
3131                                                         Marshal.StructureToPtr (ncp, msg.LParam, true);
3132                                                 }
3133                                         }
3134
3135                                         return IntPtr.Zero;
3136                                 }
3137
3138                                 case Msg.WM_CONTEXTMENU: {
3139                                         Hwnd hwnd;
3140
3141                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3142
3143                                         if ((hwnd != null) && (hwnd.parent != null)) {
3144                                                 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3145                                         }
3146                                         return IntPtr.Zero;
3147                                 }
3148
3149                                 case Msg.WM_MOUSEWHEEL: {
3150                                         Hwnd hwnd;
3151
3152                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3153
3154                                         if ((hwnd != null) && (hwnd.parent != null)) {
3155                                                 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3156                                                 if (msg.Result == IntPtr.Zero) {
3157                                                         return IntPtr.Zero;
3158                                                 }
3159                                         }
3160                                         return IntPtr.Zero;
3161                                 }
3162
3163                                 case Msg.WM_SETCURSOR: {
3164                                         Hwnd    hwnd;
3165
3166                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3167                                         if (hwnd == null)
3168                                                 break; // not sure how this happens, but it does
3169
3170                                         // Pass to parent window first
3171                                         while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3172                                                 hwnd = hwnd.parent;
3173                                                 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3174                                         }
3175
3176                                         if (msg.Result == IntPtr.Zero) {
3177                                                 IntPtr handle;
3178
3179                                                 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3180                                                         case HitTest.HTBOTTOM:          handle = Cursors.SizeNS.handle; break;
3181                                                         case HitTest.HTBORDER:          handle = Cursors.SizeNS.handle; break;
3182                                                         case HitTest.HTBOTTOMLEFT:      handle = Cursors.SizeNESW.handle; break;
3183                                                         case HitTest.HTBOTTOMRIGHT:     handle = Cursors.SizeNWSE.handle; break;
3184                                                         case HitTest.HTERROR:           if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3185                                                                                                 AudibleAlert();
3186                                                                                         }
3187                                                                                         handle = Cursors.Default.handle;
3188                                                                                         break;
3189
3190                                                         case HitTest.HTHELP:            handle = Cursors.Help.handle; break;
3191                                                         case HitTest.HTLEFT:            handle = Cursors.SizeWE.handle; break;
3192                                                         case HitTest.HTRIGHT:           handle = Cursors.SizeWE.handle; break;
3193                                                         case HitTest.HTTOP:             handle = Cursors.SizeNS.handle; break;
3194                                                         case HitTest.HTTOPLEFT:         handle = Cursors.SizeNWSE.handle; break;
3195                                                         case HitTest.HTTOPRIGHT:        handle = Cursors.SizeNESW.handle; break;
3196
3197                                                         #if SameAsDefault
3198                                                         case HitTest.HTGROWBOX:
3199                                                         case HitTest.HTSIZE:
3200                                                         case HitTest.HTZOOM:
3201                                                         case HitTest.HTVSCROLL:
3202                                                         case HitTest.HTSYSMENU:
3203                                                         case HitTest.HTREDUCE:
3204                                                         case HitTest.HTNOWHERE:
3205                                                         case HitTest.HTMAXBUTTON:
3206                                                         case HitTest.HTMINBUTTON:
3207                                                         case HitTest.HTMENU:
3208                                                         case HitTest.HSCROLL:
3209                                                         case HitTest.HTBOTTOM:
3210                                                         case HitTest.HTCAPTION:
3211                                                         case HitTest.HTCLIENT:
3212                                                         case HitTest.HTCLOSE:
3213                                                         #endif
3214                                                         default: handle = Cursors.Default.handle; break;
3215                                                 }
3216                                                 SetCursor(msg.HWnd, handle);
3217                                         }
3218                                         return (IntPtr)1;
3219                                 }
3220                         }
3221                         return IntPtr.Zero;
3222                 }
3223
3224                 internal override void DestroyCaret(IntPtr handle) {
3225                         if (Caret.Hwnd == handle) {
3226                                 if (Caret.Visible) {
3227                                         HideCaret ();
3228                                         Caret.Timer.Stop();
3229                                 }
3230                                 if (Caret.gc != IntPtr.Zero) {
3231                                         XFreeGC(DisplayHandle, Caret.gc);
3232                                         Caret.gc = IntPtr.Zero;
3233                                 }
3234                                 Caret.Hwnd = IntPtr.Zero;
3235                                 Caret.Visible = false;
3236                                 Caret.On = false;
3237                         }
3238                 }
3239
3240                 internal override void DestroyCursor(IntPtr cursor) {
3241                         lock (XlibLock) {
3242                                 XFreeCursor(DisplayHandle, cursor);
3243                         }
3244                 }
3245
3246                 internal override void DestroyWindow(IntPtr handle) {
3247                         Hwnd    hwnd;
3248
3249                         hwnd = Hwnd.ObjectFromHandle(handle);
3250
3251                         if (hwnd == null) {
3252                                 #if DriverDebug || DriverDebugDestroy
3253                                         Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3254                                 #endif
3255                                 return;
3256                         }
3257
3258                         #if DriverDebug || DriverDebugDestroy
3259                                 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3260                         #endif
3261
3262                         SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3263                                 
3264                         CleanupCachedWindows (hwnd);
3265
3266                         ArrayList windows = new ArrayList ();
3267
3268                         AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3269
3270
3271                         foreach (Hwnd h in windows) {
3272                                 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3273                                 h.zombie = true;
3274                         }
3275
3276                         lock (XlibLock) {
3277                                 if (hwnd.whole_window != IntPtr.Zero) {
3278                                         #if DriverDebug || DriverDebugDestroy
3279                                         Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3280                                         #endif
3281                                         Keyboard.DestroyICForWindow (hwnd.whole_window);
3282                                         XDestroyWindow(DisplayHandle, hwnd.whole_window);
3283                                 }
3284                                 else if (hwnd.client_window != IntPtr.Zero) {
3285                                         #if DriverDebug || DriverDebugDestroy
3286                                         Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3287                                         #endif
3288                                         Keyboard.DestroyICForWindow (hwnd.client_window);
3289                                         XDestroyWindow(DisplayHandle, hwnd.client_window);
3290                                 }
3291
3292                         }
3293                 }
3294
3295                 internal override IntPtr DispatchMessage(ref MSG msg) {
3296                         return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3297                 }
3298
3299                 IntPtr GetReversibleScreenGC (Color backColor)
3300                 {
3301                         XGCValues       gc_values;
3302                         IntPtr          gc;
3303                         uint pixel;
3304
3305                         XColor xcolor = new XColor();
3306                         xcolor.red = (ushort)(backColor.R * 257);
3307                         xcolor.green = (ushort)(backColor.G * 257);
3308                         xcolor.blue = (ushort)(backColor.B * 257);
3309                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3310                         pixel = (uint)xcolor.pixel.ToInt32();
3311
3312
3313                         gc_values = new XGCValues();
3314
3315                         gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3316                         gc_values.foreground = (IntPtr)pixel;
3317
3318                         gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3319                         XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3320                         XSetFunction(DisplayHandle,   gc, GXFunction.GXxor);
3321
3322                         return gc;
3323                 }
3324
3325                 IntPtr GetReversibleControlGC (Control control, int line_width)
3326                 {
3327                         XGCValues       gc_values;
3328                         IntPtr          gc;
3329
3330                         gc_values = new XGCValues();
3331
3332                         gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3333                         gc_values.line_width = line_width;
3334                         gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3335
3336                         // This logic will give us true rubber bands: (libsx, SANE_XOR)
3337                         //mask = foreground ^ background; 
3338                         //XSetForeground(DisplayHandle, gc, 0xffffffff);
3339                         //XSetBackground(DisplayHandle, gc, background);
3340                         //XSetFunction(DisplayHandle,   gc, GXxor);
3341                         //XSetPlaneMask(DisplayHandle,  gc, mask);
3342
3343
3344                         gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3345                         uint foreground;
3346                         uint background;
3347
3348                         XColor xcolor = new XColor();
3349
3350                         xcolor.red = (ushort)(control.ForeColor.R * 257);
3351                         xcolor.green = (ushort)(control.ForeColor.G * 257);
3352                         xcolor.blue = (ushort)(control.ForeColor.B * 257);
3353                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3354                         foreground = (uint)xcolor.pixel.ToInt32();
3355
3356                         xcolor.red = (ushort)(control.BackColor.R * 257);
3357                         xcolor.green = (ushort)(control.BackColor.G * 257);
3358                         xcolor.blue = (ushort)(control.BackColor.B * 257);
3359                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3360                         background = (uint)xcolor.pixel.ToInt32();
3361
3362                         uint mask = foreground ^ background; 
3363
3364                         XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3365                         XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3366                         XSetFunction(DisplayHandle,   gc, GXFunction.GXxor);
3367                         XSetPlaneMask(DisplayHandle,  gc, (IntPtr)mask);
3368
3369                         return gc;
3370                 }
3371
3372                 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3373                 {
3374                         if (backColor.GetBrightness() < 0.5)
3375                                 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3376
3377                         IntPtr gc = GetReversibleScreenGC (backColor);
3378
3379                         XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3380
3381                         XFreeGC(DisplayHandle, gc);
3382                 }
3383
3384                 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3385                 {
3386                         if (backColor.GetBrightness() < 0.5)
3387                                 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3388
3389                         IntPtr gc = GetReversibleScreenGC (backColor);
3390
3391                         if (rectangle.Width < 0) {
3392                                 rectangle.X += rectangle.Width;
3393                                 rectangle.Width = -rectangle.Width;
3394                         }
3395                         if (rectangle.Height < 0) {
3396                                 rectangle.Y += rectangle.Height;
3397                                 rectangle.Height = -rectangle.Height;
3398                         }
3399
3400                         int line_width = 1;
3401                         GCLineStyle line_style = GCLineStyle.LineSolid;
3402                         GCCapStyle cap_style = GCCapStyle.CapButt;
3403                         GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3404
3405                         switch (style) {
3406                         case FrameStyle.Dashed:
3407                                 line_style = GCLineStyle.LineOnOffDash;
3408                                 break;
3409                         case FrameStyle.Thick:
3410                                 line_width = 2;
3411                                 break;
3412                         }
3413
3414                         XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3415
3416                         XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3417
3418                         XFreeGC(DisplayHandle, gc);
3419                 }
3420
3421                 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor) 
3422                 {
3423                         if (backColor.GetBrightness() < 0.5)
3424                                 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3425
3426                         IntPtr gc = GetReversibleScreenGC (backColor);
3427
3428                         if (rectangle.Width < 0) {
3429                                 rectangle.X += rectangle.Width;
3430                                 rectangle.Width = -rectangle.Width;
3431                         }
3432                         if (rectangle.Height < 0) {
3433                                 rectangle.Y += rectangle.Height;
3434                                 rectangle.Height = -rectangle.Height;
3435                         }
3436                         XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3437
3438                         XFreeGC(DisplayHandle, gc);
3439                 }
3440
3441                 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width)
3442                 {
3443                         IntPtr          gc;
3444                         Control control = Control.FromHandle(handle);
3445
3446                         gc = GetReversibleControlGC (control, line_width);
3447
3448                         if ((rect.Width > 0) && (rect.Height > 0)) {
3449                                 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3450                         } else {
3451                                 if (rect.Width > 0) {
3452                                         XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3453                                 } else {
3454                                         XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3455                                 }
3456                         }
3457                         XFreeGC(DisplayHandle, gc);
3458                 }
3459
3460                 internal override void DoEvents() {
3461                         MSG     msg = new MSG ();
3462                         XEventQueue queue;
3463
3464                         if (OverrideCursorHandle != IntPtr.Zero) {
3465                                 OverrideCursorHandle = IntPtr.Zero;
3466                         }
3467
3468                         queue = ThreadQueue(Thread.CurrentThread);
3469
3470                         queue.DispatchIdle = false;
3471
3472                         while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3473                                 TranslateMessage (ref msg);
3474                                 DispatchMessage (ref msg);
3475                         }
3476
3477                         queue.DispatchIdle = true;
3478                 }
3479
3480                 internal override void EnableWindow(IntPtr handle, bool Enable) {
3481                         Hwnd    hwnd;
3482
3483                         hwnd = Hwnd.ObjectFromHandle(handle);
3484                         if (hwnd != null) {
3485                                 hwnd.Enabled = Enable;
3486                         }
3487                 }
3488
3489                 internal override void EndLoop(Thread thread) {
3490                         // This is where we one day will shut down the loop for the thread
3491                 }
3492
3493                 internal override IntPtr GetActive() {
3494                         IntPtr  actual_atom;
3495                         int     actual_format;
3496                         IntPtr  nitems;
3497                         IntPtr  bytes_after;
3498                         IntPtr  prop = IntPtr.Zero;
3499                         IntPtr  active = IntPtr.Zero;
3500
3501                         XGetWindowProperty(DisplayHandle, RootWindow, _NET_ACTIVE_WINDOW, IntPtr.Zero, new IntPtr (1), false, (IntPtr)Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
3502                         if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3503                                 active = (IntPtr)Marshal.ReadInt32(prop);
3504                                 XFree(prop);
3505                         }
3506
3507                         if (active != IntPtr.Zero) {
3508                                 Hwnd    hwnd;
3509
3510                                 hwnd = Hwnd.GetObjectFromWindow(active);
3511                                 if (hwnd != null) {
3512                                         active = hwnd.Handle;
3513                                 } else {
3514                                         active = IntPtr.Zero;
3515                                 }
3516                         }
3517                         return active;
3518                 }
3519
3520                 internal override Region GetClipRegion(IntPtr handle) {
3521                         Hwnd    hwnd;
3522
3523                         hwnd = Hwnd.ObjectFromHandle(handle);
3524                         if (hwnd != null) {
3525                                 return hwnd.UserClip;
3526                         }
3527
3528                         return null;
3529                 }
3530
3531                 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3532                         width = 20;
3533                         height = 20;
3534                         hotspot_x = 0;
3535                         hotspot_y = 0;
3536                 }
3537
3538                 internal override void GetDisplaySize(out Size size) {
3539                         XWindowAttributes       attributes=new XWindowAttributes();
3540
3541                         lock (XlibLock) {
3542                                 // FIXME - use _NET_WM messages instead?
3543                                 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3544                         }
3545
3546                         size = new Size(attributes.width, attributes.height);
3547                 }
3548
3549                 internal override SizeF GetAutoScaleSize(Font font) {
3550                         Graphics        g;
3551                         float           width;
3552                         string          magic_string = "The quick brown fox jumped over the lazy dog.";
3553                         double          magic_number = 44.549996948242189;
3554
3555                         g = Graphics.FromHwnd(FosterParent);
3556
3557                         width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3558                         return new SizeF(width, font.Height);
3559                 }
3560
3561                 internal override IntPtr GetParent(IntPtr handle) {
3562                         Hwnd    hwnd;
3563
3564                         hwnd = Hwnd.ObjectFromHandle(handle);
3565                         if (hwnd != null && hwnd.parent != null) {
3566                                 return hwnd.parent.Handle;
3567                         }
3568                         return IntPtr.Zero;
3569                 }
3570                 
3571                 // This is a nop on win32 and x11
3572                 internal override IntPtr GetPreviousWindow(IntPtr handle) {
3573                         return handle;
3574                 }
3575
3576                 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3577                         IntPtr  use_handle;
3578                         IntPtr  root;
3579                         IntPtr  child;
3580                         int     root_x;
3581                         int     root_y;
3582                         int     win_x;
3583                         int     win_y;
3584                         int     keys_buttons;
3585
3586                         if (handle != IntPtr.Zero) {
3587                                 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3588                         } else {
3589                                 use_handle = RootWindow;
3590                         }
3591
3592                         lock (XlibLock) {
3593                                 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3594                         }
3595
3596                         if (handle != IntPtr.Zero) {
3597                                 x = win_x;
3598                                 y = win_y;
3599                         } else {
3600                                 x = root_x;
3601                                 y = root_y;
3602                         }
3603                 }
3604
3605                 internal override IntPtr GetFocus() {
3606                         return FocusWindow;
3607                 }
3608
3609
3610                 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3611                         FontFamily ff = font.FontFamily;
3612                         ascent = ff.GetCellAscent (font.Style);
3613                         descent = ff.GetCellDescent (font.Style);
3614                         return true;
3615                 }
3616
3617                 internal override Point GetMenuOrigin(IntPtr handle) {
3618                         Hwnd    hwnd;
3619
3620                         hwnd = Hwnd.ObjectFromHandle(handle);
3621
3622                         if (hwnd != null) {
3623                                 return hwnd.MenuOrigin;
3624                         }
3625                         return Point.Empty;
3626                 }
3627
3628                 [MonoTODO("Implement filtering")]
3629                 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3630                         XEvent  xevent;
3631                         bool    client;
3632                         Hwnd    hwnd;
3633
3634                         ProcessNextMessage:
3635
3636                         if (((XEventQueue)queue_id).Count > 0) {
3637                                 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3638                         } else {
3639                                 UpdateMessageQueue ((XEventQueue)queue_id);
3640
3641                                 if (((XEventQueue)queue_id).Count > 0) {
3642                                         xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3643                                 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3644                                         xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3645                                 } else {
3646                                         msg.hwnd= IntPtr.Zero;
3647                                         msg.message = Msg.WM_ENTERIDLE;
3648                                         return true;
3649                                 }
3650                         }
3651
3652                         hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3653
3654                         // Handle messages for windows that are already or are about to be destroyed.
3655
3656                         // we need a special block for this because unless we remove the hwnd from the paint
3657                         // queue it will always stay there (since we don't handle the expose), and we'll
3658                         // effectively loop infinitely trying to repaint a non-existant window.
3659                         if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3660                                 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3661                                 hwnd.Queue.Paint.Remove (hwnd);
3662                                 goto ProcessNextMessage;
3663                         }
3664
3665                         // We need to make sure we only allow DestroyNotify events through for zombie
3666                         // hwnds, since much of the event handling code makes requests using the hwnd's
3667                         // client_window, and that'll result in BadWindow errors if there's some lag
3668                         // between the XDestroyWindow call and the DestroyNotify event.
3669                         if (hwnd == null || hwnd.zombie && xevent.AnyEvent.type != XEventName.ClientMessage) {
3670                                 #if DriverDebug || DriverDebugDestroy
3671                                         Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3672                                 #endif
3673                                 goto ProcessNextMessage;
3674                         }
3675
3676                         if (hwnd.client_window == xevent.AnyEvent.window) {
3677                                 client = true;
3678                                 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3679                         } else {
3680                                 client = false;
3681                                 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3682                         }
3683
3684                         msg.hwnd = hwnd.Handle;
3685
3686                         // Windows sends WM_ENTERSIZEMOVE when a form resize/move operation starts and WM_EXITSIZEMOVE 
3687                         // when it is done. The problem in X11 is that there is no concept of start-end of a moving/sizing.
3688                         // Configure events ("this window has resized/moved") are sent for each step of the resize. We send a
3689                         // WM_ENTERSIZEMOVE when we get the first Configure event. The problem is the WM_EXITSIZEMOVE.
3690                         // 
3691                         //  - There is no way for us to know which is the last Configure event. We can't traverse the events 
3692                         //    queue, because the next configure event might not be pending yet.
3693                         //  - We can't get ButtonPress/Release events for the window decorations, because they are not part 
3694                         //    of the window(s) we manage.
3695                         //  - We can't rely on the mouse state to change to "up" before the last Configure event. It doesn't.
3696                         // 
3697                         // We are almost 100% guaranteed to get another event (e.g Expose or other), but we can't know for sure 
3698                         // which, so we have here to check if the mouse buttons state is "up" and send the WM_EXITSIZEMOVE
3699                         //
3700                         if (hwnd.resizing_or_moving) {
3701                                 int root_x, root_y, win_x, win_y, keys_buttons;
3702                                 IntPtr  root, child;
3703                                 XQueryPointer (DisplayHandle, hwnd.Handle, out root, out child, out root_x, out root_y, 
3704                                                out win_x, out win_y, out keys_buttons);
3705                                 if ((keys_buttons & (int)MouseKeyMasks.Button1Mask) == 0 &&
3706                                     (keys_buttons & (int)MouseKeyMasks.Button2Mask) == 0 &&
3707                                     (keys_buttons & (int)MouseKeyMasks.Button3Mask) == 0) {
3708                                         hwnd.resizing_or_moving = false;
3709                                         SendMessage (hwnd.Handle, Msg.WM_EXITSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
3710                                 }
3711                         }
3712
3713                         //
3714                         // If you add a new event to this switch make sure to add it in
3715                         // UpdateMessage also unless it is not coming through the X event system.
3716                         //
3717                         switch(xevent.type) {
3718                                 case XEventName.KeyPress: {
3719                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3720                                         break;
3721                                 }
3722
3723                                 case XEventName.KeyRelease: {
3724                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3725                                         break;
3726                                 }
3727
3728                                 case XEventName.ButtonPress: {
3729                                         switch(xevent.ButtonEvent.button) {
3730                                                 case 1: {
3731                                                         MouseState |= MouseButtons.Left;
3732                                                         if (client) {
3733                                                                 msg.message = Msg.WM_LBUTTONDOWN;
3734                                                                 msg.wParam = GetMousewParam (0);
3735                                                         } else {
3736                                                                 msg.message = Msg.WM_NCLBUTTONDOWN;
3737                                                                 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3738                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3739                                                         }
3740                                                         break;
3741                                                 }
3742
3743                                                 case 2: {
3744                                                         MouseState |= MouseButtons.Middle;
3745                                                         if (client) {
3746                                                                 msg.message = Msg.WM_MBUTTONDOWN;
3747                                                                 msg.wParam = GetMousewParam (0);
3748                                                         } else {
3749                                                                 msg.message = Msg.WM_NCMBUTTONDOWN;
3750                                                                 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3751                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3752                                                         }
3753                                                         break;
3754                                                 }
3755
3756                                                 case 3: {
3757                                                         MouseState |= MouseButtons.Right;
3758                                                         if (client) {
3759                                                                 msg.message = Msg.WM_RBUTTONDOWN;
3760                                                                 msg.wParam = GetMousewParam (0);
3761                                                         } else {
3762                                                                 msg.message = Msg.WM_NCRBUTTONDOWN;
3763                                                                 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3764                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3765                                                         }
3766                                                         break;
3767                                                 }
3768
3769                                                 case 4: {
3770                                                         msg.hwnd = FocusWindow;
3771                                                         msg.message=Msg.WM_MOUSEWHEEL;
3772                                                         msg.wParam=GetMousewParam(120);
3773                                                         break;
3774                                                 }
3775
3776                                                 case 5: {
3777                                                         msg.hwnd = FocusWindow;
3778                                                         msg.message=Msg.WM_MOUSEWHEEL;
3779                                                         msg.wParam=GetMousewParam(-120);
3780                                                         break;
3781                                                 }
3782
3783                                         }
3784
3785                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3786                                         mouse_position.X = xevent.ButtonEvent.x;
3787                                         mouse_position.Y = xevent.ButtonEvent.y;
3788
3789                                         if (!hwnd.Enabled) {
3790                                                 IntPtr dummy;
3791
3792                                                 msg.hwnd = hwnd.EnabledHwnd;
3793                                                 XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.ButtonEvent.x, xevent.ButtonEvent.y, out xevent.ButtonEvent.x, out xevent.ButtonEvent.y, out dummy);
3794                                                 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3795                                         }
3796
3797                                         if (Grab.Hwnd != IntPtr.Zero) {
3798                                                 msg.hwnd = Grab.Hwnd;
3799                                         }
3800
3801                                         if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3802                                                 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3803                                                 switch(xevent.ButtonEvent.button) {
3804                                                         case 1: {
3805                                                                 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3806                                                                 break;
3807                                                         }
3808
3809                                                         case 2: {
3810                                                                 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3811                                                                 break;
3812                                                         }
3813
3814                                                         case 3: {
3815                                                                 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3816                                                                 break;
3817                                                         }
3818                                                 }
3819                                                 ClickPending.Pending = false;
3820                                         } else {
3821                                                 ClickPending.Pending = true;
3822                                                 ClickPending.Hwnd = msg.hwnd;
3823                                                 ClickPending.Message = msg.message;
3824                                                 ClickPending.wParam = msg.wParam;
3825                                                 ClickPending.lParam = msg.lParam;
3826                                                 ClickPending.Time = (long)xevent.ButtonEvent.time;
3827                                         }
3828                                         
3829                                         if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3830                                                 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3831
3832                                                 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3833                                                 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after 
3834                                                 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3835                                                 XEvent motionEvent = new XEvent ();
3836                                                 motionEvent.type = XEventName.MotionNotify;
3837                                                 motionEvent.MotionEvent.display = DisplayHandle;
3838                                                 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3839                                                 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3840                                                 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3841                                                 hwnd.Queue.EnqueueLocked (motionEvent);
3842                                         }
3843                                         
3844                                         break;
3845                                 }
3846
3847                                 case XEventName.ButtonRelease: {
3848                                         switch(xevent.ButtonEvent.button) {
3849                                                 case 1: {
3850                                                         if (client) {
3851                                                                 msg.message = Msg.WM_LBUTTONUP;
3852                                                         } else {
3853                                                                 msg.message = Msg.WM_NCLBUTTONUP;
3854                                                                 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3855                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3856                                                         }
3857                                                         MouseState &= ~MouseButtons.Left;
3858                                                         msg.wParam = GetMousewParam (0);
3859                                                         break;
3860                                                 }
3861
3862                                                 case 2: {
3863                                                         if (client) {
3864                                                                 msg.message = Msg.WM_MBUTTONUP;
3865                                                         } else {
3866                                                                 msg.message = Msg.WM_NCMBUTTONUP;
3867                                                                 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3868                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3869                                                         }
3870                                                         MouseState &= ~MouseButtons.Middle;
3871                                                         msg.wParam = GetMousewParam (0);
3872                                                         break;
3873                                                 }
3874
3875                                                 case 3: {
3876                                                         if (client) {
3877                                                                 msg.message = Msg.WM_RBUTTONUP;
3878                                                         } else {
3879                                                                 msg.message = Msg.WM_NCRBUTTONUP;
3880                                                                 msg.wParam = (IntPtr) NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3881                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3882                                                         }
3883                                                         MouseState &= ~MouseButtons.Right;
3884                                                         msg.wParam = GetMousewParam (0);
3885                                                         break;
3886                                                 }
3887
3888                                                 case 4: {
3889                                                         goto ProcessNextMessage;
3890                                                 }
3891
3892                                                 case 5: {
3893                                                         goto ProcessNextMessage;
3894                                                 }
3895                                         }
3896
3897                                         if (!hwnd.Enabled) {
3898                                                 IntPtr dummy;
3899
3900                                                 msg.hwnd = hwnd.EnabledHwnd;
3901                                                 XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.ButtonEvent.x, xevent.ButtonEvent.y, out xevent.ButtonEvent.x, out xevent.ButtonEvent.y, out dummy);
3902                                                 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3903                                         }
3904
3905                                         if (Grab.Hwnd != IntPtr.Zero) {
3906                                                 msg.hwnd = Grab.Hwnd;
3907                                         }
3908
3909                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3910                                         mouse_position.X = xevent.ButtonEvent.x;
3911                                         mouse_position.Y = xevent.ButtonEvent.y;
3912
3913                                         // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3914                                         // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after 
3915                                         // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3916                                         if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3917                                                 XEvent motionEvent = new XEvent ();
3918                                                 motionEvent.type = XEventName.MotionNotify;
3919                                                 motionEvent.MotionEvent.display = DisplayHandle;
3920                                                 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3921                                                 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3922                                                 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3923                                                 hwnd.Queue.EnqueueLocked (motionEvent);
3924                                         }
3925                                         break;
3926                                 }
3927
3928                                 case XEventName.MotionNotify: {
3929                                         if (client) {
3930                                                 #if DriverDebugExtra
3931                                                         Console.WriteLine("GetMessage(): Window {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y);
3932                                                 #endif
3933
3934                                                 if (Grab.Hwnd != IntPtr.Zero) {
3935                                                         msg.hwnd = Grab.Hwnd;
3936                                                 } else {
3937                                                         if (hwnd.Enabled) {
3938                                                                 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3939                                                         }
3940                                                 }
3941
3942                                                 if (xevent.MotionEvent.is_hint != 0)
3943                                                 {
3944                                                         IntPtr root, child;
3945                                                         int mask;
3946                                                         XQueryPointer (DisplayHandle, xevent.AnyEvent.window,
3947                                                                                         out root, out child,
3948                                                                                         out xevent.MotionEvent.x_root, 
3949                                                                                         out xevent.MotionEvent.y_root,
3950                                                                                         out xevent.MotionEvent.x,      
3951                                                                                         out xevent.MotionEvent.y, out mask);
3952                                                 }
3953
3954                                                 msg.message = Msg.WM_MOUSEMOVE;
3955                                                 msg.wParam = GetMousewParam(0);
3956                                                 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3957
3958                                                 if (!hwnd.Enabled) {
3959                                                         IntPtr dummy;
3960
3961                                                         msg.hwnd = hwnd.EnabledHwnd;
3962                                                         XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy);
3963                                                         msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3964                                                 }
3965
3966                                                 mouse_position.X = xevent.MotionEvent.x;
3967                                                 mouse_position.Y = xevent.MotionEvent.y;
3968
3969                                                 if ((HoverState.Timer.Enabled) &&
3970                                                     (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3971                                                     ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3972                                                     ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3973                                                     ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3974                                                         HoverState.Timer.Stop();
3975                                                         HoverState.Timer.Start();
3976                                                         HoverState.X = mouse_position.X;
3977                                                         HoverState.Y = mouse_position.Y;
3978                                                 }
3979
3980                                                 break;
3981                                         } else {
3982                                                 HitTest ht;
3983                                                 IntPtr dummy;
3984                                                 int screen_x;
3985                                                 int screen_y;
3986
3987                                                 #if DriverDebugExtra
3988                                                         Console.WriteLine("GetMessage(): non-client area {0:X} MotionNotify x={1} y={2}", client ? hwnd.client_window.ToInt32() : hwnd.whole_window.ToInt32(), xevent.MotionEvent.x, xevent.MotionEvent.y);
3989                                                 #endif
3990                                                 msg.message = Msg.WM_NCMOUSEMOVE;
3991
3992                                                 if (!hwnd.Enabled) {
3993                                                         msg.hwnd = hwnd.EnabledHwnd;
3994                                                         XTranslateCoordinates(DisplayHandle, xevent.AnyEvent.window, Hwnd.ObjectFromHandle(msg.hwnd).ClientWindow, xevent.MotionEvent.x, xevent.MotionEvent.y, out xevent.MotionEvent.x, out xevent.MotionEvent.y, out dummy);
3995                                                         msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3996                                                 }
3997
3998                                                 ht = NCHitTest (hwnd, xevent.MotionEvent.x, xevent.MotionEvent.y);
3999                                                 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
4000
4001                                                 mouse_position.X = xevent.MotionEvent.x;
4002                                                 mouse_position.Y = xevent.MotionEvent.y;
4003                                         }
4004
4005                                         break;
4006                                 }
4007
4008                                 case XEventName.EnterNotify: {
4009                                         if (!hwnd.Enabled) {
4010                                                 goto ProcessNextMessage;
4011                                         }
4012                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal && xevent.CrossingEvent.window != hwnd.client_window) {
4013                                                 goto ProcessNextMessage;
4014                                         }
4015                                         msg.message = Msg.WM_MOUSE_ENTER;
4016                                         HoverState.X = xevent.CrossingEvent.x;
4017                                         HoverState.Y = xevent.CrossingEvent.y;
4018                                         HoverState.Timer.Enabled = true;
4019                                         HoverState.Window = xevent.CrossingEvent.window;
4020
4021                                         // Win32 sends a WM_MOUSEMOVE after mouse enter
4022                                         XEvent motionEvent = new XEvent ();
4023                                         motionEvent.type = XEventName.MotionNotify;
4024                                         motionEvent.MotionEvent.display = DisplayHandle;
4025                                         motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
4026                                         motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
4027                                         motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
4028                                         hwnd.Queue.EnqueueLocked (motionEvent);
4029                                         break;
4030                                 }
4031
4032                                 case XEventName.LeaveNotify: {
4033                                         if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
4034                                                 WindowUngrabbed (hwnd.Handle);
4035                                                 goto ProcessNextMessage;
4036                                         }
4037                                         if (!hwnd.Enabled) {
4038                                                 goto ProcessNextMessage;
4039                                         }
4040                                         if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
4041                                                 goto ProcessNextMessage;
4042                                         }
4043
4044                                         // Reset the cursor explicitly on X11.
4045                                         // X11 remembers the last set cursor for the window and in cases where 
4046                                         // the control won't get a WM_SETCURSOR X11 will restore the last 
4047                                         // known cursor, which we don't want.
4048                                         // 
4049                                         SetCursor (hwnd.client_window, IntPtr.Zero);
4050
4051                                         msg.message=Msg.WM_MOUSELEAVE;
4052                                         HoverState.Timer.Enabled = false;
4053                                         HoverState.Window = IntPtr.Zero;
4054                                         break;
4055                                 }
4056
4057                                 #if later
4058                                 case XEventName.CreateNotify: {
4059                                         if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
4060                                                 msg.message = WM_CREATE;
4061                                                 // Set up CreateStruct
4062                                         } else {
4063                                                 goto ProcessNextMessage;
4064                                         }
4065                                         break;
4066                                 }
4067                                 #endif
4068
4069
4070                                 case XEventName.ReparentNotify: {
4071                                         if (hwnd.parent == null) {      // Toplevel
4072                                                 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
4073                                                         hwnd.Reparented = true;
4074
4075                                                         // The location given by the event is not reliable between different wm's, 
4076                                                         // so use an alternative way of getting it.
4077                                                         Point location = GetTopLevelWindowLocation (hwnd);
4078                                                         hwnd.X = location.X;
4079                                                         hwnd.Y = location.Y;
4080
4081                                                         if (hwnd.opacity != 0xffffffff) {
4082                                                                 IntPtr opacity;
4083
4084                                                                 opacity = (IntPtr)(Int32)hwnd.opacity;
4085                                                                 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4086                                                         }
4087                                                         SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
4088                                                         goto ProcessNextMessage;
4089                                                 } else {
4090                                                         hwnd.Reparented = false;
4091                                                         goto ProcessNextMessage;
4092                                                 }
4093                                         }
4094                                         goto ProcessNextMessage;
4095                                 }
4096
4097                                 case XEventName.ConfigureNotify: {
4098                                         if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {        // Ignore events for children (SubstructureNotify) and client areas
4099                                                 #if DriverDebugExtra
4100                                                         Console.WriteLine("GetMessage(): Window {0:X} ConfigureNotify x={1} y={2} width={3} height={4}", hwnd.client_window.ToInt32(), xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, xevent.ConfigureEvent.width, xevent.ConfigureEvent.height);
4101                                                 #endif
4102
4103                                                 lock (hwnd.configure_lock) {
4104                                                         Form form = Control.FromHandle (hwnd.client_window) as Form;
4105                                                         if (form != null && !hwnd.resizing_or_moving) {
4106                                                                 if (hwnd.x != form.Bounds.X || hwnd.y != form.Bounds.Y) {
4107                                                                         SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_MOVE, IntPtr.Zero);
4108                                                                         hwnd.resizing_or_moving = true;
4109                                                                 } else if (hwnd.width != form.Bounds.Width || hwnd.height != form.Bounds.Height) {
4110                                                                         SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_SIZE, IntPtr.Zero);
4111                                                                         hwnd.resizing_or_moving = true;
4112                                                                 }
4113                                                                 if (hwnd.resizing_or_moving)
4114                                                                         SendMessage (form.Handle, Msg.WM_ENTERSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
4115                                                         }
4116         
4117                                                         SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4118                                                         hwnd.configure_pending = false;
4119         
4120                                                         // We need to adjust our client window to track the resize of whole_window
4121                                                         if (hwnd.whole_window != hwnd.client_window)
4122                                                                 PerformNCCalc(hwnd);
4123                                                 }
4124                                         }
4125                                         goto ProcessNextMessage;
4126                                 }
4127
4128                                 case XEventName.FocusIn: {
4129                                         // We received focus. We use X11 focus only to know if the app window does or does not have focus
4130                                         // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
4131                                         // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know 
4132                                         // about it having focus again
4133                                         if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4134                                                 goto ProcessNextMessage;
4135                                         }
4136
4137                                         if (FocusWindow == IntPtr.Zero) {
4138                                                 Control c = Control.FromHandle (hwnd.client_window);
4139                                                 if (c == null)
4140                                                         goto ProcessNextMessage;
4141                                                 Form form = c.FindForm ();
4142                                                 if (form == null)
4143                                                         goto ProcessNextMessage;
4144                                                 if (ActiveWindow != form.Handle) {
4145                                                         ActiveWindow = form.Handle;
4146                                                         SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
4147                                                 }
4148                                                 goto ProcessNextMessage;
4149                                         }
4150                                         SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
4151                                         Keyboard.FocusIn (FocusWindow);
4152                                         goto ProcessNextMessage;
4153                                 }
4154
4155                                 case XEventName.FocusOut: {
4156                                         // Se the comment for our FocusIn handler
4157                                         if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4158                                                 goto ProcessNextMessage;
4159                                         }
4160
4161                                         while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
4162                                                 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
4163                                         }
4164
4165                                         Keyboard.FocusOut(hwnd.client_window);
4166                                         SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
4167                                         goto ProcessNextMessage;
4168                                 }
4169
4170                                 case XEventName.MapNotify: {
4171                                         if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4172                                                 hwnd.mapped = true;
4173                                                 msg.message = Msg.WM_SHOWWINDOW;
4174                                                 msg.wParam = (IntPtr) 1;
4175                                                 // XXX we're missing the lParam..
4176                                                 break;
4177                                         }
4178                                         goto ProcessNextMessage;
4179                                 }
4180
4181                                 case XEventName.UnmapNotify: {
4182                                         if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4183                                                 hwnd.mapped = false;
4184                                                 msg.message = Msg.WM_SHOWWINDOW;
4185                                                 msg.wParam = (IntPtr) 0;
4186                                                 // XXX we're missing the lParam..
4187                                                 break;
4188                                         }
4189                                         goto ProcessNextMessage;
4190                                 }
4191
4192                                 case XEventName.Expose: {
4193                                         if (!hwnd.Mapped) {
4194                                                 if (client) {
4195                                                         hwnd.expose_pending = false;
4196                                                 } else {
4197                                                         hwnd.nc_expose_pending = false;
4198                                                 }
4199                                                 goto ProcessNextMessage;
4200                                         }
4201
4202                                         if (client) {
4203                                                 if (!hwnd.expose_pending) {
4204                                                         goto ProcessNextMessage;
4205                                                 }
4206                                         } else {
4207                                                 if (!hwnd.nc_expose_pending) {
4208                                                         goto ProcessNextMessage;
4209                                                 }
4210
4211                                                 switch (hwnd.border_style) {
4212                                                         case FormBorderStyle.Fixed3D: {
4213                                                                 Graphics g;
4214
4215                                                                 g = Graphics.FromHwnd(hwnd.whole_window);
4216                                                                 if (hwnd.border_static)
4217                                                                         ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4218                                                                 else
4219                                                                         ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4220                                                                 g.Dispose();
4221                                                                 break;
4222                                                         }
4223
4224                                                         case FormBorderStyle.FixedSingle: {
4225                                                                 Graphics g;
4226
4227                                                                 g = Graphics.FromHwnd(hwnd.whole_window);
4228                                                                 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4229                                                                 g.Dispose();
4230                                                                 break;
4231                                                         }
4232                                                 }
4233                                                 #if DriverDebugExtra
4234                                                         Console.WriteLine("GetMessage(): Window {0:X} Exposed non-client area {1},{2} {3}x{4}", hwnd.client_window.ToInt32(), xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4235                                                 #endif
4236
4237                                                 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4238                                                 Region region = new Region (rect);
4239                                                 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4240                                                 msg.message = Msg.WM_NCPAINT;
4241                                                 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4242                                                 msg.refobject = region;
4243                                                 break;
4244                                         }
4245                                         #if DriverDebugExtra
4246                                                 Console.WriteLine("GetMessage(): Window {0:X} Exposed area {1},{2} {3}x{4}", hwnd.client_window.ToInt32(), xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4247                                         #endif
4248                                         if (Caret.Visible == true) {
4249                                                 Caret.Paused = true;
4250                                                 HideCaret();
4251                                         }
4252
4253                                         if (Caret.Visible == true) {
4254                                                 ShowCaret();
4255                                                 Caret.Paused = false;
4256                                         }
4257                                         msg.message = Msg.WM_PAINT;
4258                                         break;
4259                                 }
4260
4261                                 case XEventName.DestroyNotify: {
4262
4263                                         // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4264                                         hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4265
4266                                         // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4267                                         if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4268                                                 CleanupCachedWindows (hwnd);
4269
4270                                                 #if DriverDebugDestroy
4271                                                         Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4272                                                 #endif
4273
4274                                                 msg.hwnd = hwnd.client_window;
4275                                                 msg.message=Msg.WM_DESTROY;
4276                                                 hwnd.Dispose();
4277                                         } else {
4278                                                 goto ProcessNextMessage;
4279                                         }
4280
4281                                         break;
4282                                 }
4283
4284                                 case XEventName.ClientMessage: {
4285                                         if (Dnd.HandleClientMessage (ref xevent)) {
4286                                                 goto ProcessNextMessage;
4287                                         }
4288
4289                                         if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4290                                                 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4291                                                 goto ProcessNextMessage;
4292                                         }
4293
4294                                         if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4295                                                 msg.message = Msg.WM_MOUSEHOVER;
4296                                                 msg.wParam = GetMousewParam(0);
4297                                                 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4298                                                 return true;
4299                                         }
4300
4301                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4302                                                 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4303                                                 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4304                                                 msg.wParam = xevent.ClientMessageEvent.ptr3;
4305                                                 msg.lParam = xevent.ClientMessageEvent.ptr4;
4306                                                 if (msg.message == (Msg)Msg.WM_QUIT)
4307                                                         return false;
4308                                                 else
4309                                                         return true;
4310                                         }
4311
4312                                         if  (xevent.ClientMessageEvent.message_type == _XEMBED) {
4313 #if DriverDebugXEmbed
4314                                                 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4315 #endif
4316
4317                                                 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4318                                                         XSizeHints hints = new XSizeHints();
4319                                                         IntPtr dummy;
4320
4321                                                         XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4322
4323                                                         hwnd.width = hints.max_width;
4324                                                         hwnd.height = hints.max_height;
4325                                                         hwnd.ClientRect = Rectangle.Empty;
4326                                                         SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4327                                                 }
4328                                         }
4329
4330                                         if  (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4331                                                 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4332                                                         SendMessage (msg.hwnd, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_CLOSE, IntPtr.Zero);
4333                                                         msg.message = Msg.WM_CLOSE;
4334                                                         return true;
4335                                                 }
4336
4337                                                 // We should not get this, but I'll leave the code in case we need it in the future
4338                                                 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4339                                                         goto ProcessNextMessage;
4340                                                 }
4341                                         }
4342                                         goto ProcessNextMessage;
4343                                 }
4344
4345                                 default: {
4346                                         goto ProcessNextMessage;
4347                                 }
4348                         }
4349
4350                         return true;
4351                 }
4352
4353                 private HitTest NCHitTest (Hwnd hwnd, int x, int y)
4354                 {
4355                         // The hit test is sent in screen coordinates
4356                         IntPtr dummy;
4357                         int screen_x, screen_y;
4358                         XTranslateCoordinates (DisplayHandle, hwnd.WholeWindow, RootWindow, x, y, out screen_x, out screen_y, out dummy);
4359                         return (HitTest) NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST, IntPtr.Zero, 
4360                                                                (IntPtr) (screen_y << 16 | screen_x & 0xFFFF));
4361                 }
4362
4363                 internal override bool GetText(IntPtr handle, out string text) {
4364
4365                         lock (XlibLock) {
4366                                 IntPtr actual_atom;
4367                                 int actual_format;
4368                                 IntPtr nitems;
4369                                 IntPtr bytes_after;
4370                                 IntPtr prop = IntPtr.Zero;
4371
4372                                 XGetWindowProperty(DisplayHandle, handle,
4373                                                    _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4374                                                    UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4375
4376                                 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4377                                         text = Marshal.PtrToStringUni (prop, (int)nitems);
4378                                         XFree (prop);
4379                                         return true;
4380                                 }
4381                                 else {
4382                                         // fallback on the non-_NET property
4383                                         IntPtr  textptr;
4384
4385                                         textptr = IntPtr.Zero;
4386
4387                                         XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4388                                         if (textptr != IntPtr.Zero) {
4389                                                 text = Marshal.PtrToStringAnsi(textptr);
4390                                                 XFree(textptr);
4391                                                 return true;
4392                                         } else {
4393                                                 text = "";
4394                                                 return false;
4395                                         }
4396                                 }
4397                         }
4398                 }
4399
4400                 internal override void GetWindowPos(IntPtr handle, bool is_toplevel, out int x, out int y, out int width, out int height, out int client_width, out int client_height) {
4401                         Hwnd            hwnd;
4402
4403                         hwnd = Hwnd.ObjectFromHandle(handle);
4404
4405                         if (hwnd != null) {
4406                                 x = hwnd.x;
4407                                 y = hwnd.y;
4408                                 width = hwnd.width;
4409                                 height = hwnd.height;
4410
4411                                 PerformNCCalc(hwnd);
4412
4413                                 client_width = hwnd.ClientRect.Width;
4414                                 client_height = hwnd.ClientRect.Height;
4415
4416                                 return;
4417                         }
4418
4419                         // Should we throw an exception or fail silently?
4420                         // throw new ArgumentException("Called with an invalid window handle", "handle");
4421
4422                         x = 0;
4423                         y = 0;
4424                         width = 0;
4425                         height = 0;
4426                         client_width = 0;
4427                         client_height = 0;
4428                 }
4429
4430                 internal override FormWindowState GetWindowState(IntPtr handle) {
4431                         Hwnd                    hwnd;
4432
4433                         hwnd = Hwnd.ObjectFromHandle(handle);
4434
4435                         if (hwnd.cached_window_state == (FormWindowState)(-1))
4436                                 hwnd.cached_window_state = UpdateWindowState (handle);
4437
4438                         return hwnd.cached_window_state;
4439                 }
4440
4441                 private FormWindowState UpdateWindowState (IntPtr handle) {
4442                         IntPtr                  actual_atom;
4443                         int                     actual_format;
4444                         IntPtr                  nitems;
4445                         IntPtr                  bytes_after;
4446                         IntPtr                  prop = IntPtr.Zero;
4447                         IntPtr                  atom;
4448                         int                     maximized;
4449                         bool                    minimized;
4450                         XWindowAttributes       attributes;
4451                         Hwnd                    hwnd;
4452
4453                         hwnd = Hwnd.ObjectFromHandle(handle);
4454
4455                         maximized = 0;
4456                         minimized = false;
4457                         XGetWindowProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, IntPtr.Zero, new IntPtr (256), false, (IntPtr)Atom.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4458                         if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4459                                 for (int i = 0; i < (long)nitems; i++) {
4460                                         atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4461                                         if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4462                                                 maximized++;
4463                                         } else if (atom == _NET_WM_STATE_HIDDEN) {
4464                                                 minimized = true;
4465                                         }
4466                                 }
4467                                 XFree(prop);
4468                         }
4469
4470                         if (minimized) {
4471                                 return FormWindowState.Minimized;
4472                         } else if (maximized == 2) {
4473                                 return FormWindowState.Maximized;
4474                         }
4475
4476                         attributes = new XWindowAttributes();
4477                         XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4478                         if (attributes.map_state == MapState.IsUnmapped) {
4479                                 return (FormWindowState)(-1);
4480                         }
4481
4482
4483                         return FormWindowState.Normal;
4484                 }
4485
4486                 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4487                         handle = Grab.Hwnd;
4488                         GrabConfined = Grab.Confined;
4489                         GrabArea = Grab.Area;
4490                 }
4491
4492                 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4493                         Hwnd    hwnd;
4494                         IntPtr  confine_to_window;
4495
4496                         confine_to_window = IntPtr.Zero;
4497
4498                         if (confine_to_handle != IntPtr.Zero) {
4499                                 XWindowAttributes       attributes = new XWindowAttributes();
4500
4501                                 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4502
4503                                 lock (XlibLock) {
4504                                         XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4505                                 }
4506                                 Grab.Area.X = attributes.x;
4507                                 Grab.Area.Y = attributes.y;
4508                                 Grab.Area.Width = attributes.width;
4509                                 Grab.Area.Height = attributes.height;
4510                                 Grab.Confined = true;
4511                                 confine_to_window = hwnd.client_window;
4512                         }
4513
4514                         Grab.Hwnd = handle;
4515
4516                         hwnd = Hwnd.ObjectFromHandle(handle);
4517
4518                         lock (XlibLock) {
4519                                 XGrabPointer(DisplayHandle, hwnd.client_window, false, 
4520                                         EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4521                                         EventMask.ButtonReleaseMask | EventMask.PointerMotionMask | 
4522                                         EventMask.PointerMotionHintMask | EventMask.LeaveWindowMask,
4523                                         GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4524                         }
4525                 }
4526
4527                 internal override void UngrabWindow(IntPtr hwnd) {
4528                         lock (XlibLock) {
4529                                 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4530                                 XFlush(DisplayHandle);
4531                         }
4532                         WindowUngrabbed (hwnd);                 
4533                 }
4534                 
4535                 private void WindowUngrabbed (IntPtr hwnd) {
4536                         bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4537                         
4538                         Grab.Hwnd = IntPtr.Zero;
4539                         Grab.Confined = false;
4540                         
4541                         if (was_grabbed) {
4542                                 // lparam should be the handle to the window gaining the mouse capture,
4543                                 // but X doesn't seem to give us that information.
4544                                 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4545                                 // X will send a NotifyUngrab, but since it comes late sometimes we're
4546                                 // calling WindowUngrabbed directly from UngrabWindow in order to send
4547                                 // this WM right away.
4548                                 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4549                         }
4550                 }
4551
4552                 internal override void HandleException(Exception e) {
4553                         StackTrace st = new StackTrace(e, true);
4554                         Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4555                         Console.WriteLine("{0}{1}", e.Message, st.ToString());
4556                 }
4557
4558                 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4559                         Hwnd    hwnd;
4560
4561                         hwnd = Hwnd.ObjectFromHandle(handle);
4562
4563                         if (clear) {
4564                                 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4565                         } else {
4566                                 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4567                         }
4568                 }
4569
4570                 internal override void InvalidateNC (IntPtr handle) {
4571                         Hwnd    hwnd;
4572
4573                         hwnd = Hwnd.ObjectFromHandle(handle);
4574
4575                         AddExpose (hwnd, hwnd.WholeWindow == hwnd.ClientWindow, 0, 0, hwnd.Width, hwnd.Height);
4576                 }
4577
4578                 internal override bool IsEnabled(IntPtr handle) {
4579                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4580                         return (hwnd != null && hwnd.Enabled);
4581                 }
4582                 
4583                 internal override bool IsVisible(IntPtr handle) {
4584                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4585                         return (hwnd != null && hwnd.visible);
4586                 }
4587
4588                 internal override void KillTimer(Timer timer) {
4589                         XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4590
4591                         if (queue == null) {
4592                                 // This isn't really an error, MS doesn't start the timer if
4593                                 // it has no assosciated queue. In this case, remove the timer
4594                                 // from the list of unattached timers (if it was enabled).
4595                                 lock (unattached_timer_list) {
4596                                         if (unattached_timer_list.Contains (timer))
4597                                                 unattached_timer_list.Remove (timer);
4598                                 }
4599                                 return;
4600                         }
4601                         queue.timer_list.Remove (timer);
4602                 }
4603
4604                 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4605                         int     dest_x_return;
4606                         int     dest_y_return;
4607                         IntPtr  child;
4608                         Hwnd    hwnd;
4609
4610                         hwnd = Hwnd.ObjectFromHandle(handle);
4611
4612                         lock (XlibLock) {
4613                                 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4614                         }
4615
4616                         x = dest_x_return;
4617                         y = dest_y_return;
4618                 }
4619
4620                 internal override void OverrideCursor(IntPtr cursor)
4621                 {
4622                         if (Grab.Hwnd != IntPtr.Zero) {
4623                                 XChangeActivePointerGrab (DisplayHandle,
4624                                                 EventMask.ButtonMotionMask |
4625                                                 EventMask.PointerMotionMask |
4626                                                 EventMask.PointerMotionHintMask |
4627                                                 EventMask.ButtonPressMask |
4628                                                 EventMask.ButtonReleaseMask,
4629                                                 cursor, IntPtr.Zero);
4630                                 return;
4631                         }
4632
4633                         OverrideCursorHandle = cursor;
4634                 }
4635
4636                 internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
4637                         PaintEventArgs  paint_event;
4638                         Hwnd            hwnd;
4639                         Hwnd            paint_hwnd;
4640                         
4641                         // 
4642                         // handle  (and paint_hwnd) refers to the window that is should be painted.
4643                         // msg.HWnd (and hwnd) refers to the window that got the paint message.
4644                         // 
4645                         
4646                         hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
4647                         if (msg.HWnd == handle) {
4648                                 paint_hwnd = hwnd;
4649                         } else {
4650                                 paint_hwnd = Hwnd.ObjectFromHandle (handle);
4651                         }
4652         
4653                         if (Caret.Visible == true) {
4654                                 Caret.Paused = true;
4655                                 HideCaret();
4656                         }
4657
4658                         Graphics dc;
4659
4660                         if (client) {
4661                                 dc = Graphics.FromHwnd (paint_hwnd.client_window);
4662
4663                                 Region clip_region = new Region ();
4664                                 clip_region.MakeEmpty();
4665
4666                                 foreach (Rectangle r in hwnd.ClipRectangles) {
4667                                         clip_region.Union (r);
4668                                 }
4669
4670                                 if (hwnd.UserClip != null) {
4671                                         clip_region.Intersect(hwnd.UserClip);
4672                                 }
4673
4674                                 dc.Clip = clip_region;
4675                                 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4676                                 hwnd.expose_pending = false;
4677
4678                                 hwnd.ClearInvalidArea();
4679
4680                                 hwnd.drawing_stack.Push (paint_event);
4681                                 hwnd.drawing_stack.Push (dc);
4682
4683                                 return paint_event;
4684                         } else {
4685                                 dc = Graphics.FromHwnd (paint_hwnd.whole_window);
4686
4687                                 if (!hwnd.nc_invalid.IsEmpty) {
4688                                         dc.SetClip (hwnd.nc_invalid);
4689                                         paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4690                                 } else {
4691                                         paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4692                                 }
4693                                 hwnd.nc_expose_pending = false;
4694
4695                                 hwnd.ClearNcInvalidArea ();
4696
4697                                 hwnd.drawing_stack.Push (paint_event);
4698                                 hwnd.drawing_stack.Push (dc);
4699
4700                                 return paint_event;
4701                         }
4702                 }
4703
4704                 internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client) {
4705                         Hwnd    hwnd;
4706
4707                         hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
4708
4709                         Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4710                         dc.Flush();
4711                         dc.Dispose();
4712                         
4713                         PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4714                         pe.SetGraphics (null);
4715                         pe.Dispose ();
4716
4717                         if (Caret.Visible == true) {
4718                                 ShowCaret();
4719                                 Caret.Paused = false;
4720                         }
4721                 }
4722
4723                 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4724                 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4725                         XEventQueue queue = (XEventQueue) queue_id;
4726                         bool    pending;
4727
4728                         if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4729                                 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet");    // FIXME - Implement PM_NOREMOVE flag
4730                         }
4731
4732                         pending = false;
4733                         if (queue.Count > 0) {
4734                                 pending = true;
4735                         } else {
4736                                 // Only call UpdateMessageQueue if real events are pending 
4737                                 // otherwise we go to sleep on the socket
4738                                 if (XPending(DisplayHandle) != 0) {
4739                                         UpdateMessageQueue((XEventQueue)queue_id);
4740                                         pending = true;
4741                                 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4742                                         pending = true;
4743                                 }
4744                         }
4745
4746                         CheckTimers(queue.timer_list, DateTime.UtcNow);
4747
4748                         if (!pending) {
4749                                 return false;
4750                         }
4751                         return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4752                 }
4753
4754                 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4755                         XEvent xevent = new XEvent ();
4756                         Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4757
4758                         xevent.type = XEventName.ClientMessage;
4759                         xevent.ClientMessageEvent.display = DisplayHandle;
4760
4761                         if (hwnd != null) {
4762                                 xevent.ClientMessageEvent.window = hwnd.whole_window;
4763                         } else {
4764                                 xevent.ClientMessageEvent.window = IntPtr.Zero;
4765                         }
4766
4767                         xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4768                         xevent.ClientMessageEvent.format = 32;
4769                         xevent.ClientMessageEvent.ptr1 = handle;
4770                         xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4771                         xevent.ClientMessageEvent.ptr3 = wparam;
4772                         xevent.ClientMessageEvent.ptr4 = lparam;
4773
4774                         if (hwnd != null)
4775                                 hwnd.Queue.EnqueueLocked (xevent);
4776                         else
4777                                 ThreadQueue(Thread.CurrentThread).EnqueueLocked (xevent);
4778
4779                         return true;
4780                 }
4781
4782                 internal override void PostQuitMessage(int exitCode) {
4783                         ApplicationContext ctx = Application.MWFThread.Current.Context;
4784                         Form f = ctx != null ? ctx.MainForm : null;
4785                         if (f != null)
4786                                 PostMessage (Application.MWFThread.Current.Context.MainForm.window.Handle, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4787                         else
4788                                 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4789                         XFlush(DisplayHandle);
4790                 }
4791
4792                 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4793                 {
4794                         // TODO
4795                 }
4796
4797                 internal override void RequestNCRecalc(IntPtr handle) {
4798                         Hwnd                            hwnd;
4799
4800                         hwnd = Hwnd.ObjectFromHandle(handle);
4801
4802                         if (hwnd == null) {
4803                                 return;
4804                         }
4805
4806                         PerformNCCalc(hwnd);
4807                         SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4808                         InvalidateNC(handle);
4809                 }
4810
4811                 internal override void ResetMouseHover(IntPtr handle) {
4812                         Hwnd    hwnd;
4813
4814                         hwnd = Hwnd.ObjectFromHandle(handle);
4815                         if (hwnd == null) {
4816                                 return;
4817                         }
4818
4819                         HoverState.Timer.Enabled = true;
4820                         HoverState.X = mouse_position.X;
4821                         HoverState.Y = mouse_position.Y;
4822                         HoverState.Window = handle;
4823                 }
4824
4825
4826                 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4827                         int     dest_x_return;
4828                         int     dest_y_return;
4829                         IntPtr  child;
4830                         Hwnd    hwnd;
4831
4832                         hwnd = Hwnd.ObjectFromHandle(handle);
4833
4834                         lock (XlibLock) {
4835                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4836                         }
4837
4838                         x = dest_x_return;
4839                         y = dest_y_return;
4840                 }
4841
4842                 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4843                         int     dest_x_return;
4844                         int     dest_y_return;
4845                         IntPtr  child;
4846                         Hwnd    hwnd;
4847
4848                         hwnd = Hwnd.ObjectFromHandle(handle);
4849
4850                         lock (XlibLock) {
4851                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4852                         }
4853
4854                         Form form = Control.FromHandle (handle) as Form;
4855                         if (form != null && form.window_manager != null) {
4856                                 dest_y_return -= form.window_manager.TitleBarHeight;
4857                         }
4858
4859                         x = dest_x_return;
4860                         y = dest_y_return;
4861                 }
4862
4863                 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4864                         Hwnd            hwnd;
4865                         IntPtr          gc;
4866                         XGCValues       gc_values;
4867
4868                         hwnd = Hwnd.ObjectFromHandle(handle);
4869
4870                         Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4871                         if (!r.IsEmpty) {
4872                                 /* We have an invalid area in the window we're scrolling. 
4873                                    Adjust our stored invalid rectangle to to match the scrolled amount */
4874
4875                                 r.X += XAmount;
4876                                 r.Y += YAmount;
4877
4878                                 if (r.X < 0) {
4879                                         r.Width += r.X;
4880                                         r.X =0;
4881                                 }
4882
4883                                 if (r.Y < 0) {
4884                                         r.Height += r.Y;
4885                                         r.Y =0;
4886                                 }
4887
4888                                 if (area.Contains (hwnd.Invalid))
4889                                         hwnd.ClearInvalidArea ();
4890                                 hwnd.AddInvalidArea(r);
4891                         }
4892
4893                         gc_values = new XGCValues();
4894
4895                         if (with_children) {
4896                                 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4897                         }
4898
4899                         gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4900
4901                         Rectangle visible_rect = GetTotalVisibleArea (hwnd.client_window);
4902                         visible_rect.Intersect (area);
4903
4904                         Rectangle dest_rect = visible_rect;
4905                         dest_rect.Y += YAmount;
4906                         dest_rect.X += XAmount;
4907                         dest_rect.Intersect (area);
4908
4909                         Point src = new Point (dest_rect.X - XAmount, dest_rect.Y - YAmount);
4910                         XCopyArea (DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src.X, src.Y, 
4911                                         dest_rect.Width, dest_rect.Height, dest_rect.X, dest_rect.Y);
4912
4913                         Rectangle dirty_area = GetDirtyArea (area, dest_rect, XAmount, YAmount);
4914                         AddExpose (hwnd, true, dirty_area.X, dirty_area.Y, dirty_area.Width, dirty_area.Height);
4915
4916                         XFreeGC(DisplayHandle, gc);
4917                 }
4918
4919                 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4920                         Hwnd            hwnd;
4921                         Rectangle       rect;
4922
4923                         hwnd = Hwnd.GetObjectFromWindow(handle);
4924
4925                         rect = hwnd.ClientRect;
4926                         rect.X = 0;
4927                         rect.Y = 0;
4928                         ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4929                 }
4930
4931                 Rectangle GetDirtyArea (Rectangle total_area, Rectangle valid_area, int XAmount, int YAmount)
4932                 {
4933                         Rectangle dirty_area = total_area;
4934
4935                         if (YAmount > 0)
4936                                 dirty_area.Height -= valid_area.Height;
4937                         else if (YAmount < 0) {
4938                                 dirty_area.Height -= valid_area.Height;
4939                                 dirty_area.Y += valid_area.Height;
4940                         }
4941
4942                         if (XAmount > 0)
4943                                 dirty_area.Width -= valid_area.Width;
4944                         else if (XAmount < 0) {
4945                                 dirty_area.Width -= valid_area.Width;
4946                                 dirty_area.X += valid_area.Width;
4947                         }
4948
4949                         return dirty_area;
4950                 }
4951
4952                 Rectangle GetTotalVisibleArea (IntPtr handle)
4953                 {
4954                         Control c = Control.FromHandle (handle);
4955
4956                         Rectangle visible_area = c.ClientRectangle;
4957                         visible_area.Location = c.PointToScreen (Point.Empty);
4958
4959                         for (Control parent = c.Parent; parent != null; parent = parent.Parent) {
4960                                 if (!parent.IsHandleCreated || !parent.Visible)
4961                                         return visible_area; // Non visible, not need to finish computations
4962
4963                                 Rectangle r = parent.ClientRectangle;
4964                                 r.Location = parent.PointToScreen (Point.Empty);
4965
4966                                 visible_area.Intersect (r);
4967                         }
4968
4969                         // If region is null, the entire area is visible.
4970                         // Get the area not obscured otherwise.
4971                         Region visible_region = GetVisibleRegion (c, visible_area);
4972                         if (visible_region != null) {
4973                                 RectangleF rectf = visible_region.GetBounds (Hwnd.GraphicsContext);
4974                                 visible_area = new Rectangle ((int) rectf.X, (int) rectf.Y,
4975                                                 (int) rectf.Width, (int) rectf.Height);
4976
4977                                 visible_region.Dispose ();
4978                         }
4979
4980                         visible_area.Location = c.PointToClient (visible_area.Location);
4981                         return visible_area;
4982                 }
4983
4984                 // Obscured area by other toplevel windows
4985                 Region GetVisibleRegion (Control c, Rectangle visible_area)
4986                 {
4987                         Region visible_region = null;
4988                         IntPtr Root;
4989                         IntPtr Parent;
4990                         IntPtr Children;
4991                         int ChildCount;
4992
4993                         Control form = c.FindForm ();
4994                         if (form == null || !form.IsHandleCreated)
4995                                 return null;
4996
4997                         Hwnd hwnd = Hwnd.GetObjectFromWindow (form.Handle);
4998                         IntPtr form_handle = hwnd.whole_window;
4999
5000                         lock (XlibLock) {
5001                                 XQueryTree (DisplayHandle, RootWindow, out Root, out Parent, out Children, out ChildCount);
5002                         }
5003
5004                         int intptr_size = IntPtr.Size;
5005                         bool above = false;
5006
5007                         for (int i = 0; i < ChildCount; i++) {
5008                                 IntPtr window = Marshal.ReadIntPtr (Children, i * intptr_size);
5009
5010                                 XWindowAttributes win_attrs = new XWindowAttributes ();
5011                                 lock (XlibLock) {
5012                                         XGetWindowAttributes (DisplayHandle, window, ref win_attrs);
5013                                 }
5014
5015                                 Rectangle win_area = new Rectangle (win_attrs.x, win_attrs.y, 
5016                                                 win_attrs.width, win_attrs.height);
5017
5018                                 if (win_attrs.map_state != MapState.IsViewable || !win_area.IntersectsWith (visible_area))
5019                                         continue;
5020
5021                                 IntPtr SubChildren;
5022                                 int SubChildCount;
5023
5024                                 if (above) {
5025                                         if (visible_region == null)
5026                                                 visible_region = new Region (visible_area);
5027
5028                                         visible_region.Exclude (win_area);
5029                                         continue;
5030                                 }
5031
5032                                 lock (XlibLock) {
5033                                         XQueryTree (DisplayHandle, window, out Root, out Parent, out SubChildren, out SubChildCount);
5034                                 }
5035
5036                                 if (SubChildren != IntPtr.Zero) {
5037                                         IntPtr sub_win = new IntPtr (Marshal.ReadInt32 (SubChildren));
5038
5039                                         lock (XlibLock) {
5040                                                 XFree (SubChildren);
5041                                         }
5042
5043                                         if (sub_win == form_handle)
5044                                                 above = true;
5045                                 }
5046                         }
5047
5048                         if (Children != IntPtr.Zero) {
5049                                 lock (XlibLock) {
5050                                         XFree (Children);
5051                                 }
5052                         }
5053
5054                         return visible_region;
5055                 }
5056
5057                 internal override void SendAsyncMethod (AsyncMethodData method) {
5058                         Hwnd    hwnd;
5059                         XEvent  xevent = new XEvent ();
5060
5061                         hwnd = Hwnd.ObjectFromHandle(method.Handle);
5062
5063                         xevent.type = XEventName.ClientMessage;
5064                         xevent.ClientMessageEvent.display = DisplayHandle;
5065                         xevent.ClientMessageEvent.window = method.Handle;
5066                         xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
5067                         xevent.ClientMessageEvent.format = 32;
5068                         xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
5069
5070                         hwnd.Queue.EnqueueLocked (xevent);
5071
5072                         WakeupMain ();
5073                 }
5074
5075                 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
5076
5077                 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
5078                 {
5079                         Hwnd    h;
5080                         h = Hwnd.ObjectFromHandle(hwnd);
5081
5082                         if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
5083                                 AsyncMethodResult       result;
5084                                 AsyncMethodData         data;
5085
5086                                 result = new AsyncMethodResult ();
5087                                 data = new AsyncMethodData ();
5088
5089                                 data.Handle = hwnd;
5090                                 data.Method = new WndProcDelegate (NativeWindow.WndProc);
5091                                 data.Args = new object[] { hwnd, message, wParam, lParam };
5092                                 data.Result = result;
5093                                 
5094                                 SendAsyncMethod (data);
5095                                 #if DriverDebug || DriverDebugThreads
5096                                 Console.WriteLine ("Sending {0} message across.", message);
5097                                 #endif
5098
5099                                 return IntPtr.Zero;
5100                         }
5101                         return NativeWindow.WndProc(hwnd, message, wParam, lParam);
5102                 }
5103
5104                 internal override int SendInput(IntPtr handle, Queue keys) { 
5105                         if (handle == IntPtr.Zero)
5106                                 return 0;
5107
5108                         int count = keys.Count;
5109                         Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5110
5111                         while (keys.Count > 0) {
5112                         
5113                                 MSG msg = (MSG)keys.Dequeue();
5114
5115                                 XEvent xevent = new XEvent ();
5116
5117                                 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
5118                                 xevent.KeyEvent.display = DisplayHandle;
5119
5120                                 if (hwnd != null) {
5121                                         xevent.KeyEvent.window = hwnd.whole_window;
5122                                 } else {
5123                                         xevent.KeyEvent.window = IntPtr.Zero;
5124                                 }
5125
5126                                 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
5127
5128                                 hwnd.Queue.EnqueueLocked (xevent);
5129                         }
5130                         return count;
5131                 }
5132
5133                 internal override void SetAllowDrop (IntPtr handle, bool value)
5134                 {
5135                         // We allow drop on all windows
5136                 }
5137
5138                 internal override DragDropEffects StartDrag (IntPtr handle, object data,
5139                                 DragDropEffects allowed_effects)
5140                 {
5141                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5142
5143                         if (hwnd == null)
5144                                 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
5145
5146                         return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
5147                 }
5148
5149                 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
5150                         Form form = Control.FromHandle (handle) as Form;
5151                         if (form != null && form.window_manager == null) {
5152                                 CreateParams cp = form.GetCreateParams ();
5153                                 if (border_style == FormBorderStyle.FixedToolWindow ||
5154                                      border_style == FormBorderStyle.SizableToolWindow || 
5155                                      cp.IsSet (WindowExStyles.WS_EX_TOOLWINDOW)) {
5156                                         form.window_manager = new ToolWindowManager (form);
5157                                 }
5158                         }
5159                         
5160                         RequestNCRecalc(handle);
5161                 }
5162
5163                 internal override void SetCaretPos(IntPtr handle, int x, int y) {
5164                         if (Caret.Hwnd == handle) {
5165                                 Caret.Timer.Stop();
5166                                 HideCaret();
5167
5168                                 Caret.X = x;
5169                                 Caret.Y = y;
5170
5171                                 Keyboard.SetCaretPos (Caret, handle, x, y);
5172
5173                                 if (Caret.Visible == true) {
5174                                         ShowCaret();
5175                                         Caret.Timer.Start();
5176                                 }
5177                         }
5178                 }
5179
5180                 internal override void SetClipRegion(IntPtr handle, Region region) {
5181                         Hwnd    hwnd;
5182
5183                         hwnd = Hwnd.ObjectFromHandle(handle);
5184                         if (hwnd == null) {
5185                                 return;
5186                         }
5187
5188                         hwnd.UserClip = region;
5189                 }
5190
5191                 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
5192                         Hwnd    hwnd;
5193
5194                         if (OverrideCursorHandle == IntPtr.Zero) {
5195                                 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
5196                                         return;
5197                                 }
5198
5199                                 LastCursorHandle = cursor;
5200                                 LastCursorWindow = handle;
5201
5202                                 hwnd = Hwnd.ObjectFromHandle(handle);
5203                                 lock (XlibLock) {
5204                                         if (cursor != IntPtr.Zero) {
5205                                                 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
5206                                         } else {
5207                                                 XUndefineCursor(DisplayHandle, hwnd.whole_window);
5208                                         }
5209                                         XFlush(DisplayHandle);
5210                                 }
5211                                 return;
5212                         }
5213
5214                         hwnd = Hwnd.ObjectFromHandle(handle);
5215                         lock (XlibLock) {
5216                                 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
5217                         }
5218                 }
5219
5220                 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
5221                                            out int root_x, out int root_y, out int child_x, out int child_y,
5222                                            out int mask)
5223                 {
5224                         /* this code was written with the help of
5225                         glance at gdk.  I never would have realized we
5226                         needed a loop in order to traverse down in the
5227                         hierarchy.  I would have assumed you'd get the
5228                         most deeply nested child and have to do
5229                         XQueryTree to move back up the hierarchy..
5230                         stupid me, of course. */
5231                         IntPtr c;
5232
5233                         XGrabServer (display);
5234
5235                         XQueryPointer(display, w, out root, out c,
5236                                       out root_x, out root_y, out child_x, out child_y,
5237                                       out mask);
5238
5239                         if (root != w)
5240                                 c = root;
5241
5242                         IntPtr child_last = IntPtr.Zero;
5243                         while (c != IntPtr.Zero) {
5244                                 child_last = c;
5245                                 XQueryPointer(display, c, out root, out c,
5246                                               out root_x, out root_y, out child_x, out child_y,
5247                                               out mask);
5248                         }
5249                         XUngrabServer (display);
5250                         XFlush (display);
5251
5252                         child = child_last;
5253                 }
5254
5255                 internal override void SetCursorPos(IntPtr handle, int x, int y) {
5256                         if (handle == IntPtr.Zero) {
5257                                 lock (XlibLock) {
5258                                         IntPtr root, child;
5259                                         int root_x, root_y, child_x, child_y, mask;
5260
5261                                         /* we need to do a
5262                                          * QueryPointer before warping
5263                                          * because if the warp is on
5264                                          * the RootWindow, the x/y are
5265                                          * relative to the current
5266                                          * mouse position
5267                                          */
5268                                         QueryPointer (DisplayHandle, RootWindow,
5269                                                       out root,
5270                                                       out child,
5271                                                       out root_x, out root_y,
5272                                                       out child_x, out child_y,
5273                                                       out mask);
5274
5275                                         XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
5276
5277                                         XFlush (DisplayHandle);
5278
5279                                         /* then we need to a
5280                                          * QueryPointer after warping
5281                                          * to manually generate a
5282                                          * motion event for the window
5283                                          * we move into.
5284                                          */
5285                                         QueryPointer (DisplayHandle, RootWindow,
5286                                                       out root,
5287                                                       out child,
5288                                                       out root_x, out root_y,
5289                                                       out child_x, out child_y,
5290                                                       out mask);
5291
5292                                         Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
5293                                         if (child_hwnd == null) {
5294                                                 return;
5295                                         }
5296
5297                                         XEvent xevent = new XEvent ();
5298
5299                                         xevent.type = XEventName.MotionNotify;
5300                                         xevent.MotionEvent.display = DisplayHandle;
5301                                         xevent.MotionEvent.window = child_hwnd.client_window;
5302                                         xevent.MotionEvent.root = RootWindow;
5303                                         xevent.MotionEvent.x = child_x;
5304                                         xevent.MotionEvent.y = child_y;
5305                                         xevent.MotionEvent.x_root = root_x;
5306                                         xevent.MotionEvent.y_root = root_y;
5307                                         xevent.MotionEvent.state = mask;
5308
5309                                         child_hwnd.Queue.EnqueueLocked (xevent);
5310                                 }
5311                         } else {
5312                                 Hwnd    hwnd;
5313
5314                                 hwnd = Hwnd.ObjectFromHandle(handle);
5315                                 lock (XlibLock) {
5316                                         XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5317                                 }
5318                         }
5319                 }
5320
5321                 internal override void SetFocus(IntPtr handle) {
5322                         Hwnd    hwnd;
5323                         IntPtr  prev_focus_window;
5324
5325                         hwnd = Hwnd.ObjectFromHandle(handle);
5326
5327                         if (hwnd.client_window == FocusWindow) {
5328                                 return;
5329                         }
5330
5331                         // Win32 doesn't do anything if disabled
5332                         if (!hwnd.enabled)
5333                                 return;
5334
5335                         prev_focus_window = FocusWindow;
5336                         FocusWindow = hwnd.client_window;
5337
5338                         if (prev_focus_window != IntPtr.Zero) {
5339                                 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5340                         }
5341                         SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5342                         Keyboard.FocusIn (FocusWindow);
5343
5344                         //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5345                 }
5346
5347                 internal override void SetIcon(IntPtr handle, Icon icon) {
5348                         Hwnd    hwnd;
5349
5350                         hwnd = Hwnd.ObjectFromHandle(handle);
5351                         if (hwnd != null) {
5352                                 SetIcon(hwnd, icon);
5353                         }
5354                 }
5355
5356                 internal override void SetMenu(IntPtr handle, Menu menu) {
5357                         Hwnd    hwnd;
5358
5359                         hwnd = Hwnd.ObjectFromHandle(handle);
5360                         hwnd.menu = menu;
5361
5362                         RequestNCRecalc(handle);
5363                 }
5364
5365                 internal override void SetModal(IntPtr handle, bool Modal) {
5366                         if (Modal) {
5367                                 ModalWindows.Push(handle);
5368                         } else {
5369                                 if (ModalWindows.Contains(handle)) {
5370                                         ModalWindows.Pop();
5371                                 }
5372                                 if (ModalWindows.Count > 0) {
5373                                         Activate((IntPtr)ModalWindows.Peek());
5374                                 }
5375                         }
5376
5377                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5378                         Control ctrl = Control.FromHandle (handle);
5379                         SetWMStyles (hwnd, ctrl.GetCreateParams ());
5380                 }
5381
5382                 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5383                         Hwnd    hwnd;
5384
5385                         hwnd = Hwnd.ObjectFromHandle(handle);
5386                         hwnd.parent = Hwnd.ObjectFromHandle(parent);
5387
5388                         lock (XlibLock) {
5389                                 #if DriverDebug || DriverDebugParent
5390                                         Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5391                                 #endif
5392                                 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5393                         }
5394
5395                         return IntPtr.Zero;
5396                 }
5397
5398                 internal override void SetTimer (Timer timer) {
5399                         XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5400
5401                         if (queue == null) {
5402                                 // This isn't really an error, MS doesn't start the timer if
5403                                 // it has no assosciated queue at this stage (it will be
5404                                 // enabled when a window is activated).
5405                                 unattached_timer_list.Add (timer);
5406                                 return;
5407                         }
5408                         queue.timer_list.Add (timer);
5409                         WakeupMain ();
5410                 }
5411
5412                 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5413
5414                         Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5415
5416                         if (enabled) {
5417                                 lock (XlibLock) {
5418                                         int[] atoms = new int[8];
5419                                         atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5420                                         XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5421                                 }
5422                         } else {
5423                                 lock (XlibLock) {
5424                                         XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5425                                 }
5426                         }
5427                         return true;
5428                 }
5429
5430                 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5431                         Hwnd hwnd;
5432                         Hwnd hwnd_owner;
5433
5434                         hwnd = Hwnd.ObjectFromHandle(handle);
5435
5436                         if (handle_owner != IntPtr.Zero) {
5437                                 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5438                                 lock (XlibLock) {
5439                                         int[]   atoms;
5440
5441                                         atoms = new int[8];
5442
5443                                         atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5444                                         XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5445
5446                                         if (hwnd_owner != null) {
5447                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5448                                         } else {
5449                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5450                                         }
5451                                 }
5452                         } else {
5453                                 lock (XlibLock) {
5454                                         XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5455                                 }
5456                         }
5457                         return true;
5458                 }
5459
5460                 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5461                 {
5462                         Hwnd    hwnd;
5463
5464                         hwnd = Hwnd.ObjectFromHandle(handle);
5465                         hwnd.visible = visible;
5466
5467                         lock (XlibLock) {
5468                                 if (visible) {
5469                                         MapWindow(hwnd, WindowType.Both);
5470
5471                                         if (Control.FromHandle(handle) is Form) {
5472                                                 FormWindowState s;
5473
5474                                                 s = ((Form)Control.FromHandle(handle)).WindowState;
5475
5476                                                 switch(s) {
5477                                                         case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5478                                                         case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5479                                                 }
5480                                         }
5481
5482                                         SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5483                                 }
5484                                 else {
5485                                         UnmapWindow(hwnd, WindowType.Both);
5486                                 }
5487                         }
5488                         return true;
5489                 }
5490
5491                 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5492                         Control ctrl = Control.FromHandle (handle);
5493                         SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
5494                 }
5495
5496                 internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
5497                 {
5498                         Hwnd            hwnd;
5499                         XSizeHints      hints;
5500                         IntPtr          dummy;
5501
5502                         hwnd = Hwnd.ObjectFromHandle(handle);
5503                         if (hwnd == null) {
5504                                 return;
5505                         }
5506
5507                         min.Width = Math.Max (min.Width, SystemInformation.MinimumWindowSize.Width);
5508                         min.Height = Math.Max (min.Height, SystemInformation.MinimumWindowSize.Height);
5509                         
5510                         hints = new XSizeHints();
5511
5512                         XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5513                         if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5514                                 if (cp != null)
5515                                         min = TranslateWindowSizeToXWindowSize (cp, min);
5516                                 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5517                                 hints.min_width = min.Width;
5518                                 hints.min_height = min.Height;
5519                         }
5520
5521                         if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5522                                 if (cp != null)
5523                                         max = TranslateWindowSizeToXWindowSize (cp, max);
5524                                 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5525                                 hints.max_width = max.Width;
5526                                 hints.max_height = max.Height;
5527                         }
5528
5529                         if (hints.flags != IntPtr.Zero) {
5530                                 // The Metacity team has decided that they won't care about this when clicking the maximize icon, 
5531                                 // they will maximize the window to fill the screen/parent no matter what.
5532                                 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5533                                 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5534                         }
5535
5536                         if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5537                                 if (cp != null)
5538                                         maximized.Size = TranslateWindowSizeToXWindowSize (cp);
5539                                 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5540                                 hints.x = maximized.X;
5541                                 hints.y = maximized.Y;
5542                                 hints.width = maximized.Width;
5543                                 hints.height = maximized.Height;
5544
5545                                 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5546                                 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5547                         }
5548                 }
5549
5550
5551                 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5552                         Hwnd            hwnd;
5553
5554                         hwnd = Hwnd.ObjectFromHandle(handle);
5555
5556                         if (hwnd == null) {
5557                                 return;
5558                         }
5559
5560                         // Win32 automatically changes negative width/height to 0.
5561                         if (width < 0)
5562                                 width = 0;
5563                         if (height < 0)
5564                                 height = 0;
5565                                 
5566                         // X requires a sanity check for width & height; otherwise it dies
5567                         if (hwnd.zero_sized && width > 0 && height > 0) {
5568                                 if (hwnd.visible) {
5569                                         MapWindow(hwnd, WindowType.Whole);
5570                                 }
5571                                 hwnd.zero_sized = false;
5572                         }
5573
5574                         if ((width < 1) || (height < 1)) {
5575                                 hwnd.zero_sized = true;
5576                                 UnmapWindow(hwnd, WindowType.Whole);
5577                         }
5578
5579                         // Save a server roundtrip (and prevent a feedback loop)
5580                         if ((hwnd.x == x) && (hwnd.y == y) && 
5581                                 (hwnd.width == width) && (hwnd.height == height)) {
5582                                 return;
5583                         }
5584
5585                         if (!hwnd.zero_sized) {
5586                                 //Hack?
5587                                 hwnd.x = x;
5588                                 hwnd.y = y;
5589                                 hwnd.width = width;
5590                                 hwnd.height = height;
5591                                 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5592
5593                                 if (hwnd.fixed_size) {
5594                                         SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5595                                 }
5596
5597                                 lock (XlibLock) {
5598                                         Control ctrl = Control.FromHandle (handle);
5599                                         Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams (), new Size (width, height));
5600                                         MoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5601                                         PerformNCCalc(hwnd);
5602                                 }
5603                         }
5604
5605                         // Update our position/size immediately, so
5606                         // that future calls to SetWindowPos aren't
5607                         // kept from calling XMoveResizeWindow (by the
5608                         // "Save a server roundtrip" block above).
5609                         hwnd.x = x;
5610                         hwnd.y = y;
5611                         hwnd.width = width;
5612                         hwnd.height = height;
5613                         hwnd.ClientRect = Rectangle.Empty;
5614                 }
5615
5616                 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5617                         FormWindowState current_state;
5618                         Hwnd            hwnd;
5619
5620                         hwnd = Hwnd.ObjectFromHandle(handle);
5621
5622                         current_state = GetWindowState(handle);
5623
5624                         if (current_state == state) {
5625                                 return;
5626                         }
5627
5628                         switch(state) {
5629                                 case FormWindowState.Normal: {
5630                                         lock (XlibLock) {
5631                                                 if (current_state == FormWindowState.Minimized) {
5632                                                         MapWindow(hwnd, WindowType.Both);
5633                                                 } else if (current_state == FormWindowState.Maximized) {
5634                                                         SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5635                                                 }
5636                                         }
5637                                         Activate(handle);
5638                                         return;
5639                                 }
5640
5641                                 case FormWindowState.Minimized: {
5642                                         lock (XlibLock) {
5643                                                 if (current_state == FormWindowState.Maximized) {
5644                                                         SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5645                                                 }
5646                                                 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5647                                         }
5648                                         return;
5649                                 }
5650
5651                                 case FormWindowState.Maximized: {
5652                                         lock (XlibLock) {
5653                                                 if (current_state == FormWindowState.Minimized) {
5654                                                         MapWindow(hwnd, WindowType.Both);
5655                                                 }
5656
5657                                                 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5658                                         }
5659                                         Activate(handle);
5660                                         return;
5661                                 }
5662                         }
5663                 }
5664
5665                 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5666                         Hwnd    hwnd;
5667
5668                         hwnd = Hwnd.ObjectFromHandle(handle);
5669                         SetHwndStyles(hwnd, cp);
5670                         SetWMStyles(hwnd, cp);
5671                 }
5672
5673                 internal override double GetWindowTransparency(IntPtr handle)
5674                 {
5675                         return 1.0;
5676                 }
5677
5678                 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5679                         Hwnd    hwnd;
5680                         IntPtr  opacity;
5681
5682                         hwnd = Hwnd.ObjectFromHandle(handle);
5683
5684                         if (hwnd == null) {
5685                                 return;
5686                         }
5687
5688                         hwnd.opacity = (uint)(0xffffffff * transparency);
5689                         opacity = (IntPtr)((int)hwnd.opacity);
5690
5691                         IntPtr w = hwnd.whole_window;
5692                         if (hwnd.reparented)
5693                                 w = XGetParent (hwnd.whole_window);
5694                         XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5695                 }
5696
5697                 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5698                         Hwnd    hwnd = Hwnd.ObjectFromHandle(handle);
5699
5700                         if (!hwnd.mapped) {
5701                                 return false;
5702                         }
5703
5704                         if (top) {
5705                                 lock (XlibLock) {
5706                                         XRaiseWindow(DisplayHandle, hwnd.whole_window);
5707                                 }
5708                                 return true;
5709                         } else if (!bottom) {
5710                                 Hwnd    after_hwnd = null;
5711
5712                                 if (after_handle != IntPtr.Zero) {
5713                                         after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5714                                 }
5715
5716                                 XWindowChanges  values = new XWindowChanges();
5717
5718                                 if (after_hwnd == null) {
5719                                         // Work around metacity 'issues'
5720                                         int[]   atoms;
5721
5722                                         atoms = new int[2];
5723                                         atoms[0] = unixtime();
5724                                         XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5725
5726                                         XRaiseWindow(DisplayHandle, hwnd.whole_window);
5727                                         SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5728                                         return true;
5729                                         //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5730                                 }
5731
5732                                 values.sibling = after_hwnd.whole_window;
5733                                 values.stack_mode = StackMode.Below;
5734
5735                                 lock (XlibLock) {
5736                                         XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5737                                 }
5738                         } else {
5739                                 // Bottom
5740                                 lock (XlibLock) {
5741                                         XLowerWindow(DisplayHandle, hwnd.whole_window);
5742                                 }
5743                                 return true;
5744                         }
5745                         return false;
5746                 }
5747
5748                 internal override void ShowCursor(bool show) {
5749                         ;       // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5750                 }
5751
5752                 internal override object StartLoop(Thread thread) {
5753                         XEventQueue q = ThreadQueue(thread);
5754                         return q;
5755                 }
5756
5757                 internal override TransparencySupport SupportsTransparency() {
5758                         // We need to check if the x compositing manager is running
5759                         return TransparencySupport.Set;
5760                 }
5761
5762                 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5763                         GetSystrayManagerWindow();
5764
5765                         if (SystrayMgrWindow != IntPtr.Zero) {
5766                                 XSizeHints      size_hints;
5767                                 Hwnd            hwnd;
5768
5769                                 hwnd = Hwnd.ObjectFromHandle(handle);
5770                                 #if DriverDebug
5771                                         Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5772                                 #endif
5773
5774                                 // Oh boy.
5775                                 if (hwnd.client_window != hwnd.whole_window) {
5776                                         Keyboard.DestroyICForWindow (hwnd.client_window);
5777                                         XDestroyWindow(DisplayHandle, hwnd.client_window);
5778                                         hwnd.client_window = hwnd.whole_window;
5779                                 }       
5780
5781                                 /* by virtue of the way the tests are ordered when determining if it's PAINT
5782                                    or NCPAINT, client_window == whole_window will always be PAINT.  So, if we're
5783                                    waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5784                                    there's a pending expose). */
5785                                 if (hwnd.nc_expose_pending) {
5786                                         hwnd.nc_expose_pending = false;
5787                                         if (!hwnd.expose_pending)
5788                                                 hwnd.Queue.Paint.Remove (hwnd);
5789                                 }
5790
5791                                 size_hints = new XSizeHints();
5792
5793                                 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5794
5795                                 size_hints.min_width = 24;
5796                                 size_hints.min_height = 24;
5797                                 size_hints.max_width = 24;
5798                                 size_hints.max_height = 24;
5799                                 size_hints.base_width = 24;
5800                                 size_hints.base_height = 24;
5801
5802                                 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5803
5804                                 int[] atoms = new int[2];
5805                                 atoms [0] = 1;                  // Version 1
5806                                 atoms [1] = 1;                  // we want to be mapped
5807
5808                                 // This line cost me 3 days...
5809                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5810
5811                                 // Need to pick some reasonable defaults
5812                                 tt = new ToolTip();
5813                                 tt.AutomaticDelay = 350;
5814                                 tt.InitialDelay = 250;
5815                                 tt.ReshowDelay = 250;
5816                                 tt.ShowAlways = true;
5817
5818                                 if ((tip != null) && (tip != string.Empty)) {
5819                                         tt.SetToolTip(Control.FromHandle(handle), tip);
5820                                         tt.Active = true;
5821                                 } else {
5822                                         tt.Active = false;
5823                                 }
5824
5825                                 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5826
5827                                 return true;
5828                         }
5829                         tt = null;
5830                         return false;
5831                 }
5832
5833                 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5834                         Control control;
5835
5836                         control = Control.FromHandle(handle);
5837                         if (control != null && tt != null) {
5838                                 tt.SetToolTip(control, tip);
5839                                 tt.Active = true;
5840                                 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5841                                 return true;
5842                         } else {
5843                                 return false;
5844                         }
5845                 }
5846
5847                 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5848
5849                         SetVisible (handle, false, false);
5850
5851                         // The caller can now re-dock it later...
5852                         if (tt != null) {
5853                                 tt.Dispose();
5854                                 tt = null;
5855                         }
5856                 }
5857
5858 #if NET_2_0
5859                 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5860                 {
5861                         ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5862                         SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);    
5863                 }
5864 #endif
5865
5866                 internal override bool Text(IntPtr handle, string text) {
5867                         Hwnd    hwnd;
5868
5869                         hwnd = Hwnd.ObjectFromHandle(handle);
5870
5871                         lock (XlibLock) {
5872                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5873                                                 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5874
5875                                 // XXX this has problems with UTF8.
5876                                 // we need to either use the actual
5877                                 // text if it's latin-1, or convert it
5878                                 // to compound text if it's in a
5879                                 // different charset.
5880                                 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5881                         }
5882                         return true;
5883                 }
5884
5885                 internal override bool TranslateMessage(ref MSG msg) {
5886                         return Keyboard.TranslateMessage (ref msg);
5887                 }
5888
5889                 internal override void UpdateWindow(IntPtr handle) {
5890                         Hwnd    hwnd;
5891
5892                         hwnd = Hwnd.ObjectFromHandle(handle);
5893
5894                         if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5895                                 return;
5896                         }
5897
5898                         SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5899                         hwnd.Queue.Paint.Remove(hwnd);
5900                 }
5901
5902                 internal override void CreateOffscreenDrawable (IntPtr handle,
5903                                                                 int width, int height,
5904                                                                 out object offscreen_drawable)
5905                 {
5906                         IntPtr root_out;
5907                         int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5908
5909                         XGetGeometry (DisplayHandle, handle,
5910                                       out root_out,
5911                                       out x_out, out y_out,
5912                                       out width_out, out height_out,
5913                                       out border_width_out, out depth_out);
5914
5915                         IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5916
5917                         offscreen_drawable = pixmap;
5918
5919                 }
5920
5921                 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5922                 {
5923                         XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5924                 }
5925
5926                 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5927                 {
5928                         return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5929                 }
5930                 
5931                 internal override void BlitFromOffscreen (IntPtr dest_handle,
5932                                                           Graphics dest_dc,
5933                                                           object offscreen_drawable,
5934                                                           Graphics offscreen_dc,
5935                                                           Rectangle r)
5936                 {
5937                         XGCValues gc_values;
5938                         IntPtr gc;
5939
5940                         gc_values = new XGCValues();
5941
5942                         gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5943
5944                         XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5945                                    gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5946
5947                         XFreeGC (DisplayHandle, gc);
5948                 }
5949
5950                 #endregion      // Public Static Methods
5951
5952                 #region Events
5953                 internal override event EventHandler Idle;
5954                 #endregion      // Events
5955
5956 #region Xcursor imports
5957                 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
5958                 internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
5959
5960                 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
5961                 internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
5962                 
5963                 [DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
5964                 internal extern static void XcursorImagesDestroy (IntPtr images);
5965                 
5966                 [DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
5967                 internal extern static int XcursorGetDefaultSize (IntPtr display);
5968
5969                 [DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
5970                 internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
5971
5972                 [DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
5973                 internal extern static IntPtr XcursorGetTheme (IntPtr display);
5974 #endregion
5975                 #region X11 Imports
5976                 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5977                 internal extern static IntPtr XOpenDisplay(IntPtr display);
5978                 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5979                 internal extern static int XCloseDisplay(IntPtr display);                                                   
5980                 [DllImport ("libX11", EntryPoint="XSynchronize")]
5981                 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5982
5983                 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5984                 internal extern static IntPtr XCreateWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int depth, int xclass, IntPtr visual, UIntPtr valuemask, ref XSetWindowAttributes attributes);
5985                 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5986                 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5987                 [DllImport ("libX11", EntryPoint="XMapWindow")]
5988                 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5989                 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5990                 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5991                 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5992                 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5993                 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5994                 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5995                 [DllImport ("libX11", EntryPoint="XRootWindow")]
5996                 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5997                 [DllImport ("libX11", EntryPoint="XNextEvent")]
5998                 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
5999                 [DllImport ("libX11")]
6000                 internal extern static int XConnectionNumber (IntPtr diplay);
6001                 [DllImport ("libX11")]
6002                 internal extern static int XPending (IntPtr diplay);
6003                 [DllImport ("libX11", EntryPoint="XSelectInput")]
6004                 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
6005
6006                 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
6007                 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
6008
6009                 [DllImport ("libX11", EntryPoint="XReparentWindow")]
6010                 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
6011                 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
6012                 private extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
6013
6014                 internal static int MoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height)
6015                 {
6016                         int ret = XMoveResizeWindow (display, window, x, y, width, height);
6017                         Keyboard.MoveCurrentCaretPos ();
6018                         return ret;
6019                 }
6020
6021                 [DllImport ("libX11", EntryPoint="XResizeWindow")]
6022                 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
6023
6024                 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
6025                 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
6026
6027                 [DllImport ("libX11", EntryPoint="XFlush")]
6028                 internal extern static int XFlush(IntPtr display);
6029
6030                 [DllImport ("libX11", EntryPoint="XSetWMName")]
6031                 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
6032
6033                 [DllImport ("libX11", EntryPoint="XStoreName")]
6034                 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
6035
6036                 [DllImport ("libX11", EntryPoint="XFetchName")]
6037                 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
6038
6039                 [DllImport ("libX11", EntryPoint="XSendEvent")]
6040                 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
6041
6042                 [DllImport ("libX11", EntryPoint="XQueryTree")]
6043                 internal extern static int XQueryTree(IntPtr display, IntPtr window, out IntPtr root_return, out IntPtr parent_return, out IntPtr children_return, out int nchildren_return);
6044
6045                 [DllImport ("libX11", EntryPoint="XFree")]
6046                 internal extern static int XFree(IntPtr data);
6047
6048                 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
6049                 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
6050
6051                 [DllImport ("libX11", EntryPoint="XLowerWindow")]
6052                 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
6053
6054                 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
6055                 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
6056
6057                 [DllImport ("libX11", EntryPoint="XInternAtom")]
6058                 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
6059
6060                 [DllImport ("libX11", EntryPoint="XInternAtoms")]
6061                 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
6062
6063                 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
6064                 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
6065
6066                 [DllImport ("libX11", EntryPoint="XGrabPointer")]
6067                 internal extern static int XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, IntPtr cursor, IntPtr timestamp);
6068
6069                 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
6070                 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
6071
6072                 [DllImport ("libX11", EntryPoint="XQueryPointer")]
6073                 internal extern static bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr root, out IntPtr child, out int root_x, out int root_y, out int win_x, out int win_y, out int keys_buttons);
6074
6075                 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
6076                 internal extern static bool XTranslateCoordinates (IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, out int intdest_x_return,  out int dest_y_return, out IntPtr child_return);
6077
6078                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6079                 internal extern static bool XGetGeometry(IntPtr display, IntPtr window, out IntPtr root, out int x, out int y, out int width, out int height, out int border_width, out int depth);
6080
6081                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6082                 internal extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, out int width, out int height, IntPtr border_width, IntPtr depth);
6083
6084                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6085                 internal extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, out int x, out int y, IntPtr width, IntPtr height, IntPtr border_width, IntPtr depth);
6086
6087                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6088                 internal extern static bool XGetGeometry(IntPtr display, IntPtr window, IntPtr root, IntPtr x, IntPtr y, out int width, out int height, IntPtr border_width, IntPtr depth);
6089
6090                 [DllImport ("libX11", EntryPoint="XWarpPointer")]
6091                 internal extern static uint XWarpPointer(IntPtr display, IntPtr src_w, IntPtr dest_w, int src_x, int src_y, uint src_width, uint src_height, int dest_x, int dest_y);
6092
6093                 [DllImport ("libX11", EntryPoint="XClearWindow")]
6094                 internal extern static int XClearWindow(IntPtr display, IntPtr window);
6095
6096                 [DllImport ("libX11", EntryPoint="XClearArea")]
6097                 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
6098
6099                 // Colormaps
6100                 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
6101                 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
6102
6103                 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
6104                 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
6105
6106                 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
6107                 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
6108
6109                 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
6110                 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
6111
6112                 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
6113                 internal extern static int XDefaultScreen(IntPtr display);
6114
6115                 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
6116                 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
6117
6118                 [DllImport ("libX11", EntryPoint="XLookupColor")]
6119                 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
6120
6121                 [DllImport ("libX11", EntryPoint="XAllocColor")]
6122                 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
6123
6124                 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
6125                 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
6126
6127                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6128                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
6129
6130                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6131                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
6132
6133                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6134                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
6135
6136                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6137                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
6138
6139                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6140                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
6141
6142                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6143                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
6144
6145                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6146                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
6147
6148                 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
6149                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
6150
6151                 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
6152                 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
6153
6154                 // Drawing
6155                 [DllImport ("libX11", EntryPoint="XCreateGC")]
6156                 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
6157
6158                 [DllImport ("libX11", EntryPoint="XFreeGC")]
6159                 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
6160
6161                 [DllImport ("libX11", EntryPoint="XSetFunction")]
6162                 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
6163
6164                 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
6165                 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
6166
6167                 [DllImport ("libX11", EntryPoint="XDrawLine")]
6168                 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
6169
6170                 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
6171                 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
6172
6173                 [DllImport ("libX11", EntryPoint="XFillRectangle")]
6174                 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
6175
6176                 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
6177                 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
6178
6179                 [DllImport ("libX11", EntryPoint="XCopyArea")]
6180                 internal extern static int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y);
6181
6182                 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
6183                 internal extern static int XGetWindowProperty(IntPtr display, IntPtr window, IntPtr atom, IntPtr long_offset, IntPtr long_length, bool delete, IntPtr req_type, out IntPtr actual_type, out int actual_format, out IntPtr nitems, out IntPtr bytes_after, ref IntPtr prop);
6184
6185                 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
6186                 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
6187
6188                 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
6189                 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
6190
6191                 [DllImport ("libX11", EntryPoint="XDefineCursor")]
6192                 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
6193
6194                 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
6195                 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
6196
6197                 [DllImport ("libX11", EntryPoint="XFreeCursor")]
6198                 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
6199
6200                 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
6201                 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
6202
6203                 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
6204                 internal extern static IntPtr XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foreground_color, ref XColor background_color, int x_hot, int y_hot);
6205
6206                 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
6207                 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
6208
6209                 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
6210                 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
6211
6212                 [DllImport ("libX11", EntryPoint="XFreePixmap")]
6213                 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
6214
6215                 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
6216                 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
6217
6218                 [DllImport ("libX11", EntryPoint="XQueryExtension")]
6219                 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
6220
6221                 [DllImport ("libX11", EntryPoint="XWhitePixel")]
6222                 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
6223
6224                 [DllImport ("libX11", EntryPoint="XBlackPixel")]
6225                 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
6226
6227                 [DllImport ("libX11", EntryPoint="XGrabServer")]
6228                 internal extern static void XGrabServer(IntPtr display);
6229
6230                 [DllImport ("libX11", EntryPoint="XUngrabServer")]
6231                 internal extern static void XUngrabServer(IntPtr display);
6232
6233                 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
6234                 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
6235
6236                 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
6237                 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6238
6239                 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
6240                 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6241
6242                 [DllImport ("libX11", EntryPoint="XSetWMHints")]
6243                 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
6244
6245                 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
6246                 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
6247
6248                 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
6249                 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
6250
6251                 [DllImport ("libX11", EntryPoint="XGetErrorText")]
6252                 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
6253
6254                 [DllImport ("libX11", EntryPoint="XInitThreads")]
6255                 internal extern static int XInitThreads();
6256
6257                 [DllImport ("libX11", EntryPoint="XConvertSelection")]
6258                 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
6259
6260                 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
6261                 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
6262
6263                 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
6264                 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
6265
6266                 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
6267                 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
6268
6269                 [DllImport ("libX11", EntryPoint="XSetForeground")]
6270                 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
6271
6272                 [DllImport ("libX11", EntryPoint="XSetBackground")]
6273                 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
6274
6275                 [DllImport ("libX11", EntryPoint="XBell")]
6276                 internal extern static int XBell(IntPtr display, int percent);
6277
6278                 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
6279                 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
6280
6281                 [DllImport ("libX11", EntryPoint="XFilterEvent")]
6282                 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
6283
6284                 [DllImport ("libX11")]
6285                 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
6286
6287                 [DllImport ("libX11")]
6288                 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);
6289                 #endregion
6290         }
6291 }