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