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