2008-05-02 Carlos Alberto Cortez <calberto.cortez@gmail.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  Size MinWindowTrackSize {
2163                         get {
2164                                 return new Size(1, 1);
2165                         }
2166                 }
2167
2168                 internal override Keys ModifierKeys {
2169                         get {
2170                                 return Keyboard.ModifierKeys;
2171                         }
2172                 }
2173
2174                 internal override  Size SmallIconSize {
2175                         get {
2176                                 IntPtr          list;
2177                                 XIconSize       size;
2178                                 int             count;
2179
2180                                 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
2181                                         long            current;
2182                                         int             smallest;
2183
2184                                         current = (long)list;
2185                                         smallest = 0;
2186
2187                                         size = new XIconSize();
2188
2189                                         for (int i = 0; i < count; i++) {
2190                                                 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
2191                                                 current += Marshal.SizeOf(size);
2192
2193                                                 // Look for our preferred size
2194                                                 if (size.min_width == 16) {
2195                                                         XFree(list);
2196                                                         return new Size(16, 16);
2197                                                 }
2198
2199                                                 if (size.max_width == 16) {
2200                                                         XFree(list);
2201                                                         return new Size(16, 16);
2202                                                 }
2203
2204                                                 if (size.min_width < 16 && size.max_width > 16) {
2205                                                         int     x;
2206
2207                                                         // check if we can fit one
2208                                                         x = size.min_width;
2209                                                         while (x < size.max_width) {
2210                                                                 x += size.width_inc;
2211                                                                 if (x == 16) {
2212                                                                         XFree(list);
2213                                                                         return new Size(16, 16);
2214                                                                 }
2215                                                         }
2216                                                 }
2217
2218                                                 if (smallest == 0 || smallest > size.min_width) {
2219                                                         smallest = size.min_width;
2220                                                 }
2221                                         }
2222
2223                                         // We didn't find a match or we wouldn't be here
2224                                         return new Size(smallest, smallest);
2225
2226                                 } else {
2227                                         return new Size(16, 16);
2228                                 }
2229                         }
2230                 } 
2231
2232                 internal override  int MouseButtonCount {
2233                         get {
2234                                 return 3;
2235                         }
2236                 } 
2237
2238                 internal override  bool MouseButtonsSwapped {
2239                         get {
2240                                 return false;   // FIXME - how to detect?
2241                         }
2242                 } 
2243
2244                 internal override Point MousePosition {
2245                         get {
2246                                 return mouse_position;
2247                         }
2248                 }
2249
2250                 internal override Size MouseHoverSize {
2251                         get {
2252                                 return new Size (1, 1);
2253                         }
2254                 }
2255
2256                 internal override int MouseHoverTime {
2257                         get {
2258                                 return HoverState.Interval;
2259                         }
2260                 }
2261
2262
2263
2264                 internal override  bool MouseWheelPresent {
2265                         get {
2266                                 return true;    // FIXME - how to detect?
2267                         }
2268                 } 
2269
2270                 internal override  Rectangle VirtualScreen {
2271                         get {
2272                                 IntPtr                  actual_atom;
2273                                 int                     actual_format;
2274                                 IntPtr                  nitems;
2275                                 IntPtr                  bytes_after;
2276                                 IntPtr                  prop = IntPtr.Zero;
2277                                 int                     width;
2278                                 int                     height;
2279
2280                                 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);
2281                                 if ((long)nitems < 2)
2282                                         goto failsafe;
2283
2284                                 width = Marshal.ReadIntPtr(prop, 0).ToInt32();
2285                                 height = Marshal.ReadIntPtr(prop, IntPtr.Size).ToInt32();
2286
2287                                 XFree(prop);
2288
2289                                 return new Rectangle(0, 0, width, height);
2290
2291                         failsafe:
2292                                 XWindowAttributes       attributes=new XWindowAttributes();
2293
2294                                 lock (XlibLock) {
2295                                         XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2296                                 }
2297
2298                                 return new Rectangle(0, 0, attributes.width, attributes.height);
2299                         }
2300                 } 
2301
2302                 internal override  Rectangle WorkingArea {
2303                         get {
2304                                 IntPtr                  actual_atom;
2305                                 int                     actual_format;
2306                                 IntPtr                  nitems;
2307                                 IntPtr                  bytes_after;
2308                                 IntPtr                  prop = IntPtr.Zero;
2309                                 int                     width;
2310                                 int                     height;
2311                                 int                     current_desktop;
2312                                 int                     x;
2313                                 int                     y;
2314
2315                                 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);
2316                                 if ((long)nitems < 1) {
2317                                         goto failsafe;
2318                                 }
2319
2320                                 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
2321                                 XFree(prop);
2322
2323                                 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);
2324                                 if ((long)nitems < 4 * current_desktop) {
2325                                         goto failsafe;
2326                                 }
2327
2328                                 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2329                                 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2330                                 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2331                                 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2332                                 XFree(prop);
2333
2334                                 return new Rectangle(x, y, width, height);
2335
2336                         failsafe:
2337                                 XWindowAttributes       attributes=new XWindowAttributes();
2338
2339                                 lock (XlibLock) {
2340                                         XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2341                                 }
2342
2343                                 return new Rectangle(0, 0, attributes.width, attributes.height);
2344                         }
2345                 }
2346
2347                 internal override bool ThemesEnabled {
2348                         get {
2349                                 return XplatUIX11.themes_enabled;
2350                         }
2351                 }
2352  
2353
2354                 #endregion      // Public properties
2355
2356                 #region Public Static Methods
2357                 internal override void RaiseIdle (EventArgs e)
2358                 {
2359                         if (Idle != null)
2360                                 Idle (this, e);
2361                 }
2362                 
2363                 internal override IntPtr InitializeDriver() {
2364                         lock (this) {
2365                                 if (DisplayHandle==IntPtr.Zero) {
2366                                         SetDisplay(XOpenDisplay(IntPtr.Zero));
2367                                 }
2368                         }
2369                         return IntPtr.Zero;
2370                 }
2371
2372                 internal override void ShutdownDriver(IntPtr token) {
2373                         lock (this) {
2374                                 if (DisplayHandle!=IntPtr.Zero) {
2375                                         XCloseDisplay(DisplayHandle);
2376                                         DisplayHandle=IntPtr.Zero;
2377                                 }
2378                         }
2379                 }
2380
2381                 internal override void EnableThemes() {
2382                         themes_enabled = true;
2383                 }
2384
2385
2386                 internal override void Activate(IntPtr handle) {
2387                         Hwnd hwnd;
2388
2389                         hwnd = Hwnd.ObjectFromHandle(handle);
2390
2391                         if (hwnd != null) {
2392                                 lock (XlibLock) {
2393                                         if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2394                                                 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2395                                                 XEventQueue q = null;
2396                                                 lock (unattached_timer_list) {
2397                                                         foreach (Timer t in unattached_timer_list) {
2398                                                                 if (q == null)
2399                                                                         q= (XEventQueue) MessageQueues [Thread.CurrentThread];
2400                                                                 t.thread = q.Thread;
2401                                                                 q.timer_list.Add (t);
2402                                                         }
2403                                                         unattached_timer_list.Clear ();
2404                                                 }
2405                                         }
2406 //                                      else {
2407 //                                              XRaiseWindow(DisplayHandle, handle);
2408 //                                      }
2409                                 }
2410                         }
2411                 }
2412
2413                 internal override void AudibleAlert() {
2414                         XBell(DisplayHandle, 0);
2415                         return;
2416                 }
2417
2418
2419                 internal override void CaretVisible(IntPtr handle, bool visible) {
2420                         if (Caret.Hwnd == handle) {
2421                                 if (visible) {
2422                                         if (!Caret.Visible) {
2423                                                 Caret.Visible = true;
2424                                                 ShowCaret();
2425                                                 Caret.Timer.Start();
2426                                         }
2427                                 } else {
2428                                         Caret.Visible = false;
2429                                         Caret.Timer.Stop();
2430                                         HideCaret();
2431                                 }
2432                         }
2433                 }
2434
2435                 internal override bool CalculateWindowRect(ref Rectangle ClientRect, CreateParams cp, Menu menu, out Rectangle WindowRect) {
2436                         WindowRect = Hwnd.GetWindowRectangle (cp, menu, ClientRect);
2437                         return true;
2438                 }
2439
2440                 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2441                         int     dest_x_return;
2442                         int     dest_y_return;
2443                         IntPtr  child;
2444                         Hwnd    hwnd;
2445
2446                         hwnd = Hwnd.ObjectFromHandle(handle);
2447
2448                         lock (XlibLock) {
2449                                 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2450                         }
2451
2452                         x = dest_x_return;
2453                         y = dest_y_return;
2454                 }
2455
2456                 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2457                         DataFormats.Format      f;
2458                         int[]                   result;
2459
2460                         f = DataFormats.Format.List;
2461
2462                         if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2463                                 return null;
2464                         }
2465
2466                         Clipboard.Formats = new ArrayList();
2467
2468                         while (f != null) {
2469                                 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2470
2471                                 Clipboard.Enumerating = true;
2472                                 while (Clipboard.Enumerating) {
2473                                         UpdateMessageQueue(null);
2474                                 }
2475                                 f = f.Next;
2476                         }
2477
2478                         result = new int[Clipboard.Formats.Count];
2479
2480                         for (int i = 0; i < Clipboard.Formats.Count; i++) {
2481                                 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2482                         }
2483
2484                         Clipboard.Formats = null;
2485                         return result;
2486                 }
2487
2488                 internal override void ClipboardClose(IntPtr handle) {
2489                         if (handle != ClipMagic) {
2490                                 throw new ArgumentException("handle is not a valid clipboard handle");
2491                         }
2492                         return;
2493                 }
2494
2495                 internal override int ClipboardGetID(IntPtr handle, string format) {
2496                         if (handle != ClipMagic) {
2497                                 throw new ArgumentException("handle is not a valid clipboard handle");
2498                         }
2499
2500                         if (format == "Text" ) return (int)Atom.XA_STRING;
2501                         else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2502                         //else if (format == "MetaFilePict" ) return 3;
2503                         //else if (format == "SymbolicLink" ) return 4;
2504                         //else if (format == "DataInterchangeFormat" ) return 5;
2505                         //else if (format == "Tiff" ) return 6;
2506                         else if (format == "OEMText" ) return OEMTEXT.ToInt32();
2507                         else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2508                         else if (format == "Palette" ) return (int)Atom.XA_COLORMAP;    // Useless
2509                         //else if (format == "PenData" ) return 10;
2510                         //else if (format == "RiffAudio" ) return 11;
2511                         //else if (format == "WaveAudio" ) return 12;
2512                         else if (format == "UnicodeText" ) return UNICODETEXT.ToInt32();
2513                         //else if (format == "EnhancedMetafile" ) return 14;
2514                         //else if (format == "FileDrop" ) return 15;
2515                         //else if (format == "Locale" ) return 16;
2516
2517                         return XInternAtom(DisplayHandle, format, false).ToInt32();
2518                 }
2519
2520                 internal override IntPtr ClipboardOpen(bool primary_selection) {
2521                         if (!primary_selection)
2522                                 ClipMagic = CLIPBOARD;
2523                         else
2524                                 ClipMagic = PRIMARY;
2525                         return ClipMagic;
2526                 }
2527
2528                 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2529                         XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2530
2531                         Clipboard.Retrieving = true;
2532                         while (Clipboard.Retrieving) {
2533                                 UpdateMessageQueue(null);
2534                         }
2535
2536                         return Clipboard.Item;
2537                 }
2538
2539                 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2540                         Clipboard.Item = obj;
2541                         Clipboard.Type = type;
2542                         Clipboard.Converter = converter;
2543
2544                         if (obj != null) {
2545                                 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2546                         } else {
2547                                 // Clearing the selection
2548                                 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2549                         }
2550                 }
2551
2552                 internal override void CreateCaret (IntPtr handle, int width, int height)
2553                 {
2554                         XGCValues       gc_values;
2555                         Hwnd            hwnd;
2556
2557                         hwnd = Hwnd.ObjectFromHandle(handle);
2558
2559                         if (Caret.Hwnd != IntPtr.Zero) {
2560                                 DestroyCaret(Caret.Hwnd);
2561                         }
2562
2563                         Caret.Hwnd = handle;
2564                         Caret.Window = hwnd.client_window;
2565                         Caret.Width = width;
2566                         Caret.Height = height;
2567                         Caret.Visible = false;
2568                         Caret.On = false;
2569
2570                         gc_values = new XGCValues();
2571                         gc_values.line_width = width;
2572
2573                         Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2574                         if (Caret.gc == IntPtr.Zero) {
2575                                 Caret.Hwnd = IntPtr.Zero;
2576                                 return;
2577                         }
2578
2579                         XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2580                 }
2581
2582                 internal override IntPtr CreateWindow (CreateParams cp)
2583                 {
2584                         XSetWindowAttributes    Attributes;
2585                         Hwnd                    hwnd;
2586                         Hwnd                    parent_hwnd = null;
2587                         int                     X;
2588                         int                     Y;
2589                         int                     Width;
2590                         int                     Height;
2591                         IntPtr                  ParentHandle;
2592                         IntPtr                  WholeWindow;
2593                         IntPtr                  ClientWindow;
2594                         SetWindowValuemask      ValueMask;
2595                         int[]                   atoms;
2596
2597                         hwnd = new Hwnd();
2598
2599                         Attributes = new XSetWindowAttributes();
2600                         X = cp.X;
2601                         Y = cp.Y;
2602                         Width = cp.Width;
2603                         Height = cp.Height;
2604
2605                         if (Width<1) Width=1;
2606                         if (Height<1) Height=1;
2607
2608                         if (cp.Parent != IntPtr.Zero) {
2609                                 parent_hwnd = Hwnd.ObjectFromHandle(cp.Parent);
2610                                 ParentHandle = parent_hwnd.client_window;
2611                         } else {
2612                                 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2613                                         // We need to use our foster parent window until this poor child gets it's parent assigned
2614                                         ParentHandle=FosterParent;
2615                                 } else {
2616                                         ParentHandle=RootWindow;
2617                                 }
2618                         }
2619
2620                         // Set the default location location for forms.
2621                         Point next;
2622                         if (cp.control is Form) {
2623                                 next = Hwnd.GetNextStackedFormLocation (cp, parent_hwnd);
2624                                 X = next.X;
2625                                 Y = next.Y;
2626                         }
2627                         ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2628
2629                         Attributes.bit_gravity = Gravity.NorthWestGravity;
2630                         Attributes.win_gravity = Gravity.NorthWestGravity;
2631
2632                         // Save what's under the toolwindow
2633                         if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2634                                 Attributes.save_under = true;
2635                                 ValueMask |= SetWindowValuemask.SaveUnder;
2636                         }
2637
2638
2639                         // If we're a popup without caption we override the WM
2640                         if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2641                                 Attributes.override_redirect = true;
2642                                 ValueMask |= SetWindowValuemask.OverrideRedirect;
2643                         }
2644
2645                         hwnd.x = X;
2646                         hwnd.y = Y;
2647                         hwnd.width = Width;
2648                         hwnd.height = Height;
2649                         hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2650                         hwnd.initial_style = cp.WindowStyle;
2651                         hwnd.initial_ex_style = cp.WindowExStyle;
2652
2653                         if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2654                                 hwnd.enabled = false;
2655                         }
2656
2657                         ClientWindow = IntPtr.Zero;
2658
2659                         Size XWindowSize = TranslateWindowSizeToXWindowSize (cp);
2660                         Rectangle XClientRect = TranslateClientRectangleToXClientRectangle (hwnd, cp.control);
2661                                 
2662                         lock (XlibLock) {
2663                                 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);
2664                                 if (WholeWindow != IntPtr.Zero) {
2665                                         ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2666
2667                                         if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2668                                                 ValueMask = SetWindowValuemask.ColorMap;
2669                                                 Attributes.colormap = CustomColormap;
2670                                         }
2671                                         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);
2672                                 }
2673                         }
2674
2675                         if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2676                                 throw new Exception("Could not create X11 windows");
2677                         }
2678
2679                         hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2680                         hwnd.WholeWindow = WholeWindow;
2681                         hwnd.ClientWindow = ClientWindow;
2682
2683                         #if DriverDebug || DriverDebugCreate
2684                                 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);
2685                         #endif
2686                         
2687                         if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2688                                 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2689                                         XSizeHints      hints;
2690
2691                                         hints = new XSizeHints();
2692                                         hints.x = X;
2693                                         hints.y = Y;
2694                                         hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2695                                         XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2696                                 }
2697                         }
2698
2699                         lock (XlibLock) {
2700                                 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | EventMask.PropertyChangeMask | Keyboard.KeyEventMask)));
2701                                 if (hwnd.whole_window != hwnd.client_window)
2702                                         XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask | Keyboard.KeyEventMask)));
2703                         }
2704
2705                         if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2706                                 atoms = new int[2];
2707                                 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2708                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2709
2710                                 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2711                         }
2712
2713                         SetWMStyles(hwnd, cp);
2714                         
2715                         // set the group leader
2716                         XWMHints wm_hints = new XWMHints ();
2717                         
2718                         wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2719                         wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2720                         wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2721                         
2722                         if (ParentHandle != RootWindow) {
2723                                 wm_hints.window_group = hwnd.whole_window;
2724                         } else {
2725                                 wm_hints.window_group = ParentHandle;
2726                         }
2727                         
2728                         lock (XlibLock) {
2729                                 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2730                         }
2731
2732                         if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2733                                 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2734                         } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2735                                 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2736                         }
2737
2738                         // for now make all windows dnd enabled
2739                         Dnd.SetAllowDrop (hwnd, true);
2740
2741                         // Set caption/window title
2742                         Text(hwnd.Handle, cp.Caption);
2743
2744                         SendMessage (hwnd.Handle, Msg.WM_CREATE, (IntPtr)1, IntPtr.Zero /* XXX unused */);
2745                         SendParentNotify (hwnd.Handle, Msg.WM_CREATE, int.MaxValue, int.MaxValue);
2746
2747                         if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2748                                 hwnd.visible = true;
2749                                 MapWindow(hwnd, WindowType.Both);
2750                                 if (!(Control.FromHandle(hwnd.Handle) is Form))
2751                                         SendMessage(hwnd.Handle, Msg.WM_SHOWWINDOW, (IntPtr)1, IntPtr.Zero);
2752                         }
2753
2754                         return hwnd.Handle;
2755                 }
2756
2757                 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2758                         CreateParams create_params = new CreateParams();
2759
2760                         create_params.Caption = "";
2761                         create_params.X = X;
2762                         create_params.Y = Y;
2763                         create_params.Width = Width;
2764                         create_params.Height = Height;
2765
2766                         create_params.ClassName=XplatUI.DefaultClassName;
2767                         create_params.ClassStyle = 0;
2768                         create_params.ExStyle=0;
2769                         create_params.Parent=IntPtr.Zero;
2770                         create_params.Param=0;
2771
2772                         return CreateWindow(create_params);
2773                 }
2774
2775                 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2776                         IntPtr  cursor;
2777                         Bitmap  cursor_bitmap;
2778                         Bitmap  cursor_mask;
2779                         Byte[]  cursor_bits;
2780                         Byte[]  mask_bits;
2781                         Color   c_pixel;
2782                         Color   m_pixel;
2783                         int     width;
2784                         int     height;
2785                         IntPtr  cursor_pixmap;
2786                         IntPtr  mask_pixmap;
2787                         XColor  fg;
2788                         XColor  bg;
2789                         bool    and;
2790                         bool    xor;
2791
2792                         if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2793                                 return IntPtr.Zero;
2794                         }
2795
2796                         // Win32 only allows creation cursors of a certain size
2797                         if ((bitmap.Width != width) || (bitmap.Width != height)) {
2798                                 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2799                                 cursor_mask = new Bitmap(mask, new Size(width, height));
2800                         } else {
2801                                 cursor_bitmap = bitmap;
2802                                 cursor_mask = mask;
2803                         }
2804
2805                         width = cursor_bitmap.Width;
2806                         height = cursor_bitmap.Height;
2807
2808                         cursor_bits = new Byte[(width / 8) * height];
2809                         mask_bits = new Byte[(width / 8) * height];
2810
2811                         for (int y = 0; y < height; y++) {
2812                                 for (int x = 0; x < width; x++) {
2813                                         c_pixel = cursor_bitmap.GetPixel(x, y);
2814                                         m_pixel = cursor_mask.GetPixel(x, y);
2815
2816                                         and = c_pixel == cursor_pixel;
2817                                         xor = m_pixel == mask_pixel;
2818
2819                                         if (!and && !xor) {
2820                                                 // Black
2821                                                 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));       // The bit already is 0
2822                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2823                                         } else if (and && !xor) {
2824                                                 // White
2825                                                 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2826                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2827 #if notneeded
2828                                         } else if (and && !xor) {
2829                                                 // Screen
2830                                         } else if (and && xor) {
2831                                                 // Inverse Screen
2832
2833                                                 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2834                                                 // we want both to be 0 so nothing to be done
2835                                                 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2836                                                 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2837 #endif
2838                                         }
2839                                 }
2840                         }
2841
2842                         cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2843                         mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2844                         fg = new XColor();
2845                         bg = new XColor();
2846
2847                         fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2848                         fg.red = (ushort)65535;
2849                         fg.green = (ushort)65535;
2850                         fg.blue = (ushort)65535;
2851
2852                         bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2853
2854                         cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2855
2856                         XFreePixmap(DisplayHandle, cursor_pixmap);
2857                         XFreePixmap(DisplayHandle, mask_pixmap);
2858
2859                         return cursor;
2860                 }
2861
2862                 internal override Bitmap DefineStdCursorBitmap (StdCursor id) {
2863                         CursorFontShape shape;
2864                         string name;
2865                         IntPtr theme;
2866                         int size;
2867                         Bitmap bmp = null;
2868                         
2869                         try {
2870                                 shape = StdCursorToFontShape (id);
2871                                 name = shape.ToString ().Replace ("XC_", string.Empty);
2872                                 size = XcursorGetDefaultSize (DisplayHandle);
2873                                 theme = XcursorGetTheme (DisplayHandle);
2874                                 IntPtr images_ptr = XcursorLibraryLoadImages (name, theme, size);
2875 #if debug
2876                                 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);
2877 #endif
2878
2879                                 if (images_ptr == IntPtr.Zero) {
2880                                         return null;
2881                                 }
2882
2883                                 XcursorImages images = (XcursorImages) Marshal.PtrToStructure (images_ptr, typeof (XcursorImages));
2884 #if debug
2885                                 Console.WriteLine ("DefineStdCursorBitmap, cursor has {0} images", images.nimage);
2886 #endif
2887
2888                                 if (images.nimage > 0) {                        
2889                                         // We only care about the first image.
2890                                         XcursorImage image = (XcursorImage)Marshal.PtrToStructure (Marshal.ReadIntPtr (images.images), typeof (XcursorImage));
2891                                         
2892 #if debug
2893                                         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);
2894 #endif
2895                                         // A sanity check
2896                                         if (image.width <= short.MaxValue && image.height <= short.MaxValue) {
2897                                                 int [] pixels = new int [image.width * image.height];
2898                                                 Marshal.Copy (image.pixels, pixels, 0, pixels.Length);
2899                                                 bmp = new Bitmap (image.width, image.height);
2900                                                 for (int w = 0; w < image.width; w++) {
2901                                                         for (int h = 0; h < image.height; h++) {
2902                                                                 bmp.SetPixel (w, h, Color.FromArgb (pixels [h * image.width + w]));
2903                                                         }
2904                                                 }
2905                                         }
2906                                 }
2907                                 
2908                                 XcursorImagesDestroy (images_ptr);
2909                                 
2910                         } catch (DllNotFoundException ex) {
2911                                 Console.WriteLine ("Could not load libXcursor: " + ex.Message + " (" + ex.GetType ().Name + ")");
2912                                 return null;
2913                         }
2914                         
2915                         return bmp;
2916                 }
2917
2918                 
2919                 internal override IntPtr DefineStdCursor(StdCursor id) {
2920                         CursorFontShape shape;
2921                         IntPtr          cursor;
2922
2923                         shape = StdCursorToFontShape (id);
2924
2925                         lock (XlibLock) {
2926                                 cursor = XCreateFontCursor(DisplayHandle, shape);
2927                         }
2928                         return cursor;
2929                 }
2930
2931                 internal static CursorFontShape StdCursorToFontShape (StdCursor id) {
2932                         CursorFontShape shape;
2933                         // FIXME - define missing shapes
2934
2935                         switch (id) {
2936                                 case StdCursor.AppStarting: {
2937                                         shape = CursorFontShape.XC_watch;
2938                                         break;
2939                                 }
2940
2941                                 case StdCursor.Arrow: {
2942                                         shape = CursorFontShape.XC_top_left_arrow;
2943                                         break;
2944                                 }
2945
2946                                 case StdCursor.Cross: {
2947                                         shape = CursorFontShape.XC_crosshair;
2948                                         break;
2949                                 }
2950
2951                                 case StdCursor.Default: {
2952                                         shape = CursorFontShape.XC_top_left_arrow;
2953                                         break;
2954                                 }
2955
2956                                 case StdCursor.Hand: {
2957                                         shape = CursorFontShape.XC_hand1;
2958                                         break;
2959                                 }
2960
2961                                 case StdCursor.Help: {
2962                                         shape = CursorFontShape.XC_question_arrow;
2963                                         break;
2964                                 }
2965
2966                                 case StdCursor.HSplit: {
2967                                         shape = CursorFontShape.XC_sb_v_double_arrow; 
2968                                         break;
2969                                 }
2970
2971                                 case StdCursor.IBeam: {
2972                                         shape = CursorFontShape.XC_xterm; 
2973                                         break;
2974                                 }
2975
2976                                 case StdCursor.No: {
2977                                         shape = CursorFontShape.XC_circle; 
2978                                         break;
2979                                 }
2980
2981                                 case StdCursor.NoMove2D: {
2982                                         shape = CursorFontShape.XC_fleur; 
2983                                         break;
2984                                 }
2985
2986                                 case StdCursor.NoMoveHoriz: {
2987                                         shape = CursorFontShape.XC_fleur; 
2988                                         break;
2989                                 }
2990
2991                                 case StdCursor.NoMoveVert: {
2992                                         shape = CursorFontShape.XC_fleur; 
2993                                         break;
2994                                 }
2995
2996                                 case StdCursor.PanEast: {
2997                                         shape = CursorFontShape.XC_fleur; 
2998                                         break;
2999                                 }
3000
3001                                 case StdCursor.PanNE: {
3002                                         shape = CursorFontShape.XC_fleur; 
3003                                         break;
3004                                 }
3005
3006                                 case StdCursor.PanNorth: {
3007                                         shape = CursorFontShape.XC_fleur; 
3008                                         break;
3009                                 }
3010
3011                                 case StdCursor.PanNW: {
3012                                         shape = CursorFontShape.XC_fleur; 
3013                                         break;
3014                                 }
3015
3016                                 case StdCursor.PanSE: {
3017                                         shape = CursorFontShape.XC_fleur; 
3018                                         break;
3019                                 }
3020
3021                                 case StdCursor.PanSouth: {
3022                                         shape = CursorFontShape.XC_fleur; 
3023                                         break;
3024                                 }
3025
3026                                 case StdCursor.PanSW: {
3027                                         shape = CursorFontShape.XC_fleur; 
3028                                         break;
3029                                 }
3030
3031                                 case StdCursor.PanWest: {
3032                                         shape = CursorFontShape.XC_sizing; 
3033                                         break;
3034                                 }
3035
3036                                 case StdCursor.SizeAll: {
3037                                         shape = CursorFontShape.XC_fleur; 
3038                                         break;
3039                                 }
3040
3041                                 case StdCursor.SizeNESW: {
3042                                         shape = CursorFontShape.XC_top_right_corner; 
3043                                         break;
3044                                 }
3045
3046                                 case StdCursor.SizeNS: {
3047                                         shape = CursorFontShape.XC_sb_v_double_arrow;
3048                                         break;
3049                                 }
3050
3051                                 case StdCursor.SizeNWSE: {
3052                                         shape = CursorFontShape.XC_top_left_corner; 
3053                                         break;
3054                                 }
3055
3056                                 case StdCursor.SizeWE: {
3057                                         shape = CursorFontShape.XC_sb_h_double_arrow; 
3058                                         break;
3059                                 }
3060
3061                                 case StdCursor.UpArrow: {
3062                                         shape = CursorFontShape.XC_center_ptr; 
3063                                         break;
3064                                 }
3065
3066                                 case StdCursor.VSplit: {
3067                                         shape = CursorFontShape.XC_sb_h_double_arrow;
3068                                         break;
3069                                 }
3070
3071                                 case StdCursor.WaitCursor: {
3072                                         shape = CursorFontShape.XC_watch; 
3073                                         break;
3074                                 }
3075
3076                                 default: {
3077                                         shape = (CursorFontShape) 0;
3078                                         break;
3079                                 }
3080                         }
3081                         
3082                         return shape;
3083                 }
3084
3085                 internal override IntPtr DefWndProc(ref Message msg) {
3086                         switch ((Msg)msg.Msg) {
3087                                 
3088                                 case Msg.WM_IME_COMPOSITION:
3089                                         string s = Keyboard.GetCompositionString ();
3090                                         foreach (char c in s)
3091                                                 SendMessage (msg.HWnd, Msg.WM_IME_CHAR, (IntPtr) c, msg.LParam);
3092                                         return IntPtr.Zero;
3093
3094                                 case Msg.WM_IME_CHAR:
3095                                         // On Windows API it sends two WM_CHAR messages for each byte, but
3096                                         // I wonder if it is worthy to emulate it (also no idea how to 
3097                                         // reconstruct those bytes into chars).
3098                                         SendMessage (msg.HWnd, Msg.WM_CHAR, msg.WParam, msg.LParam);
3099                                         return IntPtr.Zero;
3100
3101                                 case Msg.WM_PAINT: {
3102                                         Hwnd hwnd;
3103
3104                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3105                                         if (hwnd != null) {
3106                                                 hwnd.expose_pending = false;
3107                                         }
3108
3109                                         return IntPtr.Zero;
3110                                 }
3111
3112                                 case Msg.WM_NCPAINT: {
3113                                         Hwnd hwnd;
3114
3115                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3116                                         if (hwnd != null) {
3117                                                 hwnd.nc_expose_pending = false;
3118                                         }
3119
3120                                         return IntPtr.Zero;
3121                                 }
3122
3123                                 case Msg.WM_NCCALCSIZE: {
3124                                         Hwnd hwnd;
3125
3126                                         if (msg.WParam == (IntPtr)1) {
3127                                                 hwnd = Hwnd.GetObjectFromWindow (msg.HWnd);
3128                                                 
3129                                                 XplatUIWin32.NCCALCSIZE_PARAMS ncp;
3130                                                 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure (msg.LParam, typeof (XplatUIWin32.NCCALCSIZE_PARAMS));
3131
3132                                                 // Add all the stuff X is supposed to draw.
3133                                                 Control ctrl = Control.FromHandle (hwnd.Handle);
3134                                                 
3135                                                 if (ctrl != null) {
3136                                                         Hwnd.Borders rect = Hwnd.GetBorders (ctrl.GetCreateParams (), null);
3137                                                         
3138                                                         ncp.rgrc1.top += rect.top;
3139                                                         ncp.rgrc1.bottom -= rect.bottom;
3140                                                         ncp.rgrc1.left += rect.left;
3141                                                         ncp.rgrc1.right -= rect.right;
3142                                                         
3143                                                         Marshal.StructureToPtr (ncp, msg.LParam, true);
3144                                                 }
3145                                         }
3146
3147                                         return IntPtr.Zero;
3148                                 }
3149
3150                                 case Msg.WM_CONTEXTMENU: {
3151                                         Hwnd hwnd;
3152
3153                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3154
3155                                         if ((hwnd != null) && (hwnd.parent != null)) {
3156                                                 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
3157                                         }
3158                                         return IntPtr.Zero;
3159                                 }
3160
3161                                 case Msg.WM_MOUSEWHEEL: {
3162                                         Hwnd hwnd;
3163
3164                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3165
3166                                         if ((hwnd != null) && (hwnd.parent != null)) {
3167                                                 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
3168                                                 if (msg.Result == IntPtr.Zero) {
3169                                                         return IntPtr.Zero;
3170                                                 }
3171                                         }
3172                                         return IntPtr.Zero;
3173                                 }
3174
3175                                 case Msg.WM_SETCURSOR: {
3176                                         Hwnd    hwnd;
3177
3178                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
3179                                         if (hwnd == null)
3180                                                 break; // not sure how this happens, but it does
3181
3182                                         // Pass to parent window first
3183                                         while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
3184                                                 hwnd = hwnd.parent;
3185                                                 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
3186                                         }
3187
3188                                         if (msg.Result == IntPtr.Zero) {
3189                                                 IntPtr handle;
3190
3191                                                 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
3192                                                         case HitTest.HTBOTTOM:          handle = Cursors.SizeNS.handle; break;
3193                                                         case HitTest.HTBORDER:          handle = Cursors.SizeNS.handle; break;
3194                                                         case HitTest.HTBOTTOMLEFT:      handle = Cursors.SizeNESW.handle; break;
3195                                                         case HitTest.HTBOTTOMRIGHT:     handle = Cursors.SizeNWSE.handle; break;
3196                                                         case HitTest.HTERROR:           if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
3197                                                                                                 AudibleAlert();
3198                                                                                         }
3199                                                                                         handle = Cursors.Default.handle;
3200                                                                                         break;
3201
3202                                                         case HitTest.HTHELP:            handle = Cursors.Help.handle; break;
3203                                                         case HitTest.HTLEFT:            handle = Cursors.SizeWE.handle; break;
3204                                                         case HitTest.HTRIGHT:           handle = Cursors.SizeWE.handle; break;
3205                                                         case HitTest.HTTOP:             handle = Cursors.SizeNS.handle; break;
3206                                                         case HitTest.HTTOPLEFT:         handle = Cursors.SizeNWSE.handle; break;
3207                                                         case HitTest.HTTOPRIGHT:        handle = Cursors.SizeNESW.handle; break;
3208
3209                                                         #if SameAsDefault
3210                                                         case HitTest.HTGROWBOX:
3211                                                         case HitTest.HTSIZE:
3212                                                         case HitTest.HTZOOM:
3213                                                         case HitTest.HTVSCROLL:
3214                                                         case HitTest.HTSYSMENU:
3215                                                         case HitTest.HTREDUCE:
3216                                                         case HitTest.HTNOWHERE:
3217                                                         case HitTest.HTMAXBUTTON:
3218                                                         case HitTest.HTMINBUTTON:
3219                                                         case HitTest.HTMENU:
3220                                                         case HitTest.HSCROLL:
3221                                                         case HitTest.HTBOTTOM:
3222                                                         case HitTest.HTCAPTION:
3223                                                         case HitTest.HTCLIENT:
3224                                                         case HitTest.HTCLOSE:
3225                                                         #endif
3226                                                         default: handle = Cursors.Default.handle; break;
3227                                                 }
3228                                                 SetCursor(msg.HWnd, handle);
3229                                         }
3230                                         return (IntPtr)1;
3231                                 }
3232                         }
3233                         return IntPtr.Zero;
3234                 }
3235
3236                 internal override void DestroyCaret(IntPtr handle) {
3237                         if (Caret.Hwnd == handle) {
3238                                 if (Caret.Visible) {
3239                                         HideCaret ();
3240                                         Caret.Timer.Stop();
3241                                 }
3242                                 if (Caret.gc != IntPtr.Zero) {
3243                                         XFreeGC(DisplayHandle, Caret.gc);
3244                                         Caret.gc = IntPtr.Zero;
3245                                 }
3246                                 Caret.Hwnd = IntPtr.Zero;
3247                                 Caret.Visible = false;
3248                                 Caret.On = false;
3249                         }
3250                 }
3251
3252                 internal override void DestroyCursor(IntPtr cursor) {
3253                         lock (XlibLock) {
3254                                 XFreeCursor(DisplayHandle, cursor);
3255                         }
3256                 }
3257
3258                 internal override void DestroyWindow(IntPtr handle) {
3259                         Hwnd    hwnd;
3260
3261                         hwnd = Hwnd.ObjectFromHandle(handle);
3262
3263                         if (hwnd == null) {
3264                                 #if DriverDebug || DriverDebugDestroy
3265                                         Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
3266                                 #endif
3267                                 return;
3268                         }
3269
3270                         #if DriverDebug || DriverDebugDestroy
3271                                 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
3272                         #endif
3273
3274                         SendParentNotify (hwnd.Handle, Msg.WM_DESTROY, int.MaxValue, int.MaxValue);
3275                                 
3276                         CleanupCachedWindows (hwnd);
3277
3278                         ArrayList windows = new ArrayList ();
3279
3280                         AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
3281
3282
3283                         foreach (Hwnd h in windows) {
3284                                 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
3285                                 h.zombie = true;
3286                         }
3287
3288                         lock (XlibLock) {
3289                                 if (hwnd.whole_window != IntPtr.Zero) {
3290                                         #if DriverDebug || DriverDebugDestroy
3291                                         Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
3292                                         #endif
3293                                         Keyboard.DestroyICForWindow (hwnd.whole_window);
3294                                         XDestroyWindow(DisplayHandle, hwnd.whole_window);
3295                                 }
3296                                 else if (hwnd.client_window != IntPtr.Zero) {
3297                                         #if DriverDebug || DriverDebugDestroy
3298                                         Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
3299                                         #endif
3300                                         Keyboard.DestroyICForWindow (hwnd.client_window);
3301                                         XDestroyWindow(DisplayHandle, hwnd.client_window);
3302                                 }
3303
3304                         }
3305                 }
3306
3307                 internal override IntPtr DispatchMessage(ref MSG msg) {
3308                         return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
3309                 }
3310
3311                 IntPtr GetReversibleScreenGC (Color backColor)
3312                 {
3313                         XGCValues       gc_values;
3314                         IntPtr          gc;
3315                         uint pixel;
3316
3317                         XColor xcolor = new XColor();
3318                         xcolor.red = (ushort)(backColor.R * 257);
3319                         xcolor.green = (ushort)(backColor.G * 257);
3320                         xcolor.blue = (ushort)(backColor.B * 257);
3321                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3322                         pixel = (uint)xcolor.pixel.ToInt32();
3323
3324
3325                         gc_values = new XGCValues();
3326
3327                         gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3328                         gc_values.foreground = (IntPtr)pixel;
3329
3330                         gc = XCreateGC(DisplayHandle, RootWindow, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCForeground)), ref gc_values);
3331                         XSetForeground(DisplayHandle, gc, (UIntPtr)pixel);
3332                         XSetFunction(DisplayHandle,   gc, GXFunction.GXxor);
3333
3334                         return gc;
3335                 }
3336
3337                 IntPtr GetReversibleControlGC (Control control, int line_width)
3338                 {
3339                         XGCValues       gc_values;
3340                         IntPtr          gc;
3341
3342                         gc_values = new XGCValues();
3343
3344                         gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
3345                         gc_values.line_width = line_width;
3346                         gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
3347
3348                         // This logic will give us true rubber bands: (libsx, SANE_XOR)
3349                         //mask = foreground ^ background; 
3350                         //XSetForeground(DisplayHandle, gc, 0xffffffff);
3351                         //XSetBackground(DisplayHandle, gc, background);
3352                         //XSetFunction(DisplayHandle,   gc, GXxor);
3353                         //XSetPlaneMask(DisplayHandle,  gc, mask);
3354
3355
3356                         gc = XCreateGC(DisplayHandle, control.Handle, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
3357                         uint foreground;
3358                         uint background;
3359
3360                         XColor xcolor = new XColor();
3361
3362                         xcolor.red = (ushort)(control.ForeColor.R * 257);
3363                         xcolor.green = (ushort)(control.ForeColor.G * 257);
3364                         xcolor.blue = (ushort)(control.ForeColor.B * 257);
3365                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3366                         foreground = (uint)xcolor.pixel.ToInt32();
3367
3368                         xcolor.red = (ushort)(control.BackColor.R * 257);
3369                         xcolor.green = (ushort)(control.BackColor.G * 257);
3370                         xcolor.blue = (ushort)(control.BackColor.B * 257);
3371                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
3372                         background = (uint)xcolor.pixel.ToInt32();
3373
3374                         uint mask = foreground ^ background; 
3375
3376                         XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
3377                         XSetBackground(DisplayHandle, gc, (UIntPtr)background);
3378                         XSetFunction(DisplayHandle,   gc, GXFunction.GXxor);
3379                         XSetPlaneMask(DisplayHandle,  gc, (IntPtr)mask);
3380
3381                         return gc;
3382                 }
3383
3384                 internal override void DrawReversibleLine(Point start, Point end, Color backColor)
3385                 {
3386                         if (backColor.GetBrightness() < 0.5)
3387                                 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3388
3389                         IntPtr gc = GetReversibleScreenGC (backColor);
3390
3391                         XDrawLine (DisplayHandle, RootWindow, gc, start.X, start.Y, end.X, end.Y);
3392
3393                         XFreeGC(DisplayHandle, gc);
3394                 }
3395
3396                 internal override void DrawReversibleFrame (Rectangle rectangle, Color backColor, FrameStyle style)
3397                 {
3398                         if (backColor.GetBrightness() < 0.5)
3399                                 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3400
3401                         IntPtr gc = GetReversibleScreenGC (backColor);
3402
3403                         if (rectangle.Width < 0) {
3404                                 rectangle.X += rectangle.Width;
3405                                 rectangle.Width = -rectangle.Width;
3406                         }
3407                         if (rectangle.Height < 0) {
3408                                 rectangle.Y += rectangle.Height;
3409                                 rectangle.Height = -rectangle.Height;
3410                         }
3411
3412                         int line_width = 1;
3413                         GCLineStyle line_style = GCLineStyle.LineSolid;
3414                         GCCapStyle cap_style = GCCapStyle.CapButt;
3415                         GCJoinStyle join_style = GCJoinStyle.JoinMiter;
3416
3417                         switch (style) {
3418                         case FrameStyle.Dashed:
3419                                 line_style = GCLineStyle.LineOnOffDash;
3420                                 break;
3421                         case FrameStyle.Thick:
3422                                 line_width = 2;
3423                                 break;
3424                         }
3425
3426                         XSetLineAttributes (DisplayHandle, gc, line_width, line_style, cap_style, join_style);
3427
3428                         XDrawRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3429
3430                         XFreeGC(DisplayHandle, gc);
3431                 }
3432
3433                 internal override void FillReversibleRectangle (Rectangle rectangle, Color backColor) 
3434                 {
3435                         if (backColor.GetBrightness() < 0.5)
3436                                 backColor = Color.FromArgb(255 - backColor.R, 255 - backColor.G, 255 - backColor.B);
3437
3438                         IntPtr gc = GetReversibleScreenGC (backColor);
3439
3440                         if (rectangle.Width < 0) {
3441                                 rectangle.X += rectangle.Width;
3442                                 rectangle.Width = -rectangle.Width;
3443                         }
3444                         if (rectangle.Height < 0) {
3445                                 rectangle.Y += rectangle.Height;
3446                                 rectangle.Height = -rectangle.Height;
3447                         }
3448                         XFillRectangle(DisplayHandle, RootWindow, gc, rectangle.Left, rectangle.Top, rectangle.Width, rectangle.Height);
3449
3450                         XFreeGC(DisplayHandle, gc);
3451                 }
3452
3453                 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width)
3454                 {
3455                         IntPtr          gc;
3456                         Control control = Control.FromHandle(handle);
3457
3458                         gc = GetReversibleControlGC (control, line_width);
3459
3460                         if ((rect.Width > 0) && (rect.Height > 0)) {
3461                                 XDrawRectangle(DisplayHandle, control.Handle, gc, rect.Left, rect.Top, rect.Width, rect.Height);
3462                         } else {
3463                                 if (rect.Width > 0) {
3464                                         XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.Right, rect.Y);
3465                                 } else {
3466                                         XDrawLine(DisplayHandle, control.Handle, gc, rect.X, rect.Y, rect.X, rect.Bottom);
3467                                 }
3468                         }
3469                         XFreeGC(DisplayHandle, gc);
3470                 }
3471
3472                 internal override void DoEvents() {
3473                         MSG     msg = new MSG ();
3474                         XEventQueue queue;
3475
3476                         if (OverrideCursorHandle != IntPtr.Zero) {
3477                                 OverrideCursorHandle = IntPtr.Zero;
3478                         }
3479
3480                         queue = ThreadQueue(Thread.CurrentThread);
3481
3482                         queue.DispatchIdle = false;
3483
3484                         while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
3485                                 TranslateMessage (ref msg);
3486                                 DispatchMessage (ref msg);
3487                         }
3488
3489                         queue.DispatchIdle = true;
3490                 }
3491
3492                 internal override void EnableWindow(IntPtr handle, bool Enable) {
3493                         Hwnd    hwnd;
3494
3495                         hwnd = Hwnd.ObjectFromHandle(handle);
3496                         if (hwnd != null) {
3497                                 hwnd.Enabled = Enable;
3498                         }
3499                 }
3500
3501                 internal override void EndLoop(Thread thread) {
3502                         // This is where we one day will shut down the loop for the thread
3503                 }
3504
3505                 internal override IntPtr GetActive() {
3506                         IntPtr  actual_atom;
3507                         int     actual_format;
3508                         IntPtr  nitems;
3509                         IntPtr  bytes_after;
3510                         IntPtr  prop = IntPtr.Zero;
3511                         IntPtr  active = IntPtr.Zero;
3512
3513                         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);
3514                         if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3515                                 active = (IntPtr)Marshal.ReadInt32(prop);
3516                                 XFree(prop);
3517                         }
3518
3519                         if (active != IntPtr.Zero) {
3520                                 Hwnd    hwnd;
3521
3522                                 hwnd = Hwnd.GetObjectFromWindow(active);
3523                                 if (hwnd != null) {
3524                                         active = hwnd.Handle;
3525                                 } else {
3526                                         active = IntPtr.Zero;
3527                                 }
3528                         }
3529                         return active;
3530                 }
3531
3532                 internal override Region GetClipRegion(IntPtr handle) {
3533                         Hwnd    hwnd;
3534
3535                         hwnd = Hwnd.ObjectFromHandle(handle);
3536                         if (hwnd != null) {
3537                                 return hwnd.UserClip;
3538                         }
3539
3540                         return null;
3541                 }
3542
3543                 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
3544                         width = 20;
3545                         height = 20;
3546                         hotspot_x = 0;
3547                         hotspot_y = 0;
3548                 }
3549
3550                 internal override void GetDisplaySize(out Size size) {
3551                         XWindowAttributes       attributes=new XWindowAttributes();
3552
3553                         lock (XlibLock) {
3554                                 // FIXME - use _NET_WM messages instead?
3555                                 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3556                         }
3557
3558                         size = new Size(attributes.width, attributes.height);
3559                 }
3560
3561                 internal override SizeF GetAutoScaleSize(Font font) {
3562                         Graphics        g;
3563                         float           width;
3564                         string          magic_string = "The quick brown fox jumped over the lazy dog.";
3565                         double          magic_number = 44.549996948242189;
3566
3567                         g = Graphics.FromHwnd(FosterParent);
3568
3569                         width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3570                         return new SizeF(width, font.Height);
3571                 }
3572
3573                 internal override IntPtr GetParent(IntPtr handle) {
3574                         Hwnd    hwnd;
3575
3576                         hwnd = Hwnd.ObjectFromHandle(handle);
3577                         if (hwnd != null && hwnd.parent != null) {
3578                                 return hwnd.parent.Handle;
3579                         }
3580                         return IntPtr.Zero;
3581                 }
3582                 
3583                 // This is a nop on win32 and x11
3584                 internal override IntPtr GetPreviousWindow(IntPtr handle) {
3585                         return handle;
3586                 }
3587
3588                 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3589                         IntPtr  use_handle;
3590                         IntPtr  root;
3591                         IntPtr  child;
3592                         int     root_x;
3593                         int     root_y;
3594                         int     win_x;
3595                         int     win_y;
3596                         int     keys_buttons;
3597
3598                         if (handle != IntPtr.Zero) {
3599                                 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3600                         } else {
3601                                 use_handle = RootWindow;
3602                         }
3603
3604                         lock (XlibLock) {
3605                                 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3606                         }
3607
3608                         if (handle != IntPtr.Zero) {
3609                                 x = win_x;
3610                                 y = win_y;
3611                         } else {
3612                                 x = root_x;
3613                                 y = root_y;
3614                         }
3615                 }
3616
3617                 internal override IntPtr GetFocus() {
3618                         return FocusWindow;
3619                 }
3620
3621
3622                 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3623                         FontFamily ff = font.FontFamily;
3624                         ascent = ff.GetCellAscent (font.Style);
3625                         descent = ff.GetCellDescent (font.Style);
3626                         return true;
3627                 }
3628
3629                 internal override Point GetMenuOrigin(IntPtr handle) {
3630                         Hwnd    hwnd;
3631
3632                         hwnd = Hwnd.ObjectFromHandle(handle);
3633
3634                         if (hwnd != null) {
3635                                 return hwnd.MenuOrigin;
3636                         }
3637                         return Point.Empty;
3638                 }
3639
3640                 [MonoTODO("Implement filtering")]
3641                 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3642                         XEvent  xevent;
3643                         bool    client;
3644                         Hwnd    hwnd;
3645
3646                         ProcessNextMessage:
3647
3648                         if (((XEventQueue)queue_id).Count > 0) {
3649                                 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3650                         } else {
3651                                 UpdateMessageQueue ((XEventQueue)queue_id);
3652
3653                                 if (((XEventQueue)queue_id).Count > 0) {
3654                                         xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3655                                 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3656                                         xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3657                                 } else {
3658                                         msg.hwnd= IntPtr.Zero;
3659                                         msg.message = Msg.WM_ENTERIDLE;
3660                                         return true;
3661                                 }
3662                         }
3663
3664                         hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3665
3666                         // Handle messages for windows that are already or are about to be destroyed.
3667
3668                         // we need a special block for this because unless we remove the hwnd from the paint
3669                         // queue it will always stay there (since we don't handle the expose), and we'll
3670                         // effectively loop infinitely trying to repaint a non-existant window.
3671                         if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3672                                 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3673                                 hwnd.Queue.Paint.Remove (hwnd);
3674                                 goto ProcessNextMessage;
3675                         }
3676
3677                         // We need to make sure we only allow DestroyNotify events through for zombie
3678                         // hwnds, since much of the event handling code makes requests using the hwnd's
3679                         // client_window, and that'll result in BadWindow errors if there's some lag
3680                         // between the XDestroyWindow call and the DestroyNotify event.
3681                         if (hwnd == null || hwnd.zombie && xevent.AnyEvent.type != XEventName.ClientMessage) {
3682                                 #if DriverDebug || DriverDebugDestroy
3683                                         Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3684                                 #endif
3685                                 goto ProcessNextMessage;
3686                         }
3687
3688                         if (hwnd.client_window == xevent.AnyEvent.window) {
3689                                 client = true;
3690                                 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3691                         } else {
3692                                 client = false;
3693                                 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3694                         }
3695
3696                         msg.hwnd = hwnd.Handle;
3697
3698                         // Windows sends WM_ENTERSIZEMOVE when a form resize/move operation starts and WM_EXITSIZEMOVE 
3699                         // when it is done. The problem in X11 is that there is no concept of start-end of a moving/sizing.
3700                         // Configure events ("this window has resized/moved") are sent for each step of the resize. We send a
3701                         // WM_ENTERSIZEMOVE when we get the first Configure event. The problem is the WM_EXITSIZEMOVE.
3702                         // 
3703                         //  - There is no way for us to know which is the last Configure event. We can't traverse the events 
3704                         //    queue, because the next configure event might not be pending yet.
3705                         //  - We can't get ButtonPress/Release events for the window decorations, because they are not part 
3706                         //    of the window(s) we manage.
3707                         //  - We can't rely on the mouse state to change to "up" before the last Configure event. It doesn't.
3708                         // 
3709                         // We are almost 100% guaranteed to get another event (e.g Expose or other), but we can't know for sure 
3710                         // which, so we have here to check if the mouse buttons state is "up" and send the WM_EXITSIZEMOVE
3711                         //
3712                         if (hwnd.resizing_or_moving) {
3713                                 int root_x, root_y, win_x, win_y, keys_buttons;
3714                                 IntPtr  root, child;
3715                                 XQueryPointer (DisplayHandle, hwnd.Handle, out root, out child, out root_x, out root_y, 
3716                                                out win_x, out win_y, out keys_buttons);
3717                                 if ((keys_buttons & (int)MouseKeyMasks.Button1Mask) == 0 &&
3718                                     (keys_buttons & (int)MouseKeyMasks.Button2Mask) == 0 &&
3719                                     (keys_buttons & (int)MouseKeyMasks.Button3Mask) == 0) {
3720                                         hwnd.resizing_or_moving = false;
3721                                         SendMessage (hwnd.Handle, Msg.WM_EXITSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
3722                                 }
3723                         }
3724
3725                         //
3726                         // If you add a new event to this switch make sure to add it in
3727                         // UpdateMessage also unless it is not coming through the X event system.
3728                         //
3729                         switch(xevent.type) {
3730                                 case XEventName.KeyPress: {
3731                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3732                                         break;
3733                                 }
3734
3735                                 case XEventName.KeyRelease: {
3736                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3737                                         break;
3738                                 }
3739
3740                                 case XEventName.ButtonPress: {
3741                                         switch(xevent.ButtonEvent.button) {
3742                                                 case 1: {
3743                                                         MouseState |= MouseButtons.Left;
3744                                                         if (client) {
3745                                                                 msg.message = Msg.WM_LBUTTONDOWN;
3746                                                         } else {
3747                                                                 msg.message = Msg.WM_NCLBUTTONDOWN;
3748                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3749                                                         }
3750                                                         // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3751                                                         msg.wParam=GetMousewParam(0);
3752                                                         break;
3753                                                 }
3754
3755                                                 case 2: {
3756                                                         MouseState |= MouseButtons.Middle;
3757                                                         if (client) {
3758                                                                 msg.message = Msg.WM_MBUTTONDOWN;
3759                                                         } else {
3760                                                                 msg.message = Msg.WM_NCMBUTTONDOWN;
3761                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3762                                                         }
3763                                                         msg.wParam=GetMousewParam(0);
3764                                                         break;
3765                                                 }
3766
3767                                                 case 3: {
3768                                                         MouseState |= MouseButtons.Right;
3769                                                         if (client) {
3770                                                                 msg.message = Msg.WM_RBUTTONDOWN;
3771                                                         } else {
3772                                                                 msg.message = Msg.WM_NCRBUTTONDOWN;
3773                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3774                                                         }
3775                                                         msg.wParam=GetMousewParam(0);
3776                                                         break;
3777                                                 }
3778
3779                                                 case 4: {
3780                                                         msg.hwnd = FocusWindow;
3781                                                         msg.message=Msg.WM_MOUSEWHEEL;
3782                                                         msg.wParam=GetMousewParam(120);
3783                                                         break;
3784                                                 }
3785
3786                                                 case 5: {
3787                                                         msg.hwnd = FocusWindow;
3788                                                         msg.message=Msg.WM_MOUSEWHEEL;
3789                                                         msg.wParam=GetMousewParam(-120);
3790                                                         break;
3791                                                 }
3792
3793                                         }
3794
3795                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3796                                         mouse_position.X = xevent.ButtonEvent.x;
3797                                         mouse_position.Y = xevent.ButtonEvent.y;
3798
3799                                         if (!hwnd.Enabled) {
3800                                                 IntPtr dummy;
3801
3802                                                 msg.hwnd = hwnd.EnabledHwnd;
3803                                                 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);
3804                                                 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3805                                         }
3806
3807                                         if (Grab.Hwnd != IntPtr.Zero) {
3808                                                 msg.hwnd = Grab.Hwnd;
3809                                         }
3810
3811                                         if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3812                                                 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3813                                                 switch(xevent.ButtonEvent.button) {
3814                                                         case 1: {
3815                                                                 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3816                                                                 break;
3817                                                         }
3818
3819                                                         case 2: {
3820                                                                 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3821                                                                 break;
3822                                                         }
3823
3824                                                         case 3: {
3825                                                                 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3826                                                                 break;
3827                                                         }
3828                                                 }
3829                                                 ClickPending.Pending = false;
3830                                         } else {
3831                                                 ClickPending.Pending = true;
3832                                                 ClickPending.Hwnd = msg.hwnd;
3833                                                 ClickPending.Message = msg.message;
3834                                                 ClickPending.wParam = msg.wParam;
3835                                                 ClickPending.lParam = msg.lParam;
3836                                                 ClickPending.Time = (long)xevent.ButtonEvent.time;
3837                                         }
3838                                         
3839                                         if (msg.message == Msg.WM_LBUTTONDOWN || msg.message == Msg.WM_MBUTTONDOWN || msg.message == Msg.WM_RBUTTONDOWN) {
3840                                                 SendParentNotify(msg.hwnd, msg.message, mouse_position.X, mouse_position.Y);
3841
3842                                                 // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3843                                                 // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after 
3844                                                 // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3845                                                 XEvent motionEvent = new XEvent ();
3846                                                 motionEvent.type = XEventName.MotionNotify;
3847                                                 motionEvent.MotionEvent.display = DisplayHandle;
3848                                                 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3849                                                 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3850                                                 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3851                                                 hwnd.Queue.EnqueueLocked (motionEvent);
3852                                         }
3853                                         
3854                                         break;
3855                                 }
3856
3857                                 case XEventName.ButtonRelease: {
3858
3859                                         switch(xevent.ButtonEvent.button) {
3860                                                 case 1: {
3861                                                         if (client) {
3862                                                                 msg.message = Msg.WM_LBUTTONUP;
3863                                                         } else {
3864                                                                 msg.message = Msg.WM_NCLBUTTONUP;
3865                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3866                                                         }
3867                                                         MouseState &= ~MouseButtons.Left;
3868                                                         msg.wParam=GetMousewParam(0);
3869                                                         break;
3870                                                 }
3871
3872                                                 case 2: {
3873                                                         if (client) {
3874                                                                 msg.message = Msg.WM_MBUTTONUP;
3875                                                         } else {
3876                                                                 msg.message = Msg.WM_NCMBUTTONUP;
3877                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3878                                                         }
3879                                                         MouseState &= ~MouseButtons.Middle;
3880                                                         msg.wParam=GetMousewParam(0);
3881                                                         break;
3882                                                 }
3883
3884                                                 case 3: {
3885                                                         if (client) {
3886                                                                 msg.message = Msg.WM_RBUTTONUP;
3887                                                         } else {
3888                                                                 msg.message = Msg.WM_NCRBUTTONUP;
3889                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3890                                                         }
3891                                                         MouseState &= ~MouseButtons.Right;
3892                                                         msg.wParam=GetMousewParam(0);
3893                                                         break;
3894                                                 }
3895
3896                                                 case 4: {
3897                                                         goto ProcessNextMessage;
3898                                                 }
3899
3900                                                 case 5: {
3901                                                         goto ProcessNextMessage;
3902                                                 }
3903                                         }
3904
3905                                         if (!hwnd.Enabled) {
3906                                                 IntPtr dummy;
3907
3908                                                 msg.hwnd = hwnd.EnabledHwnd;
3909                                                 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);
3910                                                 msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3911                                         }
3912
3913                                         if (Grab.Hwnd != IntPtr.Zero) {
3914                                                 msg.hwnd = Grab.Hwnd;
3915                                         }
3916
3917                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3918                                         mouse_position.X = xevent.ButtonEvent.x;
3919                                         mouse_position.Y = xevent.ButtonEvent.y;
3920
3921                                         // Win32 splurts MouseMove events all over the place, regardless of whether the mouse is actually moving or
3922                                         // not, especially after mousedown and mouseup. To support apps relying on mousemove events between and after 
3923                                         // mouse clicks to repaint or whatever, we generate a mousemove event here. *sigh*
3924                                         if (msg.message == Msg.WM_LBUTTONUP || msg.message == Msg.WM_MBUTTONUP || msg.message == Msg.WM_RBUTTONUP) {
3925                                                 XEvent motionEvent = new XEvent ();
3926                                                 motionEvent.type = XEventName.MotionNotify;
3927                                                 motionEvent.MotionEvent.display = DisplayHandle;
3928                                                 motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
3929                                                 motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
3930                                                 motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
3931                                                 hwnd.Queue.EnqueueLocked (motionEvent);
3932                                         }
3933                                         break;
3934                                 }
3935
3936                                 case XEventName.MotionNotify: {
3937                                         if (client) {
3938                                                 #if DriverDebugExtra
3939                                                         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);
3940                                                 #endif
3941
3942                                                 if (Grab.Hwnd != IntPtr.Zero) {
3943                                                         msg.hwnd = Grab.Hwnd;
3944                                                 } else {
3945                                                         if (hwnd.Enabled) {
3946                                                                 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3947                                                         }
3948                                                 }
3949
3950                                                 if (xevent.MotionEvent.is_hint != 0)
3951                                                 {
3952                                                         IntPtr root, child;
3953                                                         int mask;
3954                                                         XQueryPointer (DisplayHandle, xevent.AnyEvent.window,
3955                                                                                         out root, out child,
3956                                                                                         out xevent.MotionEvent.x_root, 
3957                                                                                         out xevent.MotionEvent.y_root,
3958                                                                                         out xevent.MotionEvent.x,      
3959                                                                                         out xevent.MotionEvent.y, out mask);
3960                                                 }
3961
3962                                                 msg.message = Msg.WM_MOUSEMOVE;
3963                                                 msg.wParam = GetMousewParam(0);
3964                                                 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3965
3966                                                 if (!hwnd.Enabled) {
3967                                                         IntPtr dummy;
3968
3969                                                         msg.hwnd = hwnd.EnabledHwnd;
3970                                                         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);
3971                                                         msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
3972                                                 }
3973
3974                                                 mouse_position.X = xevent.MotionEvent.x;
3975                                                 mouse_position.Y = xevent.MotionEvent.y;
3976
3977                                                 if ((HoverState.Timer.Enabled) &&
3978                                                     (((mouse_position.X + HoverState.Size.Width) < HoverState.X) ||
3979                                                     ((mouse_position.X - HoverState.Size.Width) > HoverState.X) ||
3980                                                     ((mouse_position.Y + HoverState.Size.Height) < HoverState.Y) ||
3981                                                     ((mouse_position.Y - HoverState.Size.Height) > HoverState.Y))) {
3982                                                         HoverState.Timer.Stop();
3983                                                         HoverState.Timer.Start();
3984                                                         HoverState.X = mouse_position.X;
3985                                                         HoverState.Y = mouse_position.Y;
3986                                                 }
3987
3988                                                 break;
3989                                         } else {
3990                                                 HitTest ht;
3991                                                 IntPtr dummy;
3992                                                 int screen_x;
3993                                                 int screen_y;
3994
3995                                                 #if DriverDebugExtra
3996                                                         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);
3997                                                 #endif
3998                                                 msg.message = Msg.WM_NCMOUSEMOVE;
3999
4000                                                 if (!hwnd.Enabled) {
4001                                                         msg.hwnd = hwnd.EnabledHwnd;
4002                                                         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);
4003                                                         msg.lParam = (IntPtr)(mouse_position.Y << 16 | mouse_position.X);
4004                                                 }
4005
4006                                                 // The hit test is sent in screen coordinates
4007                                                 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
4008                                                                 xevent.MotionEvent.x, xevent.MotionEvent.y,
4009                                                                 out screen_x, out screen_y, out dummy);
4010
4011                                                 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
4012                                                 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
4013                                                                 IntPtr.Zero, msg.lParam).ToInt32 ();
4014                                                 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
4015
4016                                                 mouse_position.X = xevent.MotionEvent.x;
4017                                                 mouse_position.Y = xevent.MotionEvent.y;
4018                                         }
4019
4020                                         break;
4021                                 }
4022
4023                                 case XEventName.EnterNotify: {
4024                                         if (!hwnd.Enabled) {
4025                                                 goto ProcessNextMessage;
4026                                         }
4027                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal && xevent.CrossingEvent.window != hwnd.client_window) {
4028                                                 goto ProcessNextMessage;
4029                                         }
4030                                         msg.message = Msg.WM_MOUSE_ENTER;
4031                                         HoverState.X = xevent.CrossingEvent.x;
4032                                         HoverState.Y = xevent.CrossingEvent.y;
4033                                         HoverState.Timer.Enabled = true;
4034                                         HoverState.Window = xevent.CrossingEvent.window;
4035
4036                                         // Win32 sends a WM_MOUSEMOVE after mouse enter
4037                                         XEvent motionEvent = new XEvent ();
4038                                         motionEvent.type = XEventName.MotionNotify;
4039                                         motionEvent.MotionEvent.display = DisplayHandle;
4040                                         motionEvent.MotionEvent.window = xevent.ButtonEvent.window;
4041                                         motionEvent.MotionEvent.x = xevent.ButtonEvent.x;
4042                                         motionEvent.MotionEvent.y = xevent.ButtonEvent.y;
4043                                         hwnd.Queue.EnqueueLocked (motionEvent);
4044                                         break;
4045                                 }
4046
4047                                 case XEventName.LeaveNotify: {
4048                                         if (xevent.CrossingEvent.mode == NotifyMode.NotifyUngrab) {
4049                                                 WindowUngrabbed (hwnd.Handle);
4050                                                 goto ProcessNextMessage;
4051                                         }
4052                                         if (!hwnd.Enabled) {
4053                                                 goto ProcessNextMessage;
4054                                         }
4055                                         if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
4056                                                 goto ProcessNextMessage;
4057                                         }
4058
4059                                         // Reset the cursor explicitly on X11.
4060                                         // X11 remembers the last set cursor for the window and in cases where 
4061                                         // the control won't get a WM_SETCURSOR X11 will restore the last 
4062                                         // known cursor, which we don't want.
4063                                         // 
4064                                         SetCursor (hwnd.client_window, IntPtr.Zero);
4065
4066                                         msg.message=Msg.WM_MOUSELEAVE;
4067                                         HoverState.Timer.Enabled = false;
4068                                         HoverState.Window = IntPtr.Zero;
4069                                         break;
4070                                 }
4071
4072                                 #if later
4073                                 case XEventName.CreateNotify: {
4074                                         if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
4075                                                 msg.message = WM_CREATE;
4076                                                 // Set up CreateStruct
4077                                         } else {
4078                                                 goto ProcessNextMessage;
4079                                         }
4080                                         break;
4081                                 }
4082                                 #endif
4083
4084
4085                                 case XEventName.ReparentNotify: {
4086                                         if (hwnd.parent == null) {      // Toplevel
4087                                                 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
4088                                                         hwnd.Reparented = true;
4089
4090                                                         // The location given by the event is not reliable between different wm's, 
4091                                                         // so use an alternative way of getting it.
4092                                                         Point location = GetTopLevelWindowLocation (hwnd);
4093                                                         hwnd.X = location.X;
4094                                                         hwnd.Y = location.Y;
4095
4096                                                         if (hwnd.opacity != 0xffffffff) {
4097                                                                 IntPtr opacity;
4098
4099                                                                 opacity = (IntPtr)(Int32)hwnd.opacity;
4100                                                                 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4101                                                         }
4102                                                         SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
4103                                                         goto ProcessNextMessage;
4104                                                 } else {
4105                                                         hwnd.Reparented = false;
4106                                                         goto ProcessNextMessage;
4107                                                 }
4108                                         }
4109                                         goto ProcessNextMessage;
4110                                 }
4111
4112                                 case XEventName.ConfigureNotify: {
4113                                         if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {        // Ignore events for children (SubstructureNotify) and client areas
4114                                                 #if DriverDebugExtra
4115                                                         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);
4116                                                 #endif
4117
4118                                                 lock (hwnd.configure_lock) {
4119                                                         Form form = Control.FromHandle (hwnd.client_window) as Form;
4120                                                         if (form != null && !hwnd.resizing_or_moving) {
4121                                                                 if (hwnd.x != form.Bounds.X || hwnd.y != form.Bounds.Y) {
4122                                                                         SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_MOVE, IntPtr.Zero);
4123                                                                         hwnd.resizing_or_moving = true;
4124                                                                 } else if (hwnd.width != form.Bounds.Width || hwnd.height != form.Bounds.Height) {
4125                                                                         SendMessage (form.Handle, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_SIZE, IntPtr.Zero);
4126                                                                         hwnd.resizing_or_moving = true;
4127                                                                 }
4128                                                                 if (hwnd.resizing_or_moving)
4129                                                                         SendMessage (form.Handle, Msg.WM_ENTERSIZEMOVE, IntPtr.Zero, IntPtr.Zero);
4130                                                         }
4131         
4132                                                         SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4133                                                         hwnd.configure_pending = false;
4134         
4135                                                         // We need to adjust our client window to track the resize of whole_window
4136                                                         if (hwnd.whole_window != hwnd.client_window)
4137                                                                 PerformNCCalc(hwnd);
4138                                                 }
4139                                         }
4140                                         goto ProcessNextMessage;
4141                                 }
4142
4143                                 case XEventName.FocusIn: {
4144                                         // We received focus. We use X11 focus only to know if the app window does or does not have focus
4145                                         // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
4146                                         // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know 
4147                                         // about it having focus again
4148                                         if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4149                                                 goto ProcessNextMessage;
4150                                         }
4151
4152                                         if (FocusWindow == IntPtr.Zero) {
4153                                                 Control c = Control.FromHandle (hwnd.client_window);
4154                                                 if (c == null)
4155                                                         goto ProcessNextMessage;
4156                                                 Form form = c.FindForm ();
4157                                                 if (form == null)
4158                                                         goto ProcessNextMessage;
4159                                                 if (ActiveWindow != form.Handle) {
4160                                                         ActiveWindow = form.Handle;
4161                                                         SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
4162                                                 }
4163                                                 goto ProcessNextMessage;
4164                                         }
4165                                         SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
4166                                         Keyboard.FocusIn (FocusWindow);
4167                                         goto ProcessNextMessage;
4168                                 }
4169
4170                                 case XEventName.FocusOut: {
4171                                         // Se the comment for our FocusIn handler
4172                                         if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
4173                                                 goto ProcessNextMessage;
4174                                         }
4175
4176                                         while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
4177                                                 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
4178                                         }
4179
4180                                         Keyboard.FocusOut(hwnd.client_window);
4181                                         SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
4182                                         goto ProcessNextMessage;
4183                                 }
4184
4185                                 case XEventName.MapNotify: {
4186                                         if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4187                                                 hwnd.mapped = true;
4188                                                 msg.message = Msg.WM_SHOWWINDOW;
4189                                                 msg.wParam = (IntPtr) 1;
4190                                                 // XXX we're missing the lParam..
4191                                                 break;
4192                                         }
4193                                         goto ProcessNextMessage;
4194                                 }
4195
4196                                 case XEventName.UnmapNotify: {
4197                                         if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) { // Ignore events for children (SubstructureNotify) and client areas
4198                                                 hwnd.mapped = false;
4199                                                 msg.message = Msg.WM_SHOWWINDOW;
4200                                                 msg.wParam = (IntPtr) 0;
4201                                                 // XXX we're missing the lParam..
4202                                                 break;
4203                                         }
4204                                         goto ProcessNextMessage;
4205                                 }
4206
4207                                 case XEventName.Expose: {
4208                                         if (!hwnd.Mapped) {
4209                                                 if (client) {
4210                                                         hwnd.expose_pending = false;
4211                                                 } else {
4212                                                         hwnd.nc_expose_pending = false;
4213                                                 }
4214                                                 goto ProcessNextMessage;
4215                                         }
4216
4217                                         if (client) {
4218                                                 if (!hwnd.expose_pending) {
4219                                                         goto ProcessNextMessage;
4220                                                 }
4221                                         } else {
4222                                                 if (!hwnd.nc_expose_pending) {
4223                                                         goto ProcessNextMessage;
4224                                                 }
4225
4226                                                 switch (hwnd.border_style) {
4227                                                         case FormBorderStyle.Fixed3D: {
4228                                                                 Graphics g;
4229
4230                                                                 g = Graphics.FromHwnd(hwnd.whole_window);
4231                                                                 if (hwnd.border_static)
4232                                                                         ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.SunkenOuter);
4233                                                                 else
4234                                                                         ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
4235                                                                 g.Dispose();
4236                                                                 break;
4237                                                         }
4238
4239                                                         case FormBorderStyle.FixedSingle: {
4240                                                                 Graphics g;
4241
4242                                                                 g = Graphics.FromHwnd(hwnd.whole_window);
4243                                                                 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
4244                                                                 g.Dispose();
4245                                                                 break;
4246                                                         }
4247                                                 }
4248                                                 #if DriverDebugExtra
4249                                                         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);
4250                                                 #endif
4251
4252                                                 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
4253                                                 Region region = new Region (rect);
4254                                                 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
4255                                                 msg.message = Msg.WM_NCPAINT;
4256                                                 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
4257                                                 msg.refobject = region;
4258                                                 break;
4259                                         }
4260                                         #if DriverDebugExtra
4261                                                 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);
4262                                         #endif
4263                                         if (Caret.Visible == true) {
4264                                                 Caret.Paused = true;
4265                                                 HideCaret();
4266                                         }
4267
4268                                         if (Caret.Visible == true) {
4269                                                 ShowCaret();
4270                                                 Caret.Paused = false;
4271                                         }
4272                                         msg.message = Msg.WM_PAINT;
4273                                         break;
4274                                 }
4275
4276                                 case XEventName.DestroyNotify: {
4277
4278                                         // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
4279                                         hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
4280
4281                                         // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
4282                                         if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
4283                                                 CleanupCachedWindows (hwnd);
4284
4285                                                 #if DriverDebugDestroy
4286                                                         Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
4287                                                 #endif
4288
4289                                                 msg.hwnd = hwnd.client_window;
4290                                                 msg.message=Msg.WM_DESTROY;
4291                                                 hwnd.Dispose();
4292                                         } else {
4293                                                 goto ProcessNextMessage;
4294                                         }
4295
4296                                         break;
4297                                 }
4298
4299                                 case XEventName.ClientMessage: {
4300                                         if (Dnd.HandleClientMessage (ref xevent)) {
4301                                                 goto ProcessNextMessage;
4302                                         }
4303
4304                                         if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
4305                                                 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
4306                                                 goto ProcessNextMessage;
4307                                         }
4308
4309                                         if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
4310                                                 msg.message = Msg.WM_MOUSEHOVER;
4311                                                 msg.wParam = GetMousewParam(0);
4312                                                 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
4313                                                 return true;
4314                                         }
4315
4316                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
4317                                                 msg.hwnd = xevent.ClientMessageEvent.ptr1;
4318                                                 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
4319                                                 msg.wParam = xevent.ClientMessageEvent.ptr3;
4320                                                 msg.lParam = xevent.ClientMessageEvent.ptr4;
4321                                                 if (msg.message == (Msg)Msg.WM_QUIT)
4322                                                         return false;
4323                                                 else
4324                                                         return true;
4325                                         }
4326
4327                                         if  (xevent.ClientMessageEvent.message_type == _XEMBED) {
4328 #if DriverDebugXEmbed
4329                                                 Console.WriteLine("GOT EMBED MESSAGE {0:X}, detail {1:X}", xevent.ClientMessageEvent.ptr2.ToInt32(), xevent.ClientMessageEvent.ptr3.ToInt32());
4330 #endif
4331
4332                                                 if (xevent.ClientMessageEvent.ptr2.ToInt32() == (int)XEmbedMessage.EmbeddedNotify) {
4333                                                         XSizeHints hints = new XSizeHints();
4334                                                         IntPtr dummy;
4335
4336                                                         XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4337
4338                                                         hwnd.width = hints.max_width;
4339                                                         hwnd.height = hints.max_height;
4340                                                         hwnd.ClientRect = Rectangle.Empty;
4341                                                         SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4342                                                 }
4343                                         }
4344
4345                                         if  (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
4346                                                 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
4347                                                         SendMessage (msg.hwnd, Msg.WM_SYSCOMMAND, (IntPtr)SystemCommands.SC_CLOSE, IntPtr.Zero);
4348                                                         msg.message = Msg.WM_CLOSE;
4349                                                         return true;
4350                                                 }
4351
4352                                                 // We should not get this, but I'll leave the code in case we need it in the future
4353                                                 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
4354                                                         goto ProcessNextMessage;
4355                                                 }
4356                                         }
4357                                         goto ProcessNextMessage;
4358                                 }
4359
4360                                 default: {
4361                                         goto ProcessNextMessage;
4362                                 }
4363                         }
4364
4365                         return true;
4366                 }
4367
4368                 internal override bool GetText(IntPtr handle, out string text) {
4369
4370                         lock (XlibLock) {
4371                                 IntPtr actual_atom;
4372                                 int actual_format;
4373                                 IntPtr nitems;
4374                                 IntPtr bytes_after;
4375                                 IntPtr prop = IntPtr.Zero;
4376
4377                                 XGetWindowProperty(DisplayHandle, handle,
4378                                                    _NET_WM_NAME, IntPtr.Zero, new IntPtr (1), false,
4379                                                    UNICODETEXT, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
4380
4381                                 if ((long)nitems > 0 && prop != IntPtr.Zero) {
4382                                         text = Marshal.PtrToStringUni (prop, (int)nitems);
4383                                         XFree (prop);
4384                                         return true;
4385                                 }
4386                                 else {
4387                                         // fallback on the non-_NET property
4388                                         IntPtr  textptr;
4389
4390                                         textptr = IntPtr.Zero;
4391
4392                                         XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
4393                                         if (textptr != IntPtr.Zero) {
4394                                                 text = Marshal.PtrToStringAnsi(textptr);
4395                                                 XFree(textptr);
4396                                                 return true;
4397                                         } else {
4398                                                 text = "";
4399                                                 return false;
4400                                         }
4401                                 }
4402                         }
4403                 }
4404
4405                 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) {
4406                         Hwnd            hwnd;
4407
4408                         hwnd = Hwnd.ObjectFromHandle(handle);
4409
4410                         if (hwnd != null) {
4411                                 x = hwnd.x;
4412                                 y = hwnd.y;
4413                                 width = hwnd.width;
4414                                 height = hwnd.height;
4415
4416                                 PerformNCCalc(hwnd);
4417
4418                                 client_width = hwnd.ClientRect.Width;
4419                                 client_height = hwnd.ClientRect.Height;
4420
4421                                 return;
4422                         }
4423
4424                         // Should we throw an exception or fail silently?
4425                         // throw new ArgumentException("Called with an invalid window handle", "handle");
4426
4427                         x = 0;
4428                         y = 0;
4429                         width = 0;
4430                         height = 0;
4431                         client_width = 0;
4432                         client_height = 0;
4433                 }
4434
4435                 internal override FormWindowState GetWindowState(IntPtr handle) {
4436                         Hwnd                    hwnd;
4437
4438                         hwnd = Hwnd.ObjectFromHandle(handle);
4439
4440                         if (hwnd.cached_window_state == (FormWindowState)(-1))
4441                                 hwnd.cached_window_state = UpdateWindowState (handle);
4442
4443                         return hwnd.cached_window_state;
4444                 }
4445
4446                 private FormWindowState UpdateWindowState (IntPtr handle) {
4447                         IntPtr                  actual_atom;
4448                         int                     actual_format;
4449                         IntPtr                  nitems;
4450                         IntPtr                  bytes_after;
4451                         IntPtr                  prop = IntPtr.Zero;
4452                         IntPtr                  atom;
4453                         int                     maximized;
4454                         bool                    minimized;
4455                         XWindowAttributes       attributes;
4456                         Hwnd                    hwnd;
4457
4458                         hwnd = Hwnd.ObjectFromHandle(handle);
4459
4460                         maximized = 0;
4461                         minimized = false;
4462                         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);
4463                         if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
4464                                 for (int i = 0; i < (long)nitems; i++) {
4465                                         atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
4466                                         if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
4467                                                 maximized++;
4468                                         } else if (atom == _NET_WM_STATE_HIDDEN) {
4469                                                 minimized = true;
4470                                         }
4471                                 }
4472                                 XFree(prop);
4473                         }
4474
4475                         if (minimized) {
4476                                 return FormWindowState.Minimized;
4477                         } else if (maximized == 2) {
4478                                 return FormWindowState.Maximized;
4479                         }
4480
4481                         attributes = new XWindowAttributes();
4482                         XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4483                         if (attributes.map_state == MapState.IsUnmapped) {
4484                                 return (FormWindowState)(-1);
4485                         }
4486
4487
4488                         return FormWindowState.Normal;
4489                 }
4490
4491                 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
4492                         handle = Grab.Hwnd;
4493                         GrabConfined = Grab.Confined;
4494                         GrabArea = Grab.Area;
4495                 }
4496
4497                 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
4498                         Hwnd    hwnd;
4499                         IntPtr  confine_to_window;
4500
4501                         confine_to_window = IntPtr.Zero;
4502
4503                         if (confine_to_handle != IntPtr.Zero) {
4504                                 XWindowAttributes       attributes = new XWindowAttributes();
4505
4506                                 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
4507
4508                                 lock (XlibLock) {
4509                                         XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
4510                                 }
4511                                 Grab.Area.X = attributes.x;
4512                                 Grab.Area.Y = attributes.y;
4513                                 Grab.Area.Width = attributes.width;
4514                                 Grab.Area.Height = attributes.height;
4515                                 Grab.Confined = true;
4516                                 confine_to_window = hwnd.client_window;
4517                         }
4518
4519                         Grab.Hwnd = handle;
4520
4521                         hwnd = Hwnd.ObjectFromHandle(handle);
4522
4523                         lock (XlibLock) {
4524                                 XGrabPointer(DisplayHandle, hwnd.client_window, false, 
4525                                         EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
4526                                         EventMask.ButtonReleaseMask | EventMask.PointerMotionMask | 
4527                                         EventMask.PointerMotionHintMask | EventMask.LeaveWindowMask,
4528                                         GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
4529                         }
4530                 }
4531
4532                 internal override void UngrabWindow(IntPtr hwnd) {
4533                         lock (XlibLock) {
4534                                 XUngrabPointer(DisplayHandle, IntPtr.Zero);
4535                                 XFlush(DisplayHandle);
4536                         }
4537                         WindowUngrabbed (hwnd);                 
4538                 }
4539                 
4540                 private void WindowUngrabbed (IntPtr hwnd) {
4541                         bool was_grabbed = Grab.Hwnd != IntPtr.Zero;
4542                         
4543                         Grab.Hwnd = IntPtr.Zero;
4544                         Grab.Confined = false;
4545                         
4546                         if (was_grabbed) {
4547                                 // lparam should be the handle to the window gaining the mouse capture,
4548                                 // but X doesn't seem to give us that information.
4549                                 // Also only generate WM_CAPTURECHANGED if the window actually was grabbed.
4550                                 // X will send a NotifyUngrab, but since it comes late sometimes we're
4551                                 // calling WindowUngrabbed directly from UngrabWindow in order to send
4552                                 // this WM right away.
4553                                 SendMessage (hwnd, Msg.WM_CAPTURECHANGED, IntPtr.Zero, IntPtr.Zero);
4554                         }
4555                 }
4556
4557                 internal override void HandleException(Exception e) {
4558                         StackTrace st = new StackTrace(e, true);
4559                         Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
4560                         Console.WriteLine("{0}{1}", e.Message, st.ToString());
4561                 }
4562
4563                 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
4564                         Hwnd    hwnd;
4565
4566                         hwnd = Hwnd.ObjectFromHandle(handle);
4567
4568                         if (clear) {
4569                                 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
4570                         } else {
4571                                 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
4572                         }
4573                 }
4574
4575                 internal override void InvalidateNC (IntPtr handle) {
4576                         Hwnd    hwnd;
4577
4578                         hwnd = Hwnd.ObjectFromHandle(handle);
4579
4580                         AddExpose (hwnd, false, 0, 0, hwnd.Width, hwnd.Height);
4581                 }
4582
4583                 internal override bool IsEnabled(IntPtr handle) {
4584                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4585                         return (hwnd != null && hwnd.Enabled);
4586                 }
4587                 
4588                 internal override bool IsVisible(IntPtr handle) {
4589                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4590                         return (hwnd != null && hwnd.visible);
4591                 }
4592
4593                 internal override void KillTimer(Timer timer) {
4594                         XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4595
4596                         if (queue == null) {
4597                                 // This isn't really an error, MS doesn't start the timer if
4598                                 // it has no assosciated queue. In this case, remove the timer
4599                                 // from the list of unattached timers (if it was enabled).
4600                                 lock (unattached_timer_list) {
4601                                         if (unattached_timer_list.Contains (timer))
4602                                                 unattached_timer_list.Remove (timer);
4603                                 }
4604                                 return;
4605                         }
4606                         queue.timer_list.Remove (timer);
4607                 }
4608
4609                 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
4610                         int     dest_x_return;
4611                         int     dest_y_return;
4612                         IntPtr  child;
4613                         Hwnd    hwnd;
4614
4615                         hwnd = Hwnd.ObjectFromHandle(handle);
4616
4617                         lock (XlibLock) {
4618                                 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
4619                         }
4620
4621                         x = dest_x_return;
4622                         y = dest_y_return;
4623                 }
4624
4625                 internal override void OverrideCursor(IntPtr cursor)
4626                 {
4627                         if (Grab.Hwnd != IntPtr.Zero) {
4628                                 XChangeActivePointerGrab (DisplayHandle,
4629                                                 EventMask.ButtonMotionMask |
4630                                                 EventMask.PointerMotionMask |
4631                                                 EventMask.PointerMotionHintMask |
4632                                                 EventMask.ButtonPressMask |
4633                                                 EventMask.ButtonReleaseMask,
4634                                                 cursor, IntPtr.Zero);
4635                                 return;
4636                         }
4637
4638                         OverrideCursorHandle = cursor;
4639                 }
4640
4641                 internal override PaintEventArgs PaintEventStart(ref Message msg, IntPtr handle, bool client) {
4642                         PaintEventArgs  paint_event;
4643                         Hwnd            hwnd;
4644                         Hwnd            paint_hwnd;
4645                         
4646                         // 
4647                         // handle  (and paint_hwnd) refers to the window that is should be painted.
4648                         // msg.HWnd (and hwnd) refers to the window that got the paint message.
4649                         // 
4650                         
4651                         hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
4652                         if (msg.HWnd == handle) {
4653                                 paint_hwnd = hwnd;
4654                         } else {
4655                                 paint_hwnd = Hwnd.ObjectFromHandle (handle);
4656                         }
4657         
4658                         if (Caret.Visible == true) {
4659                                 Caret.Paused = true;
4660                                 HideCaret();
4661                         }
4662
4663                         Graphics dc;
4664
4665                         if (client) {
4666                                 dc = Graphics.FromHwnd (paint_hwnd.client_window);
4667
4668                                 Region clip_region = new Region ();
4669                                 clip_region.MakeEmpty();
4670
4671                                 foreach (Rectangle r in hwnd.ClipRectangles) {
4672                                         clip_region.Union (r);
4673                                 }
4674
4675                                 if (hwnd.UserClip != null) {
4676                                         clip_region.Intersect(hwnd.UserClip);
4677                                 }
4678
4679                                 dc.Clip = clip_region;
4680                                 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
4681                                 hwnd.expose_pending = false;
4682
4683                                 hwnd.ClearInvalidArea();
4684
4685                                 hwnd.drawing_stack.Push (paint_event);
4686                                 hwnd.drawing_stack.Push (dc);
4687
4688                                 return paint_event;
4689                         } else {
4690                                 dc = Graphics.FromHwnd (paint_hwnd.whole_window);
4691
4692                                 if (!hwnd.nc_invalid.IsEmpty) {
4693                                         dc.SetClip (hwnd.nc_invalid);
4694                                         paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
4695                                 } else {
4696                                         paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
4697                                 }
4698                                 hwnd.nc_expose_pending = false;
4699
4700                                 hwnd.ClearNcInvalidArea ();
4701
4702                                 hwnd.drawing_stack.Push (paint_event);
4703                                 hwnd.drawing_stack.Push (dc);
4704
4705                                 return paint_event;
4706                         }
4707                 }
4708
4709                 internal override void PaintEventEnd(ref Message msg, IntPtr handle, bool client) {
4710                         Hwnd    hwnd;
4711
4712                         hwnd = Hwnd.ObjectFromHandle (msg.HWnd);
4713
4714                         Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
4715                         dc.Flush();
4716                         dc.Dispose();
4717                         
4718                         PaintEventArgs pe = (PaintEventArgs)hwnd.drawing_stack.Pop();
4719                         pe.SetGraphics (null);
4720                         pe.Dispose ();
4721
4722                         if (Caret.Visible == true) {
4723                                 ShowCaret();
4724                                 Caret.Paused = false;
4725                         }
4726                 }
4727
4728                 [MonoTODO("Implement filtering and PM_NOREMOVE")]
4729                 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
4730                         XEventQueue queue = (XEventQueue) queue_id;
4731                         bool    pending;
4732
4733                         if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
4734                                 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet");    // FIXME - Implement PM_NOREMOVE flag
4735                         }
4736
4737                         pending = false;
4738                         if (queue.Count > 0) {
4739                                 pending = true;
4740                         } else {
4741                                 // Only call UpdateMessageQueue if real events are pending 
4742                                 // otherwise we go to sleep on the socket
4743                                 if (XPending(DisplayHandle) != 0) {
4744                                         UpdateMessageQueue((XEventQueue)queue_id);
4745                                         pending = true;
4746                                 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
4747                                         pending = true;
4748                                 }
4749                         }
4750
4751                         CheckTimers(queue.timer_list, DateTime.UtcNow);
4752
4753                         if (!pending) {
4754                                 return false;
4755                         }
4756                         return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
4757                 }
4758
4759                 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
4760                         XEvent xevent = new XEvent ();
4761                         Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
4762
4763                         xevent.type = XEventName.ClientMessage;
4764                         xevent.ClientMessageEvent.display = DisplayHandle;
4765
4766                         if (hwnd != null) {
4767                                 xevent.ClientMessageEvent.window = hwnd.whole_window;
4768                         } else {
4769                                 xevent.ClientMessageEvent.window = IntPtr.Zero;
4770                         }
4771
4772                         xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4773                         xevent.ClientMessageEvent.format = 32;
4774                         xevent.ClientMessageEvent.ptr1 = handle;
4775                         xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4776                         xevent.ClientMessageEvent.ptr3 = wparam;
4777                         xevent.ClientMessageEvent.ptr4 = lparam;
4778
4779                         if (hwnd != null)
4780                                 hwnd.Queue.EnqueueLocked (xevent);
4781                         else
4782                                 ThreadQueue(Thread.CurrentThread).EnqueueLocked (xevent);
4783
4784                         return true;
4785                 }
4786
4787                 internal override void PostQuitMessage(int exitCode) {
4788                         ApplicationContext ctx = Application.MWFThread.Current.Context;
4789                         Form f = ctx != null ? ctx.MainForm : null;
4790                         if (f != null)
4791                                 PostMessage (Application.MWFThread.Current.Context.MainForm.window.Handle, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4792                         else
4793                                 PostMessage (FosterParent, Msg.WM_QUIT, IntPtr.Zero, IntPtr.Zero);
4794                         XFlush(DisplayHandle);
4795                 }
4796
4797                 internal override void RequestAdditionalWM_NCMessages(IntPtr hwnd, bool hover, bool leave)
4798                 {
4799                         // TODO
4800                 }
4801
4802                 internal override void RequestNCRecalc(IntPtr handle) {
4803                         Hwnd                            hwnd;
4804
4805                         hwnd = Hwnd.ObjectFromHandle(handle);
4806
4807                         if (hwnd == null) {
4808                                 return;
4809                         }
4810
4811                         PerformNCCalc(hwnd);
4812                         SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4813                         InvalidateNC(handle);
4814                 }
4815
4816                 internal override void ResetMouseHover(IntPtr handle) {
4817                         Hwnd    hwnd;
4818
4819                         hwnd = Hwnd.ObjectFromHandle(handle);
4820                         if (hwnd == null) {
4821                                 return;
4822                         }
4823
4824                         HoverState.Timer.Enabled = true;
4825                         HoverState.X = mouse_position.X;
4826                         HoverState.Y = mouse_position.Y;
4827                         HoverState.Window = handle;
4828                 }
4829
4830
4831                 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4832                         int     dest_x_return;
4833                         int     dest_y_return;
4834                         IntPtr  child;
4835                         Hwnd    hwnd;
4836
4837                         hwnd = Hwnd.ObjectFromHandle(handle);
4838
4839                         lock (XlibLock) {
4840                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4841                         }
4842
4843                         x = dest_x_return;
4844                         y = dest_y_return;
4845                 }
4846
4847                 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4848                         int     dest_x_return;
4849                         int     dest_y_return;
4850                         IntPtr  child;
4851                         Hwnd    hwnd;
4852
4853                         hwnd = Hwnd.ObjectFromHandle(handle);
4854
4855                         lock (XlibLock) {
4856                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4857                         }
4858
4859                         Form form = Control.FromHandle (handle) as Form;
4860                         if (form != null && form.window_manager != null) {
4861                                 dest_y_return -= form.window_manager.TitleBarHeight;
4862                         }
4863
4864                         x = dest_x_return;
4865                         y = dest_y_return;
4866                 }
4867
4868                 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4869                         Hwnd            hwnd;
4870                         IntPtr          gc;
4871                         XGCValues       gc_values;
4872
4873                         hwnd = Hwnd.ObjectFromHandle(handle);
4874
4875                         Rectangle r = Rectangle.Intersect (hwnd.Invalid, area);
4876                         if (!r.IsEmpty) {
4877                                 /* We have an invalid area in the window we're scrolling. 
4878                                    Adjust our stored invalid rectangle to to match the scrolled amount */
4879
4880                                 r.X += XAmount;
4881                                 r.Y += YAmount;
4882
4883                                 if (r.X < 0) {
4884                                         r.Width += r.X;
4885                                         r.X =0;
4886                                 }
4887
4888                                 if (r.Y < 0) {
4889                                         r.Height += r.Y;
4890                                         r.Y =0;
4891                                 }
4892
4893                                 if (area.Contains (hwnd.Invalid))
4894                                         hwnd.ClearInvalidArea ();
4895                                 hwnd.AddInvalidArea(r);
4896                         }
4897
4898                         gc_values = new XGCValues();
4899
4900                         if (with_children) {
4901                                 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4902                         }
4903
4904                         gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4905
4906                         Rectangle visible_rect = GetTotalVisibleArea (hwnd.client_window);
4907                         visible_rect.Intersect (area);
4908
4909                         Rectangle dest_rect = visible_rect;
4910                         dest_rect.Y += YAmount;
4911                         dest_rect.X += XAmount;
4912                         dest_rect.Intersect (area);
4913
4914                         Point src = new Point (dest_rect.X - XAmount, dest_rect.Y - YAmount);
4915                         XCopyArea (DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src.X, src.Y, 
4916                                         dest_rect.Width, dest_rect.Height, dest_rect.X, dest_rect.Y);
4917
4918                         Rectangle dirty_area = GetDirtyArea (area, dest_rect, XAmount, YAmount);
4919                         AddExpose (hwnd, true, dirty_area.X, dirty_area.Y, dirty_area.Width, dirty_area.Height);
4920
4921                         XFreeGC(DisplayHandle, gc);
4922                 }
4923
4924                 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4925                         Hwnd            hwnd;
4926                         Rectangle       rect;
4927
4928                         hwnd = Hwnd.GetObjectFromWindow(handle);
4929
4930                         rect = hwnd.ClientRect;
4931                         rect.X = 0;
4932                         rect.Y = 0;
4933                         ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4934                 }
4935
4936                 Rectangle GetDirtyArea (Rectangle total_area, Rectangle valid_area, int XAmount, int YAmount)
4937                 {
4938                         Rectangle dirty_area = total_area;
4939
4940                         if (YAmount > 0)
4941                                 dirty_area.Height -= valid_area.Height;
4942                         else if (YAmount < 0) {
4943                                 dirty_area.Height -= valid_area.Height;
4944                                 dirty_area.Y += valid_area.Height;
4945                         }
4946
4947                         if (XAmount > 0)
4948                                 dirty_area.Width -= valid_area.Width;
4949                         else if (XAmount < 0) {
4950                                 dirty_area.Width -= valid_area.Width;
4951                                 dirty_area.X += valid_area.Width;
4952                         }
4953
4954                         return dirty_area;
4955                 }
4956
4957                 Rectangle GetTotalVisibleArea (IntPtr handle)
4958                 {
4959                         Control c = Control.FromHandle (handle);
4960
4961                         Rectangle visible_area = c.ClientRectangle;
4962                         visible_area.Location = c.PointToScreen (Point.Empty);
4963
4964                         for (Control parent = c.Parent; parent != null; parent = parent.Parent) {
4965                                 if (!parent.IsHandleCreated || !parent.Visible)
4966                                         return visible_area; // Non visible, not need to finish computations
4967
4968                                 Rectangle r = parent.ClientRectangle;
4969                                 r.Location = parent.PointToScreen (Point.Empty);
4970
4971                                 visible_area.Intersect (r);
4972                         }
4973
4974                         // If region is null, the entire area is visible.
4975                         // Get the area not obscured otherwise.
4976                         Region visible_region = GetVisibleRegion (c, visible_area);
4977                         if (visible_region != null) {
4978                                 RectangleF rectf = visible_region.GetBounds (Hwnd.GraphicsContext);
4979                                 visible_area = new Rectangle ((int) rectf.X, (int) rectf.Y,
4980                                                 (int) rectf.Width, (int) rectf.Height);
4981
4982                                 visible_region.Dispose ();
4983                         }
4984
4985                         visible_area.Location = c.PointToClient (visible_area.Location);
4986                         return visible_area;
4987                 }
4988
4989                 // Obscured area by other toplevel windows
4990                 Region GetVisibleRegion (Control c, Rectangle visible_area)
4991                 {
4992                         Region visible_region = null;
4993                         IntPtr Root;
4994                         IntPtr Parent;
4995                         IntPtr Children;
4996                         int ChildCount;
4997
4998                         Control form = c.FindForm ();
4999                         if (form == null || !form.IsHandleCreated)
5000                                 return null;
5001
5002                         Hwnd hwnd = Hwnd.GetObjectFromWindow (form.Handle);
5003                         IntPtr form_handle = hwnd.whole_window;
5004
5005                         lock (XlibLock) {
5006                                 XQueryTree (DisplayHandle, RootWindow, out Root, out Parent, out Children, out ChildCount);
5007                         }
5008
5009                         int intptr_size = Marshal.SizeOf (typeof (int));
5010                         bool above = false;
5011
5012                         for (int i = 0; i < ChildCount; i++) {
5013                                 IntPtr window = new IntPtr (Marshal.ReadInt32 (Children, i * intptr_size));
5014
5015                                 XWindowAttributes win_attrs = new XWindowAttributes ();
5016                                 lock (XlibLock) {
5017                                         XGetWindowAttributes (DisplayHandle, window, ref win_attrs);
5018                                 }
5019
5020                                 Rectangle win_area = new Rectangle (win_attrs.x, win_attrs.y, 
5021                                                 win_attrs.width, win_attrs.height);
5022
5023                                 if (win_attrs.map_state != MapState.IsViewable || !win_area.IntersectsWith (visible_area))
5024                                         continue;
5025
5026                                 IntPtr SubChildren;
5027                                 int SubChildCount;
5028
5029                                 if (above) {
5030                                         if (visible_region == null)
5031                                                 visible_region = new Region (visible_area);
5032
5033                                         visible_region.Exclude (win_area);
5034                                         continue;
5035                                 }
5036
5037                                 lock (XlibLock) {
5038                                         XQueryTree (DisplayHandle, window, out Root, out Parent, out SubChildren, out SubChildCount);
5039                                 }
5040
5041                                 if (SubChildren != IntPtr.Zero) {
5042                                         IntPtr sub_win = new IntPtr (Marshal.ReadInt32 (SubChildren));
5043
5044                                         lock (XlibLock) {
5045                                                 XFree (SubChildren);
5046                                         }
5047
5048                                         if (sub_win == form_handle)
5049                                                 above = true;
5050                                 }
5051                         }
5052
5053                         if (Children != IntPtr.Zero) {
5054                                 lock (XlibLock) {
5055                                         XFree (Children);
5056                                 }
5057                         }
5058
5059                         return visible_region;
5060                 }
5061
5062                 internal override void SendAsyncMethod (AsyncMethodData method) {
5063                         Hwnd    hwnd;
5064                         XEvent  xevent = new XEvent ();
5065
5066                         hwnd = Hwnd.ObjectFromHandle(method.Handle);
5067
5068                         xevent.type = XEventName.ClientMessage;
5069                         xevent.ClientMessageEvent.display = DisplayHandle;
5070                         xevent.ClientMessageEvent.window = method.Handle;
5071                         xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
5072                         xevent.ClientMessageEvent.format = 32;
5073                         xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
5074
5075                         hwnd.Queue.EnqueueLocked (xevent);
5076
5077                         WakeupMain ();
5078                 }
5079
5080                 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
5081
5082                 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
5083                 {
5084                         Hwnd    h;
5085                         h = Hwnd.ObjectFromHandle(hwnd);
5086
5087                         if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
5088                                 AsyncMethodResult       result;
5089                                 AsyncMethodData         data;
5090
5091                                 result = new AsyncMethodResult ();
5092                                 data = new AsyncMethodData ();
5093
5094                                 data.Handle = hwnd;
5095                                 data.Method = new WndProcDelegate (NativeWindow.WndProc);
5096                                 data.Args = new object[] { hwnd, message, wParam, lParam };
5097                                 data.Result = result;
5098                                 
5099                                 SendAsyncMethod (data);
5100                                 #if DriverDebug || DriverDebugThreads
5101                                 Console.WriteLine ("Sending {0} message across.", message);
5102                                 #endif
5103
5104                                 return IntPtr.Zero;
5105                         }
5106                         return NativeWindow.WndProc(hwnd, message, wParam, lParam);
5107                 }
5108
5109                 internal override int SendInput(IntPtr handle, Queue keys) { 
5110                         if (handle == IntPtr.Zero)
5111                                 return 0;
5112
5113                         int count = keys.Count;
5114                         Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5115
5116                         while (keys.Count > 0) {
5117                         
5118                                 MSG msg = (MSG)keys.Dequeue();
5119
5120                                 XEvent xevent = new XEvent ();
5121
5122                                 xevent.type = (msg.message == Msg.WM_KEYUP ? XEventName.KeyRelease : XEventName.KeyPress);
5123                                 xevent.KeyEvent.display = DisplayHandle;
5124
5125                                 if (hwnd != null) {
5126                                         xevent.KeyEvent.window = hwnd.whole_window;
5127                                 } else {
5128                                         xevent.KeyEvent.window = IntPtr.Zero;
5129                                 }
5130
5131                                 xevent.KeyEvent.keycode = Keyboard.ToKeycode((int)msg.wParam);
5132
5133                                 hwnd.Queue.EnqueueLocked (xevent);
5134                         }
5135                         return count;
5136                 }
5137
5138                 internal override void SetAllowDrop (IntPtr handle, bool value)
5139                 {
5140                         // We allow drop on all windows
5141                 }
5142
5143                 internal override DragDropEffects StartDrag (IntPtr handle, object data,
5144                                 DragDropEffects allowed_effects)
5145                 {
5146                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5147
5148                         if (hwnd == null)
5149                                 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
5150
5151                         return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
5152                 }
5153
5154                 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
5155                         Form form = Control.FromHandle (handle) as Form;
5156                         if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
5157                                         border_style == FormBorderStyle.SizableToolWindow)) {
5158                                 form.window_manager = new ToolWindowManager (form);
5159                         }
5160                         
5161                         RequestNCRecalc(handle);
5162                 }
5163
5164                 internal override void SetCaretPos(IntPtr handle, int x, int y) {
5165                         if (Caret.Hwnd == handle) {
5166                                 Caret.Timer.Stop();
5167                                 HideCaret();
5168
5169                                 Caret.X = x;
5170                                 Caret.Y = y;
5171
5172                                 Keyboard.SetCaretPos (Caret, handle, x, y);
5173
5174                                 if (Caret.Visible == true) {
5175                                         ShowCaret();
5176                                         Caret.Timer.Start();
5177                                 }
5178                         }
5179                 }
5180
5181                 internal override void SetClipRegion(IntPtr handle, Region region) {
5182                         Hwnd    hwnd;
5183
5184                         hwnd = Hwnd.ObjectFromHandle(handle);
5185                         if (hwnd == null) {
5186                                 return;
5187                         }
5188
5189                         hwnd.UserClip = region;
5190                 }
5191
5192                 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
5193                         Hwnd    hwnd;
5194
5195                         if (OverrideCursorHandle == IntPtr.Zero) {
5196                                 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
5197                                         return;
5198                                 }
5199
5200                                 LastCursorHandle = cursor;
5201                                 LastCursorWindow = handle;
5202
5203                                 hwnd = Hwnd.ObjectFromHandle(handle);
5204                                 lock (XlibLock) {
5205                                         if (cursor != IntPtr.Zero) {
5206                                                 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
5207                                         } else {
5208                                                 XUndefineCursor(DisplayHandle, hwnd.whole_window);
5209                                         }
5210                                         XFlush(DisplayHandle);
5211                                 }
5212                                 return;
5213                         }
5214
5215                         hwnd = Hwnd.ObjectFromHandle(handle);
5216                         lock (XlibLock) {
5217                                 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
5218                         }
5219                 }
5220
5221                 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
5222                                            out int root_x, out int root_y, out int child_x, out int child_y,
5223                                            out int mask)
5224                 {
5225                         /* this code was written with the help of
5226                         glance at gdk.  I never would have realized we
5227                         needed a loop in order to traverse down in the
5228                         hierarchy.  I would have assumed you'd get the
5229                         most deeply nested child and have to do
5230                         XQueryTree to move back up the hierarchy..
5231                         stupid me, of course. */
5232                         IntPtr c;
5233
5234                         XGrabServer (display);
5235
5236                         XQueryPointer(display, w, out root, out c,
5237                                       out root_x, out root_y, out child_x, out child_y,
5238                                       out mask);
5239
5240                         if (root != w)
5241                                 c = root;
5242
5243                         IntPtr child_last = IntPtr.Zero;
5244                         while (c != IntPtr.Zero) {
5245                                 child_last = c;
5246                                 XQueryPointer(display, c, out root, out c,
5247                                               out root_x, out root_y, out child_x, out child_y,
5248                                               out mask);
5249                         }
5250                         XUngrabServer (display);
5251                         XFlush (display);
5252
5253                         child = child_last;
5254                 }
5255
5256                 internal override void SetCursorPos(IntPtr handle, int x, int y) {
5257                         if (handle == IntPtr.Zero) {
5258                                 lock (XlibLock) {
5259                                         IntPtr root, child;
5260                                         int root_x, root_y, child_x, child_y, mask;
5261
5262                                         /* we need to do a
5263                                          * QueryPointer before warping
5264                                          * because if the warp is on
5265                                          * the RootWindow, the x/y are
5266                                          * relative to the current
5267                                          * mouse position
5268                                          */
5269                                         QueryPointer (DisplayHandle, RootWindow,
5270                                                       out root,
5271                                                       out child,
5272                                                       out root_x, out root_y,
5273                                                       out child_x, out child_y,
5274                                                       out mask);
5275
5276                                         XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
5277
5278                                         XFlush (DisplayHandle);
5279
5280                                         /* then we need to a
5281                                          * QueryPointer after warping
5282                                          * to manually generate a
5283                                          * motion event for the window
5284                                          * we move into.
5285                                          */
5286                                         QueryPointer (DisplayHandle, RootWindow,
5287                                                       out root,
5288                                                       out child,
5289                                                       out root_x, out root_y,
5290                                                       out child_x, out child_y,
5291                                                       out mask);
5292
5293                                         Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
5294                                         if (child_hwnd == null) {
5295                                                 return;
5296                                         }
5297
5298                                         XEvent xevent = new XEvent ();
5299
5300                                         xevent.type = XEventName.MotionNotify;
5301                                         xevent.MotionEvent.display = DisplayHandle;
5302                                         xevent.MotionEvent.window = child_hwnd.client_window;
5303                                         xevent.MotionEvent.root = RootWindow;
5304                                         xevent.MotionEvent.x = child_x;
5305                                         xevent.MotionEvent.y = child_y;
5306                                         xevent.MotionEvent.x_root = root_x;
5307                                         xevent.MotionEvent.y_root = root_y;
5308                                         xevent.MotionEvent.state = mask;
5309
5310                                         child_hwnd.Queue.EnqueueLocked (xevent);
5311                                 }
5312                         } else {
5313                                 Hwnd    hwnd;
5314
5315                                 hwnd = Hwnd.ObjectFromHandle(handle);
5316                                 lock (XlibLock) {
5317                                         XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
5318                                 }
5319                         }
5320                 }
5321
5322                 internal override void SetFocus(IntPtr handle) {
5323                         Hwnd    hwnd;
5324                         IntPtr  prev_focus_window;
5325
5326                         hwnd = Hwnd.ObjectFromHandle(handle);
5327
5328                         if (hwnd.client_window == FocusWindow) {
5329                                 return;
5330                         }
5331
5332                         // Win32 doesn't do anything if disabled
5333                         if (!hwnd.enabled)
5334                                 return;
5335
5336                         prev_focus_window = FocusWindow;
5337                         FocusWindow = hwnd.client_window;
5338
5339                         if (prev_focus_window != IntPtr.Zero) {
5340                                 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
5341                         }
5342                         SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
5343                         Keyboard.FocusIn (FocusWindow);
5344
5345                         //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
5346                 }
5347
5348                 internal override void SetIcon(IntPtr handle, Icon icon) {
5349                         Hwnd    hwnd;
5350
5351                         hwnd = Hwnd.ObjectFromHandle(handle);
5352                         if (hwnd != null) {
5353                                 SetIcon(hwnd, icon);
5354                         }
5355                 }
5356
5357                 internal override void SetMenu(IntPtr handle, Menu menu) {
5358                         Hwnd    hwnd;
5359
5360                         hwnd = Hwnd.ObjectFromHandle(handle);
5361                         hwnd.menu = menu;
5362
5363                         RequestNCRecalc(handle);
5364                 }
5365
5366                 internal override void SetModal(IntPtr handle, bool Modal) {
5367                         if (Modal) {
5368                                 ModalWindows.Push(handle);
5369                         } else {
5370                                 if (ModalWindows.Contains(handle)) {
5371                                         ModalWindows.Pop();
5372                                 }
5373                                 if (ModalWindows.Count > 0) {
5374                                         Activate((IntPtr)ModalWindows.Peek());
5375                                 }
5376                         }
5377
5378                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
5379                         Control ctrl = Control.FromHandle (handle);
5380                         SetWMStyles (hwnd, ctrl.GetCreateParams ());
5381                 }
5382
5383                 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
5384                         Hwnd    hwnd;
5385
5386                         hwnd = Hwnd.ObjectFromHandle(handle);
5387                         hwnd.parent = Hwnd.ObjectFromHandle(parent);
5388
5389                         lock (XlibLock) {
5390                                 #if DriverDebug || DriverDebugParent
5391                                         Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
5392                                 #endif
5393                                 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
5394                         }
5395
5396                         return IntPtr.Zero;
5397                 }
5398
5399                 internal override void SetTimer (Timer timer) {
5400                         XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
5401
5402                         if (queue == null) {
5403                                 // This isn't really an error, MS doesn't start the timer if
5404                                 // it has no assosciated queue at this stage (it will be
5405                                 // enabled when a window is activated).
5406                                 unattached_timer_list.Add (timer);
5407                                 return;
5408                         }
5409                         queue.timer_list.Add (timer);
5410                         WakeupMain ();
5411                 }
5412
5413                 internal override bool SetTopmost(IntPtr handle, bool enabled) {
5414
5415                         Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
5416
5417                         if (enabled) {
5418                                 lock (XlibLock) {
5419                                         int[] atoms = new int[8];
5420                                         atoms[0] = _NET_WM_STATE_ABOVE.ToInt32();
5421                                         XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5422                                 }
5423                         } else {
5424                                 lock (XlibLock) {
5425                                         XDeleteProperty(DisplayHandle, hwnd.whole_window, _NET_WM_STATE);
5426                                 }
5427                         }
5428                         return true;
5429                 }
5430
5431                 internal override bool SetOwner(IntPtr handle, IntPtr handle_owner) {
5432                         Hwnd hwnd;
5433                         Hwnd hwnd_owner;
5434
5435                         hwnd = Hwnd.ObjectFromHandle(handle);
5436
5437                         if (handle_owner != IntPtr.Zero) {
5438                                 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
5439                                 lock (XlibLock) {
5440                                         int[]   atoms;
5441
5442                                         atoms = new int[8];
5443
5444                                         atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
5445                                         XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
5446
5447                                         if (hwnd_owner != null) {
5448                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
5449                                         } else {
5450                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
5451                                         }
5452                                 }
5453                         } else {
5454                                 lock (XlibLock) {
5455                                         XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
5456                                 }
5457                         }
5458                         return true;
5459                 }
5460
5461                 internal override bool SetVisible (IntPtr handle, bool visible, bool activate)
5462                 {
5463                         Hwnd    hwnd;
5464
5465                         hwnd = Hwnd.ObjectFromHandle(handle);
5466                         hwnd.visible = visible;
5467
5468                         lock (XlibLock) {
5469                                 if (visible) {
5470                                         MapWindow(hwnd, WindowType.Both);
5471
5472                                         if (Control.FromHandle(handle) is Form) {
5473                                                 FormWindowState s;
5474
5475                                                 s = ((Form)Control.FromHandle(handle)).WindowState;
5476
5477                                                 switch(s) {
5478                                                         case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
5479                                                         case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
5480                                                 }
5481                                         }
5482
5483                                         SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5484                                 }
5485                                 else {
5486                                         UnmapWindow(hwnd, WindowType.Both);
5487                                 }
5488                         }
5489                         return true;
5490                 }
5491
5492                 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
5493                         Control ctrl = Control.FromHandle (handle);
5494                         SetWindowMinMax (handle, maximized, min, max, ctrl != null ? ctrl.GetCreateParams () : null);
5495                 }
5496
5497                 internal void SetWindowMinMax (IntPtr handle, Rectangle maximized, Size min, Size max, CreateParams cp)
5498                 {
5499                         Hwnd            hwnd;
5500                         XSizeHints      hints;
5501                         IntPtr          dummy;
5502
5503                         hwnd = Hwnd.ObjectFromHandle(handle);
5504                         if (hwnd == null) {
5505                                 return;
5506                         }
5507
5508                         min.Width = Math.Max (min.Width, SystemInformation.MinimumWindowSize.Width);
5509                         min.Height = Math.Max (min.Height, SystemInformation.MinimumWindowSize.Height);
5510                         
5511                         hints = new XSizeHints();
5512
5513                         XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
5514                         if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
5515                                 if (cp != null)
5516                                         min = TranslateWindowSizeToXWindowSize (cp, min);
5517                                 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
5518                                 hints.min_width = min.Width;
5519                                 hints.min_height = min.Height;
5520                         }
5521
5522                         if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
5523                                 if (cp != null)
5524                                         max = TranslateWindowSizeToXWindowSize (cp, max);
5525                                 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
5526                                 hints.max_width = max.Width;
5527                                 hints.max_height = max.Height;
5528                         }
5529
5530                         if (hints.flags != IntPtr.Zero) {
5531                                 // The Metacity team has decided that they won't care about this when clicking the maximize icon, 
5532                                 // they will maximize the window to fill the screen/parent no matter what.
5533                                 // http://bugzilla.ximian.com/show_bug.cgi?id=80021
5534                                 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
5535                         }
5536
5537                         if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
5538                                 if (cp != null)
5539                                         maximized.Size = TranslateWindowSizeToXWindowSize (cp);
5540                                 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
5541                                 hints.x = maximized.X;
5542                                 hints.y = maximized.Y;
5543                                 hints.width = maximized.Width;
5544                                 hints.height = maximized.Height;
5545
5546                                 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
5547                                 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
5548                         }
5549                 }
5550
5551
5552                 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
5553                         Hwnd            hwnd;
5554
5555                         hwnd = Hwnd.ObjectFromHandle(handle);
5556
5557                         if (hwnd == null) {
5558                                 return;
5559                         }
5560
5561                         // Win32 automatically changes negative width/height to 0.
5562                         if (width < 0)
5563                                 width = 0;
5564                         if (height < 0)
5565                                 height = 0;
5566                                 
5567                         // X requires a sanity check for width & height; otherwise it dies
5568                         if (hwnd.zero_sized && width > 0 && height > 0) {
5569                                 if (hwnd.visible) {
5570                                         MapWindow(hwnd, WindowType.Whole);
5571                                 }
5572                                 hwnd.zero_sized = false;
5573                         }
5574
5575                         if ((width < 1) || (height < 1)) {
5576                                 hwnd.zero_sized = true;
5577                                 UnmapWindow(hwnd, WindowType.Whole);
5578                         }
5579
5580                         // Save a server roundtrip (and prevent a feedback loop)
5581                         if ((hwnd.x == x) && (hwnd.y == y) && 
5582                                 (hwnd.width == width) && (hwnd.height == height)) {
5583                                 return;
5584                         }
5585
5586                         if (!hwnd.zero_sized) {
5587                                 //Hack?
5588                                 hwnd.x = x;
5589                                 hwnd.y = y;
5590                                 hwnd.width = width;
5591                                 hwnd.height = height;
5592                                 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
5593
5594                                 if (hwnd.fixed_size) {
5595                                         SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
5596                                 }
5597
5598                                 lock (XlibLock) {
5599                                         Control ctrl = Control.FromHandle (handle);
5600                                         Size TranslatedSize = TranslateWindowSizeToXWindowSize (ctrl.GetCreateParams (), new Size (width, height));
5601                                         MoveResizeWindow (DisplayHandle, hwnd.whole_window, x, y, TranslatedSize.Width, TranslatedSize.Height);
5602                                         PerformNCCalc(hwnd);
5603                                 }
5604                         }
5605
5606                         // Update our position/size immediately, so
5607                         // that future calls to SetWindowPos aren't
5608                         // kept from calling XMoveResizeWindow (by the
5609                         // "Save a server roundtrip" block above).
5610                         hwnd.x = x;
5611                         hwnd.y = y;
5612                         hwnd.width = width;
5613                         hwnd.height = height;
5614                         hwnd.ClientRect = Rectangle.Empty;
5615                 }
5616
5617                 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
5618                         FormWindowState current_state;
5619                         Hwnd            hwnd;
5620
5621                         hwnd = Hwnd.ObjectFromHandle(handle);
5622
5623                         current_state = GetWindowState(handle);
5624
5625                         if (current_state == state) {
5626                                 return;
5627                         }
5628
5629                         switch(state) {
5630                                 case FormWindowState.Normal: {
5631                                         lock (XlibLock) {
5632                                                 if (current_state == FormWindowState.Minimized) {
5633                                                         MapWindow(hwnd, WindowType.Both);
5634                                                 } else if (current_state == FormWindowState.Maximized) {
5635                                                         SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5636                                                 }
5637                                         }
5638                                         Activate(handle);
5639                                         return;
5640                                 }
5641
5642                                 case FormWindowState.Minimized: {
5643                                         lock (XlibLock) {
5644                                                 if (current_state == FormWindowState.Maximized) {
5645                                                         SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5646                                                 }
5647                                                 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
5648                                         }
5649                                         return;
5650                                 }
5651
5652                                 case FormWindowState.Maximized: {
5653                                         lock (XlibLock) {
5654                                                 if (current_state == FormWindowState.Minimized) {
5655                                                         MapWindow(hwnd, WindowType.Both);
5656                                                 }
5657
5658                                                 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
5659                                         }
5660                                         Activate(handle);
5661                                         return;
5662                                 }
5663                         }
5664                 }
5665
5666                 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
5667                         Hwnd    hwnd;
5668
5669                         hwnd = Hwnd.ObjectFromHandle(handle);
5670                         SetHwndStyles(hwnd, cp);
5671                         SetWMStyles(hwnd, cp);
5672                 }
5673
5674                 internal override double GetWindowTransparency(IntPtr handle)
5675                 {
5676                         return 1.0;
5677                 }
5678
5679                 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
5680                         Hwnd    hwnd;
5681                         IntPtr  opacity;
5682
5683                         hwnd = Hwnd.ObjectFromHandle(handle);
5684
5685                         if (hwnd == null) {
5686                                 return;
5687                         }
5688
5689                         hwnd.opacity = (uint)(0xffffffff * transparency);
5690                         opacity = (IntPtr)((int)hwnd.opacity);
5691
5692                         IntPtr w = hwnd.whole_window;
5693                         if (hwnd.reparented)
5694                                 w = XGetParent (hwnd.whole_window);
5695                         XChangeProperty(DisplayHandle, w, _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
5696                 }
5697
5698                 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
5699                         Hwnd    hwnd = Hwnd.ObjectFromHandle(handle);
5700
5701                         if (!hwnd.mapped) {
5702                                 return false;
5703                         }
5704
5705                         if (top) {
5706                                 lock (XlibLock) {
5707                                         XRaiseWindow(DisplayHandle, hwnd.whole_window);
5708                                 }
5709                                 return true;
5710                         } else if (!bottom) {
5711                                 Hwnd    after_hwnd = null;
5712
5713                                 if (after_handle != IntPtr.Zero) {
5714                                         after_hwnd = Hwnd.ObjectFromHandle(after_handle);
5715                                 }
5716
5717                                 XWindowChanges  values = new XWindowChanges();
5718
5719                                 if (after_hwnd == null) {
5720                                         // Work around metacity 'issues'
5721                                         int[]   atoms;
5722
5723                                         atoms = new int[2];
5724                                         atoms[0] = unixtime();
5725                                         XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
5726
5727                                         XRaiseWindow(DisplayHandle, hwnd.whole_window);
5728                                         SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
5729                                         return true;
5730                                         //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
5731                                 }
5732
5733                                 values.sibling = after_hwnd.whole_window;
5734                                 values.stack_mode = StackMode.Below;
5735
5736                                 lock (XlibLock) {
5737                                         XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
5738                                 }
5739                         } else {
5740                                 // Bottom
5741                                 lock (XlibLock) {
5742                                         XLowerWindow(DisplayHandle, hwnd.whole_window);
5743                                 }
5744                                 return true;
5745                         }
5746                         return false;
5747                 }
5748
5749                 internal override void ShowCursor(bool show) {
5750                         ;       // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
5751                 }
5752
5753                 internal override object StartLoop(Thread thread) {
5754                         XEventQueue q = ThreadQueue(thread);
5755                         return q;
5756                 }
5757
5758                 internal override TransparencySupport SupportsTransparency() {
5759                         // We need to check if the x compositing manager is running
5760                         return TransparencySupport.Set;
5761                 }
5762
5763                 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
5764                         GetSystrayManagerWindow();
5765
5766                         if (SystrayMgrWindow != IntPtr.Zero) {
5767                                 XSizeHints      size_hints;
5768                                 Hwnd            hwnd;
5769
5770                                 hwnd = Hwnd.ObjectFromHandle(handle);
5771                                 #if DriverDebug
5772                                         Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
5773                                 #endif
5774
5775                                 // Oh boy.
5776                                 if (hwnd.client_window != hwnd.whole_window) {
5777                                         Keyboard.DestroyICForWindow (hwnd.client_window);
5778                                         XDestroyWindow(DisplayHandle, hwnd.client_window);
5779                                         hwnd.client_window = hwnd.whole_window;
5780                                 }       
5781
5782                                 /* by virtue of the way the tests are ordered when determining if it's PAINT
5783                                    or NCPAINT, client_window == whole_window will always be PAINT.  So, if we're
5784                                    waiting on an nc_expose, drop it and remove the hwnd from the list (unless
5785                                    there's a pending expose). */
5786                                 if (hwnd.nc_expose_pending) {
5787                                         hwnd.nc_expose_pending = false;
5788                                         if (!hwnd.expose_pending)
5789                                                 hwnd.Queue.Paint.Remove (hwnd);
5790                                 }
5791
5792                                 size_hints = new XSizeHints();
5793
5794                                 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
5795
5796                                 size_hints.min_width = 24;
5797                                 size_hints.min_height = 24;
5798                                 size_hints.max_width = 24;
5799                                 size_hints.max_height = 24;
5800                                 size_hints.base_width = 24;
5801                                 size_hints.base_height = 24;
5802
5803                                 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
5804
5805                                 int[] atoms = new int[2];
5806                                 atoms [0] = 1;                  // Version 1
5807                                 atoms [1] = 1;                  // we want to be mapped
5808
5809                                 // This line cost me 3 days...
5810                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
5811
5812                                 // Need to pick some reasonable defaults
5813                                 tt = new ToolTip();
5814                                 tt.AutomaticDelay = 350;
5815                                 tt.InitialDelay = 250;
5816                                 tt.ReshowDelay = 250;
5817                                 tt.ShowAlways = true;
5818
5819                                 if ((tip != null) && (tip != string.Empty)) {
5820                                         tt.SetToolTip(Control.FromHandle(handle), tip);
5821                                         tt.Active = true;
5822                                 } else {
5823                                         tt.Active = false;
5824                                 }
5825
5826                                 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
5827
5828                                 return true;
5829                         }
5830                         tt = null;
5831                         return false;
5832                 }
5833
5834                 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
5835                         Control control;
5836
5837                         control = Control.FromHandle(handle);
5838                         if (control != null && tt != null) {
5839                                 tt.SetToolTip(control, tip);
5840                                 tt.Active = true;
5841                                 SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5842                                 return true;
5843                         } else {
5844                                 return false;
5845                         }
5846                 }
5847
5848                 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
5849
5850                         SetVisible (handle, false, false);
5851
5852                         // The caller can now re-dock it later...
5853                         if (tt != null) {
5854                                 tt.Dispose();
5855                                 tt = null;
5856                         }
5857                 }
5858
5859 #if NET_2_0
5860                 internal override void SystrayBalloon(IntPtr handle, int timeout, string title, string text, ToolTipIcon icon)
5861                 {
5862                         ThemeEngine.Current.ShowBalloonWindow (handle, timeout, title, text, icon);
5863                         SendMessage(handle, Msg.WM_USER, IntPtr.Zero, (IntPtr) Msg.NIN_BALLOONSHOW);    
5864                 }
5865 #endif
5866
5867                 internal override bool Text(IntPtr handle, string text) {
5868                         Hwnd    hwnd;
5869
5870                         hwnd = Hwnd.ObjectFromHandle(handle);
5871
5872                         lock (XlibLock) {
5873                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_NAME, UNICODETEXT, 8,
5874                                                 PropertyMode.Replace, text, Encoding.UTF8.GetByteCount (text));
5875
5876                                 // XXX this has problems with UTF8.
5877                                 // we need to either use the actual
5878                                 // text if it's latin-1, or convert it
5879                                 // to compound text if it's in a
5880                                 // different charset.
5881                                 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
5882                         }
5883                         return true;
5884                 }
5885
5886                 internal override bool TranslateMessage(ref MSG msg) {
5887                         return Keyboard.TranslateMessage (ref msg);
5888                 }
5889
5890                 internal override void UpdateWindow(IntPtr handle) {
5891                         Hwnd    hwnd;
5892
5893                         hwnd = Hwnd.ObjectFromHandle(handle);
5894
5895                         if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
5896                                 return;
5897                         }
5898
5899                         SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
5900                         hwnd.Queue.Paint.Remove(hwnd);
5901                 }
5902
5903                 internal override void CreateOffscreenDrawable (IntPtr handle,
5904                                                                 int width, int height,
5905                                                                 out object offscreen_drawable)
5906                 {
5907                         IntPtr root_out;
5908                         int x_out, y_out, width_out, height_out, border_width_out, depth_out;
5909
5910                         XGetGeometry (DisplayHandle, handle,
5911                                       out root_out,
5912                                       out x_out, out y_out,
5913                                       out width_out, out height_out,
5914                                       out border_width_out, out depth_out);
5915
5916                         IntPtr pixmap = XCreatePixmap (DisplayHandle, handle, width, height, depth_out);
5917
5918                         offscreen_drawable = pixmap;
5919
5920                 }
5921
5922                 internal override void DestroyOffscreenDrawable (object offscreen_drawable)
5923                 {
5924                         XFreePixmap (DisplayHandle, (IntPtr)offscreen_drawable);
5925                 }
5926
5927                 internal override Graphics GetOffscreenGraphics (object offscreen_drawable)
5928                 {
5929                         return Graphics.FromHwnd ((IntPtr) offscreen_drawable);
5930                 }
5931                 
5932                 internal override void BlitFromOffscreen (IntPtr dest_handle,
5933                                                           Graphics dest_dc,
5934                                                           object offscreen_drawable,
5935                                                           Graphics offscreen_dc,
5936                                                           Rectangle r)
5937                 {
5938                         XGCValues gc_values;
5939                         IntPtr gc;
5940
5941                         gc_values = new XGCValues();
5942
5943                         gc = XCreateGC (DisplayHandle, dest_handle, IntPtr.Zero, ref gc_values);
5944
5945                         XCopyArea (DisplayHandle, (IntPtr)offscreen_drawable, dest_handle,
5946                                    gc, r.X, r.Y, r.Width, r.Height, r.X, r.Y);
5947
5948                         XFreeGC (DisplayHandle, gc);
5949                 }
5950
5951                 #endregion      // Public Static Methods
5952
5953                 #region Events
5954                 internal override event EventHandler Idle;
5955                 #endregion      // Events
5956
5957 #region Xcursor imports
5958                 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadCursor")]
5959                 internal extern static IntPtr XcursorLibraryLoadCursor (IntPtr display, [MarshalAs (UnmanagedType.LPStr)] string name);
5960
5961                 [DllImport ("libXcursor", EntryPoint = "XcursorLibraryLoadImages")]
5962                 internal extern static IntPtr XcursorLibraryLoadImages ([MarshalAs (UnmanagedType.LPStr)] string file, IntPtr theme, int size);
5963                 
5964                 [DllImport ("libXcursor", EntryPoint = "XcursorImagesDestroy")]
5965                 internal extern static void XcursorImagesDestroy (IntPtr images);
5966                 
5967                 [DllImport ("libXcursor", EntryPoint = "XcursorGetDefaultSize")]
5968                 internal extern static int XcursorGetDefaultSize (IntPtr display);
5969
5970                 [DllImport ("libXcursor", EntryPoint = "XcursorImageLoadCursor")]
5971                 internal extern static IntPtr XcursorImageLoadCursor (IntPtr display, IntPtr image);
5972
5973                 [DllImport ("libXcursor", EntryPoint = "XcursorGetTheme")]
5974                 internal extern static IntPtr XcursorGetTheme (IntPtr display);
5975 #endregion
5976                 #region X11 Imports
5977                 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
5978                 internal extern static IntPtr XOpenDisplay(IntPtr display);
5979                 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
5980                 internal extern static int XCloseDisplay(IntPtr display);                                                   
5981                 [DllImport ("libX11", EntryPoint="XSynchronize")]
5982                 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
5983
5984                 [DllImport ("libX11", EntryPoint="XCreateWindow")]
5985                 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);
5986                 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
5987                 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
5988                 [DllImport ("libX11", EntryPoint="XMapWindow")]
5989                 internal extern static int XMapWindow(IntPtr display, IntPtr window);
5990                 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
5991                 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
5992                 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
5993                 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
5994                 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
5995                 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
5996                 [DllImport ("libX11", EntryPoint="XRootWindow")]
5997                 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
5998                 [DllImport ("libX11", EntryPoint="XNextEvent")]
5999                 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
6000                 [DllImport ("libX11")]
6001                 internal extern static int XConnectionNumber (IntPtr diplay);
6002                 [DllImport ("libX11")]
6003                 internal extern static int XPending (IntPtr diplay);
6004                 [DllImport ("libX11", EntryPoint="XSelectInput")]
6005                 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
6006
6007                 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
6008                 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
6009
6010                 [DllImport ("libX11", EntryPoint="XReparentWindow")]
6011                 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
6012                 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
6013                 private extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
6014
6015                 internal static int MoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height)
6016                 {
6017                         int ret = XMoveResizeWindow (display, window, x, y, width, height);
6018                         Keyboard.MoveCurrentCaretPos ();
6019                         return ret;
6020                 }
6021
6022                 [DllImport ("libX11", EntryPoint="XResizeWindow")]
6023                 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
6024
6025                 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
6026                 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
6027
6028                 [DllImport ("libX11", EntryPoint="XFlush")]
6029                 internal extern static int XFlush(IntPtr display);
6030
6031                 [DllImport ("libX11", EntryPoint="XSetWMName")]
6032                 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
6033
6034                 [DllImport ("libX11", EntryPoint="XStoreName")]
6035                 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
6036
6037                 [DllImport ("libX11", EntryPoint="XFetchName")]
6038                 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
6039
6040                 [DllImport ("libX11", EntryPoint="XSendEvent")]
6041                 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
6042
6043                 [DllImport ("libX11", EntryPoint="XQueryTree")]
6044                 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);
6045
6046                 [DllImport ("libX11", EntryPoint="XFree")]
6047                 internal extern static int XFree(IntPtr data);
6048
6049                 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
6050                 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
6051
6052                 [DllImport ("libX11", EntryPoint="XLowerWindow")]
6053                 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
6054
6055                 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
6056                 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
6057
6058                 [DllImport ("libX11", EntryPoint="XInternAtom")]
6059                 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
6060
6061                 [DllImport ("libX11", EntryPoint="XInternAtoms")]
6062                 internal extern static int XInternAtoms(IntPtr display, string[] atom_names, int atom_count, bool only_if_exists, IntPtr[] atoms);
6063
6064                 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
6065                 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
6066
6067                 [DllImport ("libX11", EntryPoint="XGrabPointer")]
6068                 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);
6069
6070                 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
6071                 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
6072
6073                 [DllImport ("libX11", EntryPoint="XQueryPointer")]
6074                 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);
6075
6076                 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
6077                 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);
6078
6079                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6080                 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);
6081
6082                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6083                 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);
6084
6085                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6086                 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);
6087
6088                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
6089                 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);
6090
6091                 [DllImport ("libX11", EntryPoint="XWarpPointer")]
6092                 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);
6093
6094                 [DllImport ("libX11", EntryPoint="XClearWindow")]
6095                 internal extern static int XClearWindow(IntPtr display, IntPtr window);
6096
6097                 [DllImport ("libX11", EntryPoint="XClearArea")]
6098                 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
6099
6100                 // Colormaps
6101                 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
6102                 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
6103
6104                 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
6105                 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
6106
6107                 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
6108                 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
6109
6110                 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
6111                 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
6112
6113                 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
6114                 internal extern static int XDefaultScreen(IntPtr display);
6115
6116                 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
6117                 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
6118
6119                 [DllImport ("libX11", EntryPoint="XLookupColor")]
6120                 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
6121
6122                 [DllImport ("libX11", EntryPoint="XAllocColor")]
6123                 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
6124
6125                 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
6126                 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
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 MotifWmHints data, 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, ref uint value, 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, ref IntPtr value, 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, uint[] 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, int[] data, int nelements);
6142
6143                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6144                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
6145
6146                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
6147                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
6148
6149                 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
6150                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
6151
6152                 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
6153                 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
6154
6155                 // Drawing
6156                 [DllImport ("libX11", EntryPoint="XCreateGC")]
6157                 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
6158
6159                 [DllImport ("libX11", EntryPoint="XFreeGC")]
6160                 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
6161
6162                 [DllImport ("libX11", EntryPoint="XSetFunction")]
6163                 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
6164
6165                 [DllImport ("libX11", EntryPoint="XSetLineAttributes")]
6166                 internal extern static int XSetLineAttributes(IntPtr display, IntPtr gc, int line_width, GCLineStyle line_style, GCCapStyle cap_style, GCJoinStyle join_style);
6167
6168                 [DllImport ("libX11", EntryPoint="XDrawLine")]
6169                 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
6170
6171                 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
6172                 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
6173
6174                 [DllImport ("libX11", EntryPoint="XFillRectangle")]
6175                 internal extern static int XFillRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
6176
6177                 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
6178                 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
6179
6180                 [DllImport ("libX11", EntryPoint="XCopyArea")]
6181                 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);
6182
6183                 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
6184                 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);
6185
6186                 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
6187                 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
6188
6189                 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
6190                 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
6191
6192                 [DllImport ("libX11", EntryPoint="XDefineCursor")]
6193                 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
6194
6195                 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
6196                 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
6197
6198                 [DllImport ("libX11", EntryPoint="XFreeCursor")]
6199                 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
6200
6201                 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
6202                 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
6203
6204                 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
6205                 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);
6206
6207                 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
6208                 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
6209
6210                 [DllImport ("libX11", EntryPoint="XCreatePixmap")]
6211                 internal extern static IntPtr XCreatePixmap(IntPtr display, IntPtr d, int width, int height, int depth);
6212
6213                 [DllImport ("libX11", EntryPoint="XFreePixmap")]
6214                 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
6215
6216                 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
6217                 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
6218
6219                 [DllImport ("libX11", EntryPoint="XQueryExtension")]
6220                 internal extern static int XQueryExtension(IntPtr display, string extension_name, ref int major, ref int first_event, ref int first_error);
6221
6222                 [DllImport ("libX11", EntryPoint="XWhitePixel")]
6223                 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
6224
6225                 [DllImport ("libX11", EntryPoint="XBlackPixel")]
6226                 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
6227
6228                 [DllImport ("libX11", EntryPoint="XGrabServer")]
6229                 internal extern static void XGrabServer(IntPtr display);
6230
6231                 [DllImport ("libX11", EntryPoint="XUngrabServer")]
6232                 internal extern static void XUngrabServer(IntPtr display);
6233
6234                 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
6235                 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
6236
6237                 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
6238                 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6239
6240                 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
6241                 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
6242
6243                 [DllImport ("libX11", EntryPoint="XSetWMHints")]
6244                 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
6245
6246                 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
6247                 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
6248
6249                 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
6250                 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
6251
6252                 [DllImport ("libX11", EntryPoint="XGetErrorText")]
6253                 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
6254
6255                 [DllImport ("libX11", EntryPoint="XInitThreads")]
6256                 internal extern static int XInitThreads();
6257
6258                 [DllImport ("libX11", EntryPoint="XConvertSelection")]
6259                 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
6260
6261                 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
6262                 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
6263
6264                 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
6265                 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
6266
6267                 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
6268                 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
6269
6270                 [DllImport ("libX11", EntryPoint="XSetForeground")]
6271                 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
6272
6273                 [DllImport ("libX11", EntryPoint="XSetBackground")]
6274                 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
6275
6276                 [DllImport ("libX11", EntryPoint="XBell")]
6277                 internal extern static int XBell(IntPtr display, int percent);
6278
6279                 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
6280                 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
6281
6282                 [DllImport ("libX11", EntryPoint="XFilterEvent")]
6283                 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
6284
6285                 [DllImport ("libX11")]
6286                 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
6287
6288                 [DllImport ("libX11")]
6289                 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);
6290                 #endregion
6291         }
6292 }