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