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