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