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