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