Fix MouseRelease to only release MouseState after create wParam for message
[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_SKIP_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_SKIP_TASKBAR = XInternAtom(DisplayHandle, "_NET_WM_STATE_SKIP_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                                 atom_count = 0;
868
869                                 // needed! map toolwindows to _NET_WM_WINDOW_TYPE_UTILITY to make newer metacity versions happy
870                                 // and get those windows in front of their parents
871                                 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
872                                         atoms [0] = _NET_WM_WINDOW_TYPE_UTILITY.ToInt32 ();
873                                         XChangeProperty (DisplayHandle, hwnd.whole_window,  _NET_WM_WINDOW_TYPE,
874                                                          (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
875                                 }
876                                 
877                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropertyMode.Replace, ref mwmHints, 5);
878                                 if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
879                                         atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
880                                         XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
881
882                                         XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
883                                 } else if (!ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_APPWINDOW)) {
884                                         /* this line keeps the window from showing up in gnome's taskbar */
885                                         atoms[atom_count++] = _NET_WM_STATE_SKIP_TASKBAR.ToInt32();
886                                 }
887                                 if ((client_rect.Width < 1) || (client_rect.Height < 1)) {
888                                         XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
889                                 } else {
890                                         XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
891                                 }
892
893                                 if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
894                                         atoms[atom_count++] = _NET_WM_STATE_SKIP_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                         if (Grab.Hwnd == hwnd.Handle) {
1644                                 Grab.Hwnd = IntPtr.Zero;
1645                                 Grab.Confined = false;
1646                         }
1647
1648                         DestroyCaret (hwnd.Handle);
1649                 }
1650
1651                 private void PerformNCCalc(Hwnd hwnd) {
1652                         XplatUIWin32.NCCALCSIZE_PARAMS  ncp;
1653                         IntPtr                          ptr;
1654                         Rectangle                       rect;
1655
1656                         rect = hwnd.DefaultClientRect;
1657
1658                         ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
1659                         ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
1660
1661                         ncp.rgrc1.left = rect.Left;
1662                         ncp.rgrc1.top = rect.Top;
1663                         ncp.rgrc1.right = rect.Right;
1664                         ncp.rgrc1.bottom = rect.Bottom;
1665
1666                         Marshal.StructureToPtr(ncp, ptr, true);
1667                         NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
1668                         ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
1669                         Marshal.FreeHGlobal(ptr);
1670
1671                         // FIXME - debug this with Menus
1672
1673                         rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
1674                         hwnd.ClientRect = rect;
1675
1676                         if (hwnd.visible) {
1677                                 if ((rect.Width < 1) || (rect.Height < 1)) {
1678                                         XMoveResizeWindow(DisplayHandle, hwnd.client_window, -5, -5, 1, 1);
1679                                 } else {
1680                                         XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
1681                                 }
1682                         }
1683                 }
1684                 #endregion      // Private Methods
1685
1686                 #region Callbacks
1687                 private void MouseHover(object sender, EventArgs e) {
1688                         XEvent  xevent;
1689                         Hwnd    hwnd;
1690
1691                         HoverState.Timer.Enabled = false;
1692
1693                         if (HoverState.Window != IntPtr.Zero) {
1694                                 hwnd = Hwnd.GetObjectFromWindow(HoverState.Window);
1695                                 if (hwnd != null) {
1696                                         xevent = new XEvent ();
1697
1698                                         xevent.type = XEventName.ClientMessage;
1699                                         xevent.ClientMessageEvent.display = DisplayHandle;
1700                                         xevent.ClientMessageEvent.window = HoverState.Window;
1701                                         xevent.ClientMessageEvent.message_type = HoverState.Atom;
1702                                         xevent.ClientMessageEvent.format = 32;
1703                                         xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
1704
1705                                         hwnd.Queue.EnqueueLocked (xevent);
1706
1707                                         WakeupMain ();
1708                                 }
1709                         }
1710                 }
1711
1712                 private void CaretCallback(object sender, EventArgs e) {
1713                         if (Caret.Paused) {
1714                                 return;
1715                         }
1716                         Caret.On = !Caret.On;
1717
1718                         XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
1719                 }
1720                 #endregion      // Callbacks
1721
1722                 #region Public Properties
1723
1724                 internal override int Caption {
1725                         get {
1726                                 return 19;
1727                         }
1728                 }
1729
1730                 internal override  Size CursorSize {
1731                         get {
1732                                 int     x;
1733                                 int     y;
1734
1735                                 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
1736                                         return new Size(x, y);
1737                                 } else {
1738                                         return new Size(16, 16);
1739                                 }
1740                         }
1741                 } 
1742
1743                 internal override  bool DragFullWindows {
1744                         get {
1745                                 return true;
1746                         }
1747                 } 
1748
1749                 internal override  Size DragSize {
1750                         get {
1751                                 return new Size(4, 4);
1752                         }
1753                 } 
1754
1755                 internal override  Size FrameBorderSize { 
1756                         get {
1757                                 throw new NotImplementedException(); 
1758                         }
1759                 }
1760
1761                 internal override  Size IconSize {
1762                         get {
1763                                 IntPtr          list;
1764                                 XIconSize       size;
1765                                 int             count;
1766
1767                                 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1768                                         long            current;
1769                                         int             largest;
1770
1771                                         current = (long)list;
1772                                         largest = 0;
1773
1774                                         size = new XIconSize();
1775
1776                                         for (int i = 0; i < count; i++) {
1777                                                 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1778                                                 current += Marshal.SizeOf(size);
1779
1780                                                 // Look for our preferred size
1781                                                 if (size.min_width == 32) {
1782                                                         XFree(list);
1783                                                         return new Size(32, 32);
1784                                                 }
1785
1786                                                 if (size.max_width == 32) {
1787                                                         XFree(list);
1788                                                         return new Size(32, 32);
1789                                                 }
1790
1791                                                 if (size.min_width < 32 && size.max_width > 32) {
1792                                                         int     x;
1793
1794                                                         // check if we can fit one
1795                                                         x = size.min_width;
1796                                                         while (x < size.max_width) {
1797                                                                 x += size.width_inc;
1798                                                                 if (x == 32) {
1799                                                                         XFree(list);
1800                                                                         return new Size(32, 32);
1801                                                                 }
1802                                                         }
1803                                                 }
1804
1805                                                 if (largest < size.max_width) {
1806                                                         largest = size.max_width;
1807                                                 }
1808                                         }
1809
1810                                         // We didn't find a match or we wouldn't be here
1811                                         return new Size(largest, largest);
1812
1813                                 } else {
1814                                         return new Size(32, 32);
1815                                 }
1816                         }
1817                 } 
1818
1819                 internal override int KeyboardSpeed {
1820                         get{
1821                                 //
1822                                 // A lot harder: need to do:
1823                                 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)       = 1
1824                                 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)        = 0x080517a8
1825                                 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58)                   = 0
1826                                 //
1827                                 // And from that we can tell the repetition rate
1828                                 //
1829                                 // Notice, the values must map to:
1830                                 //   [0, 31] which maps to 2.5 to 30 repetitions per second.
1831                                 //
1832                                 return 0;
1833                         }
1834                 }
1835
1836                 internal override int KeyboardDelay {
1837                         get {
1838                                 //
1839                                 // Return values must range from 0 to 4, 0 meaning 250ms,
1840                                 // and 4 meaning 1000 ms.
1841                                 //
1842                                 return 1; // ie, 500 ms
1843                         }
1844                 } 
1845
1846                 internal override  Size MaxWindowTrackSize {
1847                         get {
1848                                 return new Size (WorkingArea.Width, WorkingArea.Height);
1849                         }
1850                 } 
1851
1852                 internal override  Size MinimizedWindowSize {
1853                         get {
1854                                 return new Size(1, 1);
1855                         }
1856                 } 
1857
1858                 internal override  Size MinimizedWindowSpacingSize {
1859                         get {
1860                                 return new Size(1, 1);
1861                         }
1862                 } 
1863
1864                 internal override  Size MinimumWindowSize {
1865                         get {
1866                                 return new Size(1, 1);
1867                         }
1868                 } 
1869
1870                 internal override  Size MinWindowTrackSize {
1871                         get {
1872                                 return new Size(1, 1);
1873                         }
1874                 }
1875
1876                 internal override Keys ModifierKeys {
1877                         get {
1878                                 return Keyboard.ModifierKeys;
1879                         }
1880                 }
1881
1882                 internal override  Size SmallIconSize {
1883                         get {
1884                                 IntPtr          list;
1885                                 XIconSize       size;
1886                                 int             count;
1887
1888                                 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1889                                         long            current;
1890                                         int             smallest;
1891
1892                                         current = (long)list;
1893                                         smallest = 0;
1894
1895                                         size = new XIconSize();
1896
1897                                         for (int i = 0; i < count; i++) {
1898                                                 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1899                                                 current += Marshal.SizeOf(size);
1900
1901                                                 // Look for our preferred size
1902                                                 if (size.min_width == 16) {
1903                                                         XFree(list);
1904                                                         return new Size(16, 16);
1905                                                 }
1906
1907                                                 if (size.max_width == 16) {
1908                                                         XFree(list);
1909                                                         return new Size(16, 16);
1910                                                 }
1911
1912                                                 if (size.min_width < 16 && size.max_width > 16) {
1913                                                         int     x;
1914
1915                                                         // check if we can fit one
1916                                                         x = size.min_width;
1917                                                         while (x < size.max_width) {
1918                                                                 x += size.width_inc;
1919                                                                 if (x == 16) {
1920                                                                         XFree(list);
1921                                                                         return new Size(16, 16);
1922                                                                 }
1923                                                         }
1924                                                 }
1925
1926                                                 if (smallest == 0 || smallest > size.min_width) {
1927                                                         smallest = size.min_width;
1928                                                 }
1929                                         }
1930
1931                                         // We didn't find a match or we wouldn't be here
1932                                         return new Size(smallest, smallest);
1933
1934                                 } else {
1935                                         return new Size(16, 16);
1936                                 }
1937                         }
1938                 } 
1939
1940                 internal override  int MouseButtonCount {
1941                         get {
1942                                 return 3;
1943                         }
1944                 } 
1945
1946                 internal override  bool MouseButtonsSwapped {
1947                         get {
1948                                 return false;   // FIXME - how to detect?
1949                         }
1950                 } 
1951
1952                 internal override Size MouseHoverSize {
1953                         get {
1954                                 return new Size (1, 1);
1955                         }
1956                 }
1957
1958                 internal override int MouseHoverTime {
1959                         get {
1960                                 return HoverState.Interval;
1961                         }
1962                 }
1963
1964
1965
1966                 internal override  bool MouseWheelPresent {
1967                         get {
1968                                 return true;    // FIXME - how to detect?
1969                         }
1970                 } 
1971
1972                 internal override  Rectangle VirtualScreen {
1973                         get {
1974                                 return WorkingArea;
1975                         }
1976                 } 
1977
1978                 internal override  Rectangle WorkingArea {
1979                         get {
1980                                 IntPtr                  actual_atom;
1981                                 int                     actual_format;
1982                                 IntPtr                  nitems;
1983                                 IntPtr                  bytes_after;
1984                                 IntPtr                  prop = IntPtr.Zero;
1985                                 int                     width;
1986                                 int                     height;
1987                                 int                     current_desktop;
1988                                 int                     x;
1989                                 int                     y;
1990
1991                                 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);
1992                                 if ((long)nitems < 1) {
1993                                         goto failsafe;
1994                                 }
1995
1996                                 current_desktop = Marshal.ReadIntPtr(prop, 0).ToInt32();
1997                                 XFree(prop);
1998
1999                                 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);
2000                                 if ((long)nitems < 4 * current_desktop) {
2001                                         goto failsafe;
2002                                 }
2003
2004                                 x = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop).ToInt32();
2005                                 y = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size).ToInt32();
2006                                 width = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 2).ToInt32();
2007                                 height = Marshal.ReadIntPtr(prop, IntPtr.Size * 4 * current_desktop + IntPtr.Size * 3).ToInt32();
2008                                 XFree(prop);
2009
2010                                 return new Rectangle(x, y, width, height);
2011
2012                         failsafe:
2013                                 XWindowAttributes       attributes=new XWindowAttributes();
2014
2015                                 lock (XlibLock) {
2016                                         XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
2017                                 }
2018
2019                                 return new Rectangle(0, 0, attributes.width, attributes.height);
2020                         }
2021                 }
2022
2023                 internal override bool ThemesEnabled {
2024                         get {
2025                                 return XplatUIX11.themes_enabled;
2026                         }
2027                 }
2028  
2029
2030                 #endregion      // Public properties
2031
2032                 #region Public Static Methods
2033                 internal override IntPtr InitializeDriver() {
2034                         lock (this) {
2035                                 if (DisplayHandle==IntPtr.Zero) {
2036                                         SetDisplay(XOpenDisplay(IntPtr.Zero));
2037                                 }
2038                         }
2039                         return IntPtr.Zero;
2040                 }
2041
2042                 internal override void ShutdownDriver(IntPtr token) {
2043                         lock (this) {
2044                                 if (DisplayHandle!=IntPtr.Zero) {
2045                                         XCloseDisplay(DisplayHandle);
2046                                         DisplayHandle=IntPtr.Zero;
2047                                 }
2048                         }
2049                 }
2050
2051                 internal override void EnableThemes() {
2052                         themes_enabled = true;
2053                 }
2054
2055
2056                 internal override void Activate(IntPtr handle) {
2057                         Hwnd hwnd;
2058
2059                         hwnd = Hwnd.ObjectFromHandle(handle);
2060
2061                         if (hwnd != null) {
2062                                 lock (XlibLock) {
2063                                         if (true /* the window manager supports NET_ACTIVE_WINDOW */) {
2064                                                 SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
2065                                         }
2066 //                                      else {
2067 //                                              XRaiseWindow(DisplayHandle, handle);
2068 //                                      }
2069                                 }
2070                         }
2071                 }
2072
2073                 internal override void AudibleAlert() {
2074                         XBell(DisplayHandle, 0);
2075                         return;
2076                 }
2077
2078
2079                 internal override void CaretVisible(IntPtr handle, bool visible) {
2080                         if (Caret.Hwnd == handle) {
2081                                 if (visible) {
2082                                         if (!Caret.Visible) {
2083                                                 Caret.Visible = true;
2084                                                 ShowCaret();
2085                                                 Caret.Timer.Start();
2086                                         }
2087                                 } else {
2088                                         Caret.Visible = false;
2089                                         Caret.Timer.Stop();
2090                                         HideCaret();
2091                                 }
2092                         }
2093                 }
2094
2095                 internal override bool CalculateWindowRect(ref Rectangle ClientRect, int Style, int ExStyle, Menu menu, out Rectangle WindowRect) {
2096                         FormBorderStyle border_style;
2097                         TitleStyle      title_style;
2098                         int caption_height;
2099                         int tool_caption_height;
2100
2101                         DeriveStyles(Style, ExStyle, out border_style, out title_style,
2102                                 out caption_height, out tool_caption_height);
2103
2104                         WindowRect = Hwnd.GetWindowRectangle(border_style, menu, title_style,
2105                                         caption_height, tool_caption_height,
2106                                         ClientRect);
2107                         return true;
2108                 }
2109
2110                 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
2111                         int     dest_x_return;
2112                         int     dest_y_return;
2113                         IntPtr  child;
2114                         Hwnd    hwnd;
2115
2116                         hwnd = Hwnd.ObjectFromHandle(handle);
2117
2118                         lock (XlibLock) {
2119                                 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2120                         }
2121
2122                         x = dest_x_return;
2123                         y = dest_y_return;
2124                 }
2125
2126                 internal override int[] ClipboardAvailableFormats(IntPtr handle) {
2127                         DataFormats.Format      f;
2128                         int[]                   result;
2129
2130                         f = DataFormats.Format.List;
2131
2132                         if (XGetSelectionOwner(DisplayHandle, CLIPBOARD) == IntPtr.Zero) {
2133                                 return null;
2134                         }
2135
2136                         Clipboard.Formats = new ArrayList();
2137
2138                         while (f != null) {
2139                                 XConvertSelection(DisplayHandle, CLIPBOARD, (IntPtr)f.Id, (IntPtr)f.Id, FosterParent, IntPtr.Zero);
2140
2141                                 Clipboard.Enumerating = true;
2142                                 while (Clipboard.Enumerating) {
2143                                         UpdateMessageQueue(null);
2144                                 }
2145                                 f = f.Next;
2146                         }
2147
2148                         result = new int[Clipboard.Formats.Count];
2149
2150                         for (int i = 0; i < Clipboard.Formats.Count; i++) {
2151                                 result[i] = ((IntPtr)Clipboard.Formats[i]).ToInt32 ();
2152                         }
2153
2154                         Clipboard.Formats = null;
2155                         return result;
2156                 }
2157
2158                 internal override void ClipboardClose(IntPtr handle) {
2159                         if (handle != ClipMagic) {
2160                                 throw new ArgumentException("handle is not a valid clipboard handle");
2161                         }
2162                         return;
2163                 }
2164
2165                 internal override int ClipboardGetID(IntPtr handle, string format) {
2166                         if (handle != ClipMagic) {
2167                                 throw new ArgumentException("handle is not a valid clipboard handle");
2168                         }
2169
2170                         if (format == "Text" ) return (int)Atom.XA_STRING;
2171                         else if (format == "Bitmap" ) return (int)Atom.XA_BITMAP;
2172                         //else if (format == "MetaFilePict" ) return 3;
2173                         //else if (format == "SymbolicLink" ) return 4;
2174                         //else if (format == "DataInterchangeFormat" ) return 5;
2175                         //else if (format == "Tiff" ) return 6;
2176                         else if (format == "OEMText" ) return XInternAtom(DisplayHandle, "COMPOUND_TEXT", false).ToInt32();
2177                         else if (format == "DeviceIndependentBitmap" ) return (int)Atom.XA_PIXMAP;
2178                         else if (format == "Palette" ) return (int)Atom.XA_COLORMAP;    // Useless
2179                         //else if (format == "PenData" ) return 10;
2180                         //else if (format == "RiffAudio" ) return 11;
2181                         //else if (format == "WaveAudio" ) return 12;
2182                         else if (format == "UnicodeText" ) return XInternAtom(DisplayHandle, "UTF8_STRING", false).ToInt32();
2183                         //else if (format == "EnhancedMetafile" ) return 14;
2184                         //else if (format == "FileDrop" ) return 15;
2185                         //else if (format == "Locale" ) return 16;
2186
2187                         return XInternAtom(DisplayHandle, format, false).ToInt32();
2188                 }
2189
2190                 internal override IntPtr ClipboardOpen(bool primary_selection) {
2191                         if (!primary_selection)
2192                                 ClipMagic = CLIPBOARD;
2193                         else
2194                                 ClipMagic = PRIMARY;
2195                         return ClipMagic;
2196                 }
2197
2198                 internal override object ClipboardRetrieve(IntPtr handle, int type, XplatUI.ClipboardToObject converter) {
2199                         XConvertSelection(DisplayHandle, handle, (IntPtr)type, (IntPtr)type, FosterParent, IntPtr.Zero);
2200
2201                         Clipboard.Retrieving = true;
2202                         while (Clipboard.Retrieving) {
2203                                 UpdateMessageQueue(null);
2204                         }
2205
2206                         return Clipboard.Item;
2207                 }
2208
2209                 internal override void ClipboardStore(IntPtr handle, object obj, int type, XplatUI.ObjectToClipboard converter) {
2210                         Clipboard.Item = obj;
2211                         Clipboard.Type = type;
2212                         Clipboard.Converter = converter;
2213
2214                         if (obj != null) {
2215                                 XSetSelectionOwner(DisplayHandle, CLIPBOARD, FosterParent, IntPtr.Zero);
2216                         } else {
2217                                 // Clearing the selection
2218                                 XSetSelectionOwner(DisplayHandle, CLIPBOARD, IntPtr.Zero, IntPtr.Zero);
2219                         }
2220                 }
2221
2222                 internal override void CreateCaret(IntPtr handle, int width, int height) {
2223                         XGCValues       gc_values;
2224                         Hwnd            hwnd;
2225
2226                         hwnd = Hwnd.ObjectFromHandle(handle);
2227
2228                         if (Caret.Hwnd != IntPtr.Zero) {
2229                                 DestroyCaret(Caret.Hwnd);
2230                         }
2231
2232                         Caret.Hwnd = handle;
2233                         Caret.Window = hwnd.client_window;
2234                         Caret.Width = width;
2235                         Caret.Height = height;
2236                         Caret.Visible = false;
2237                         Caret.On = false;
2238
2239                         gc_values = new XGCValues();
2240                         gc_values.line_width = width;
2241
2242                         Caret.gc = XCreateGC(DisplayHandle, Caret.Window, new IntPtr ((int)GCFunction.GCLineWidth), ref gc_values);
2243                         if (Caret.gc == IntPtr.Zero) {
2244                                 Caret.Hwnd = IntPtr.Zero;
2245                                 return;
2246                         }
2247
2248                         XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
2249                 }
2250
2251                 internal override IntPtr CreateWindow(CreateParams cp) {
2252                         XSetWindowAttributes    Attributes;
2253                         Hwnd                    hwnd;
2254                         int                     X;
2255                         int                     Y;
2256                         int                     Width;
2257                         int                     Height;
2258                         IntPtr                  ParentHandle;
2259                         IntPtr                  WholeWindow;
2260                         IntPtr                  ClientWindow;
2261                         Rectangle               ClientRect;
2262                         SetWindowValuemask      ValueMask;
2263                         int[]                   atoms;
2264
2265                         hwnd = new Hwnd();
2266
2267                         Attributes = new XSetWindowAttributes();
2268                         X = cp.X;
2269                         Y = cp.Y;
2270                         Width = cp.Width;
2271                         Height = cp.Height;
2272
2273                         if (Width<1) Width=1;
2274                         if (Height<1) Height=1;
2275
2276                         if (cp.Parent != IntPtr.Zero) {
2277                                 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
2278                         } else {
2279                                 if (StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2280                                         // We need to use our foster parent window until this poor child gets it's parent assigned
2281                                         ParentHandle=FosterParent;
2282                                 } else if (StyleSet (cp.Style, WindowStyles.WS_POPUP)) {
2283                                         ParentHandle=RootWindow;
2284                                 } else {
2285                                         // Default position on screen, if window manager doesn't place us somewhere else
2286                                         if (X<0) X = 50;
2287                                         if (Y<0) Y = 50;
2288                                         ParentHandle=RootWindow;
2289                                 }
2290                         }
2291
2292                         ValueMask = SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity;
2293
2294                         Attributes.bit_gravity = Gravity.NorthWestGravity;
2295                         Attributes.win_gravity = Gravity.NorthWestGravity;
2296
2297                         // Save what's under the toolwindow
2298                         if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOOLWINDOW)) {
2299                                 Attributes.save_under = true;
2300                                 ValueMask |= SetWindowValuemask.SaveUnder;
2301                         }
2302
2303
2304                         // If we're a popup without caption we override the WM
2305                         if (StyleSet (cp.Style, WindowStyles.WS_POPUP) && !StyleSet (cp.Style, WindowStyles.WS_CAPTION)) {
2306                                 Attributes.override_redirect = true;
2307                                 ValueMask |= SetWindowValuemask.OverrideRedirect;
2308                         }
2309
2310                         hwnd.x = X;
2311                         hwnd.y = Y;
2312                         hwnd.width = Width;
2313                         hwnd.height = Height;
2314                         hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
2315
2316                         if (StyleSet (cp.Style, WindowStyles.WS_DISABLED)) {
2317                                 hwnd.enabled = false;
2318                         }
2319
2320                         ClientRect = hwnd.ClientRect;
2321                         ClientWindow = IntPtr.Zero;
2322
2323                         lock (XlibLock) {
2324                                 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, new UIntPtr ((uint)ValueMask), ref Attributes);
2325                                 if (WholeWindow != IntPtr.Zero) {
2326                                         ValueMask &= ~(SetWindowValuemask.OverrideRedirect | SetWindowValuemask.SaveUnder);
2327
2328                                         if (CustomVisual != IntPtr.Zero && CustomColormap != IntPtr.Zero) {
2329                                                 ValueMask = SetWindowValuemask.ColorMap;
2330                                                 Attributes.colormap = CustomColormap;
2331                                         }
2332                                         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);
2333                                 }
2334                         }
2335
2336                         if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
2337                                 throw new Exception("Could not create X11 windows");
2338                         }
2339
2340                         hwnd.Queue = ThreadQueue(Thread.CurrentThread);
2341                         hwnd.WholeWindow = WholeWindow;
2342                         hwnd.ClientWindow = ClientWindow;
2343
2344                         #if DriverDebug || DriverDebugCreate
2345                                 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);
2346                         #endif
2347
2348                         if (!StyleSet (cp.Style, WindowStyles.WS_CHILD)) {
2349                                 if ((X != unchecked((int)0x80000000)) && (Y != unchecked((int)0x80000000))) {
2350                                         XSizeHints      hints;
2351
2352                                         hints = new XSizeHints();
2353                                         hints.x = X;
2354                                         hints.y = Y;
2355                                         hints.flags = (IntPtr)(XSizeHintsFlags.USPosition | XSizeHintsFlags.PPosition);
2356                                         XSetWMNormalHints(DisplayHandle, WholeWindow, ref hints);
2357                                 }
2358                         }
2359
2360                         lock (XlibLock) {
2361                                 XSelectInput(DisplayHandle, hwnd.whole_window, new IntPtr ((int)(SelectInputMask | EventMask.StructureNotifyMask)));
2362                                 if (hwnd.whole_window != hwnd.client_window)
2363                                         XSelectInput(DisplayHandle, hwnd.client_window, new IntPtr ((int)SelectInputMask));
2364
2365                                 if (StyleSet (cp.Style, WindowStyles.WS_VISIBLE)) {
2366                                         MapWindow(hwnd, WindowType.Both);
2367                                         hwnd.visible = true;
2368                                 }
2369                         }
2370
2371                         if (ExStyleSet (cp.ExStyle, WindowExStyles.WS_EX_TOPMOST)) {
2372                                 atoms = new int[2];
2373                                 atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
2374                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
2375
2376                                 XSetTransientForHint (DisplayHandle, hwnd.whole_window, RootWindow);
2377                         }
2378
2379                         SetWMStyles(hwnd, cp);
2380                         
2381                         // set the group leader
2382                         XWMHints wm_hints = new XWMHints ();
2383                         
2384                         wm_hints.flags = (IntPtr)(XWMHintsFlags.InputHint | XWMHintsFlags.StateHint | XWMHintsFlags.WindowGroupHint);
2385                         wm_hints.input = !StyleSet (cp.Style, WindowStyles.WS_DISABLED);
2386                         wm_hints.initial_state = StyleSet (cp.Style, WindowStyles.WS_MINIMIZE) ? XInitialState.IconicState : XInitialState.NormalState;
2387                         
2388                         if (ParentHandle != RootWindow) {
2389                                 wm_hints.window_group = hwnd.whole_window;
2390                         } else {
2391                                 wm_hints.window_group = ParentHandle;
2392                         }
2393                         
2394                         lock (XlibLock) {
2395                                 XSetWMHints(DisplayHandle, hwnd.whole_window, ref wm_hints );
2396                         }
2397
2398                         if (StyleSet (cp.Style, WindowStyles.WS_MINIMIZE)) {
2399                                 SetWindowState(hwnd.Handle, FormWindowState.Minimized);
2400                         } else if (StyleSet (cp.Style, WindowStyles.WS_MAXIMIZE)) {
2401                                 SetWindowState(hwnd.Handle, FormWindowState.Maximized);
2402                         }
2403
2404                         // for now make all windows dnd enabled
2405                         Dnd.SetAllowDrop (hwnd, true);
2406
2407                         // Set caption/window title
2408                         Text(hwnd.Handle, cp.Caption);
2409
2410                         return hwnd.Handle;
2411                 }
2412
2413                 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
2414                         CreateParams create_params = new CreateParams();
2415
2416                         create_params.Caption = "";
2417                         create_params.X = X;
2418                         create_params.Y = Y;
2419                         create_params.Width = Width;
2420                         create_params.Height = Height;
2421
2422                         create_params.ClassName=XplatUI.DefaultClassName;
2423                         create_params.ClassStyle = 0;
2424                         create_params.ExStyle=0;
2425                         create_params.Parent=IntPtr.Zero;
2426                         create_params.Param=0;
2427
2428                         return CreateWindow(create_params);
2429                 }
2430
2431                 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
2432                         IntPtr  cursor;
2433                         Bitmap  cursor_bitmap;
2434                         Bitmap  cursor_mask;
2435                         Byte[]  cursor_bits;
2436                         Byte[]  mask_bits;
2437                         Color   c_pixel;
2438                         Color   m_pixel;
2439                         int     width;
2440                         int     height;
2441                         IntPtr  cursor_pixmap;
2442                         IntPtr  mask_pixmap;
2443                         XColor  fg;
2444                         XColor  bg;
2445                         bool    and;
2446                         bool    xor;
2447
2448                         if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
2449                                 return IntPtr.Zero;
2450                         }
2451
2452                         // Win32 only allows creation cursors of a certain size
2453                         if ((bitmap.Width != width) || (bitmap.Width != height)) {
2454                                 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
2455                                 cursor_mask = new Bitmap(mask, new Size(width, height));
2456                         } else {
2457                                 cursor_bitmap = bitmap;
2458                                 cursor_mask = mask;
2459                         }
2460
2461                         width = cursor_bitmap.Width;
2462                         height = cursor_bitmap.Height;
2463
2464                         cursor_bits = new Byte[(width / 8) * height];
2465                         mask_bits = new Byte[(width / 8) * height];
2466
2467                         for (int y = 0; y < height; y++) {
2468                                 for (int x = 0; x < width; x++) {
2469                                         c_pixel = cursor_bitmap.GetPixel(x, y);
2470                                         m_pixel = cursor_mask.GetPixel(x, y);
2471
2472                                         and = c_pixel == cursor_pixel;
2473                                         xor = m_pixel == mask_pixel;
2474
2475                                         if (!and && !xor) {
2476                                                 // Black
2477                                                 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));       // The bit already is 0
2478                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2479                                         } else if (and && !xor) {
2480                                                 // White
2481                                                 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2482                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
2483 #if notneeded
2484                                         } else if (and && !xor) {
2485                                                 // Screen
2486                                         } else if (and && xor) {
2487                                                 // Inverse Screen
2488
2489                                                 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
2490                                                 // we want both to be 0 so nothing to be done
2491                                                 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
2492                                                 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
2493 #endif
2494                                         }
2495                                 }
2496                         }
2497
2498                         cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2499                         mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
2500                         fg = new XColor();
2501                         bg = new XColor();
2502
2503                         fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
2504                         fg.red = (ushort)65535;
2505                         fg.green = (ushort)65535;
2506                         fg.blue = (ushort)65535;
2507
2508                         bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
2509
2510                         cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
2511
2512                         XFreePixmap(DisplayHandle, cursor_pixmap);
2513                         XFreePixmap(DisplayHandle, mask_pixmap);
2514
2515                         return cursor;
2516                 }
2517
2518                 internal override IntPtr DefineStdCursor(StdCursor id) {
2519                         CursorFontShape shape;
2520                         IntPtr          cursor;
2521
2522                         // FIXME - define missing shapes
2523
2524                         switch (id) {
2525                                 case StdCursor.AppStarting: {
2526                                         shape = CursorFontShape.XC_watch;
2527                                         break;
2528                                 }
2529
2530                                 case StdCursor.Arrow: {
2531                                         shape = CursorFontShape.XC_top_left_arrow;
2532                                         break;
2533                                 }
2534
2535                                 case StdCursor.Cross: {
2536                                         shape = CursorFontShape.XC_crosshair;
2537                                         break;
2538                                 }
2539
2540                                 case StdCursor.Default: {
2541                                         shape = CursorFontShape.XC_top_left_arrow;
2542                                         break;
2543                                 }
2544
2545                                 case StdCursor.Hand: {
2546                                         shape = CursorFontShape.XC_hand1;
2547                                         break;
2548                                 }
2549
2550                                 case StdCursor.Help: {
2551                                         shape = CursorFontShape.XC_question_arrow;
2552                                         break;
2553                                 }
2554
2555                                 case StdCursor.HSplit: {
2556                                         shape = CursorFontShape.XC_sb_v_double_arrow; 
2557                                         break;
2558                                 }
2559
2560                                 case StdCursor.IBeam: {
2561                                         shape = CursorFontShape.XC_xterm; 
2562                                         break;
2563                                 }
2564
2565                                 case StdCursor.No: {
2566                                         shape = CursorFontShape.XC_circle; 
2567                                         break;
2568                                 }
2569
2570                                 case StdCursor.NoMove2D: {
2571                                         shape = CursorFontShape.XC_fleur; 
2572                                         break;
2573                                 }
2574
2575                                 case StdCursor.NoMoveHoriz: {
2576                                         shape = CursorFontShape.XC_fleur; 
2577                                         break;
2578                                 }
2579
2580                                 case StdCursor.NoMoveVert: {
2581                                         shape = CursorFontShape.XC_fleur; 
2582                                         break;
2583                                 }
2584
2585                                 case StdCursor.PanEast: {
2586                                         shape = CursorFontShape.XC_fleur; 
2587                                         break;
2588                                 }
2589
2590                                 case StdCursor.PanNE: {
2591                                         shape = CursorFontShape.XC_fleur; 
2592                                         break;
2593                                 }
2594
2595                                 case StdCursor.PanNorth: {
2596                                         shape = CursorFontShape.XC_fleur; 
2597                                         break;
2598                                 }
2599
2600                                 case StdCursor.PanNW: {
2601                                         shape = CursorFontShape.XC_fleur; 
2602                                         break;
2603                                 }
2604
2605                                 case StdCursor.PanSE: {
2606                                         shape = CursorFontShape.XC_fleur; 
2607                                         break;
2608                                 }
2609
2610                                 case StdCursor.PanSouth: {
2611                                         shape = CursorFontShape.XC_fleur; 
2612                                         break;
2613                                 }
2614
2615                                 case StdCursor.PanSW: {
2616                                         shape = CursorFontShape.XC_fleur; 
2617                                         break;
2618                                 }
2619
2620                                 case StdCursor.PanWest: {
2621                                         shape = CursorFontShape.XC_sizing; 
2622                                         break;
2623                                 }
2624
2625                                 case StdCursor.SizeAll: {
2626                                         shape = CursorFontShape.XC_fleur; 
2627                                         break;
2628                                 }
2629
2630                                 case StdCursor.SizeNESW: {
2631                                         shape = CursorFontShape.XC_top_right_corner; 
2632                                         break;
2633                                 }
2634
2635                                 case StdCursor.SizeNS: {
2636                                         shape = CursorFontShape.XC_sb_v_double_arrow;
2637                                         break;
2638                                 }
2639
2640                                 case StdCursor.SizeNWSE: {
2641                                         shape = CursorFontShape.XC_top_left_corner; 
2642                                         break;
2643                                 }
2644
2645                                 case StdCursor.SizeWE: {
2646                                         shape = CursorFontShape.XC_sb_h_double_arrow; 
2647                                         break;
2648                                 }
2649
2650                                 case StdCursor.UpArrow: {
2651                                         shape = CursorFontShape.XC_center_ptr; 
2652                                         break;
2653                                 }
2654
2655                                 case StdCursor.VSplit: {
2656                                         shape = CursorFontShape.XC_sb_h_double_arrow;
2657                                         break;
2658                                 }
2659
2660                                 case StdCursor.WaitCursor: {
2661                                         shape = CursorFontShape.XC_watch; 
2662                                         break;
2663                                 }
2664
2665                                 default: {
2666                                         return IntPtr.Zero;
2667                                 }
2668                         }
2669
2670                         lock (XlibLock) {
2671                                 cursor = XCreateFontCursor(DisplayHandle, shape);
2672                         }
2673                         return cursor;
2674                 }
2675
2676                 internal override IntPtr DefWndProc(ref Message msg) {
2677                         switch ((Msg)msg.Msg) {
2678                                 case Msg.WM_PAINT: {
2679                                         Hwnd hwnd;
2680
2681                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2682                                         if (hwnd != null) {
2683                                                 hwnd.expose_pending = false;
2684                                         }
2685
2686                                         return IntPtr.Zero;
2687                                 }
2688
2689                                 case Msg.WM_NCPAINT: {
2690                                         Hwnd hwnd;
2691
2692                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2693                                         if (hwnd != null) {
2694                                                 hwnd.nc_expose_pending = false;
2695                                         }
2696
2697                                         return IntPtr.Zero;
2698                                 }
2699
2700                                 case Msg.WM_CONTEXTMENU: {
2701                                         Hwnd hwnd;
2702
2703                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2704
2705                                         if ((hwnd != null) && (hwnd.parent != null)) {
2706                                                 SendMessage(hwnd.parent.client_window, Msg.WM_CONTEXTMENU, msg.WParam, msg.LParam);
2707                                         }
2708                                         return IntPtr.Zero;
2709                                 }
2710
2711                                 case Msg.WM_MOUSEWHEEL: {
2712                                         Hwnd hwnd;
2713
2714                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2715
2716                                         if ((hwnd != null) && (hwnd.parent != null)) {
2717                                                 SendMessage(hwnd.parent.client_window, Msg.WM_MOUSEWHEEL, msg.WParam, msg.LParam);
2718                                                 if (msg.Result == IntPtr.Zero) {
2719                                                         return IntPtr.Zero;
2720                                                 }
2721                                         }
2722                                         return IntPtr.Zero;
2723                                 }
2724
2725                                 case Msg.WM_SETCURSOR: {
2726                                         Hwnd    hwnd;
2727
2728                                         hwnd = Hwnd.GetObjectFromWindow(msg.HWnd);
2729                                         if (hwnd == null)
2730                                                 break; // not sure how this happens, but it does
2731
2732                                         // Pass to parent window first
2733                                         while ((hwnd.parent != null) && (msg.Result == IntPtr.Zero)) {
2734                                                 hwnd = hwnd.parent;
2735                                                 msg.Result = NativeWindow.WndProc(hwnd.Handle, Msg.WM_SETCURSOR, msg.HWnd, msg.LParam);
2736                                         }
2737
2738                                         if (msg.Result == IntPtr.Zero) {
2739                                                 IntPtr handle;
2740
2741                                                 switch((HitTest)(msg.LParam.ToInt32() & 0xffff)) {
2742                                                         case HitTest.HTBOTTOM:          handle = Cursors.SizeNS.handle; break;
2743                                                         case HitTest.HTBORDER:          handle = Cursors.SizeNS.handle; break;
2744                                                         case HitTest.HTBOTTOMLEFT:      handle = Cursors.SizeNESW.handle; break;
2745                                                         case HitTest.HTBOTTOMRIGHT:     handle = Cursors.SizeNWSE.handle; break;
2746                                                         case HitTest.HTERROR:           if ((msg.LParam.ToInt32() >> 16) == (int)Msg.WM_LBUTTONDOWN) {
2747                                                                                                 AudibleAlert();
2748                                                                                         }
2749                                                                                         handle = Cursors.Default.handle;
2750                                                                                         break;
2751
2752                                                         case HitTest.HTHELP:            handle = Cursors.Help.handle; break;
2753                                                         case HitTest.HTLEFT:            handle = Cursors.SizeWE.handle; break;
2754                                                         case HitTest.HTRIGHT:           handle = Cursors.SizeWE.handle; break;
2755                                                         case HitTest.HTTOP:             handle = Cursors.SizeNS.handle; break;
2756                                                         case HitTest.HTTOPLEFT:         handle = Cursors.SizeNWSE.handle; break;
2757                                                         case HitTest.HTTOPRIGHT:        handle = Cursors.SizeNESW.handle; break;
2758
2759                                                         #if SameAsDefault
2760                                                         case HitTest.HTGROWBOX:
2761                                                         case HitTest.HTSIZE:
2762                                                         case HitTest.HTZOOM:
2763                                                         case HitTest.HTVSCROLL:
2764                                                         case HitTest.HTSYSMENU:
2765                                                         case HitTest.HTREDUCE:
2766                                                         case HitTest.HTNOWHERE:
2767                                                         case HitTest.HTMAXBUTTON:
2768                                                         case HitTest.HTMINBUTTON:
2769                                                         case HitTest.HTMENU:
2770                                                         case HitTest.HSCROLL:
2771                                                         case HitTest.HTBOTTOM:
2772                                                         case HitTest.HTCAPTION:
2773                                                         case HitTest.HTCLIENT:
2774                                                         case HitTest.HTCLOSE:
2775                                                         #endif
2776                                                         default: handle = Cursors.Default.handle; break;
2777                                                 }
2778                                                 SetCursor(msg.HWnd, handle);
2779                                         }
2780                                         return (IntPtr)1;
2781                                 }
2782                         }
2783                         return IntPtr.Zero;
2784                 }
2785
2786                 internal override void DestroyCaret(IntPtr handle) {
2787                         if (Caret.Hwnd == handle) {
2788                                 if (Caret.Visible == true) {
2789                                         Caret.Timer.Stop();
2790                                 }
2791                                 if (Caret.gc != IntPtr.Zero) {
2792                                         XFreeGC(DisplayHandle, Caret.gc);
2793                                         Caret.gc = IntPtr.Zero;
2794                                 }
2795                                 Caret.Hwnd = IntPtr.Zero;
2796                                 Caret.Visible = false;
2797                                 Caret.On = false;
2798                         }
2799                 }
2800
2801                 internal override void DestroyCursor(IntPtr cursor) {
2802                         lock (XlibLock) {
2803                                 XFreeCursor(DisplayHandle, cursor);
2804                         }
2805                 }
2806
2807                 internal override void DestroyWindow(IntPtr handle) {
2808                         Hwnd    hwnd;
2809
2810                         hwnd = Hwnd.ObjectFromHandle(handle);
2811
2812                         if (hwnd == null) {
2813                                 #if DriverDebug || DriverDebugDestroy
2814                                         Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
2815                                 #endif
2816                                 return;
2817                         }
2818
2819                         #if DriverDebug || DriverDebugDestroy
2820                                 Console.WriteLine("Destroying window {0}", XplatUI.Window(hwnd.client_window));
2821                         #endif
2822
2823                         CleanupCachedWindows (hwnd);
2824
2825                         ArrayList windows = new ArrayList ();
2826
2827                         AccumulateDestroyedHandles (Control.ControlNativeWindow.ControlFromHandle(hwnd.Handle), windows);
2828
2829                         lock (XlibLock) {
2830                                 if (hwnd.whole_window != IntPtr.Zero) {
2831                                         #if DriverDebug || DriverDebugDestroy
2832                                         Console.WriteLine ("XDestroyWindow (whole_window = {0:X})", hwnd.whole_window.ToInt32());
2833                                         #endif
2834                                         XDestroyWindow(DisplayHandle, hwnd.whole_window);
2835                                 }
2836                                 else if (hwnd.client_window != IntPtr.Zero) {
2837                                         #if DriverDebug || DriverDebugDestroy
2838                                         Console.WriteLine ("XDestroyWindow (client_window = {0:X})", hwnd.client_window.ToInt32());
2839                                         #endif
2840                                         XDestroyWindow(DisplayHandle, hwnd.client_window);
2841                                 }
2842
2843                         }
2844
2845                         foreach (Hwnd h in windows) {
2846                                 SendMessage (h.Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
2847                         }
2848                 }
2849
2850                 internal override IntPtr DispatchMessage(ref MSG msg) {
2851                         return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
2852                 }
2853
2854                 internal override void DrawReversibleRectangle(IntPtr handle, Rectangle rect, int line_width) {
2855                         Hwnd            hwnd;
2856                         XGCValues       gc_values;
2857                         IntPtr          gc;
2858
2859                         hwnd = Hwnd.ObjectFromHandle(handle);
2860
2861                         gc_values = new XGCValues();
2862
2863                         gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2864                         gc_values.line_width = line_width;
2865                         gc_values.foreground = XBlackPixel(DisplayHandle, ScreenNo);
2866
2867                         // This logic will give us true rubber bands: (libsx, SANE_XOR)
2868                         //mask = foreground ^ background; 
2869                         //XSetForeground(DisplayHandle, gc, 0xffffffff);
2870                         //XSetBackground(DisplayHandle, gc, background);
2871                         //XSetFunction(DisplayHandle,   gc, GXxor);
2872                         //XSetPlaneMask(DisplayHandle,  gc, mask);
2873
2874
2875                         gc = XCreateGC(DisplayHandle, hwnd.client_window, new IntPtr ((int) (GCFunction.GCSubwindowMode | GCFunction.GCLineWidth | GCFunction.GCForeground)), ref gc_values);
2876                         uint foreground;
2877                         uint background;
2878
2879                         Control control;
2880                         control = Control.FromHandle(handle);
2881
2882                         XColor xcolor = new XColor();
2883
2884                         xcolor.red = (ushort)(control.ForeColor.R * 257);
2885                         xcolor.green = (ushort)(control.ForeColor.G * 257);
2886                         xcolor.blue = (ushort)(control.ForeColor.B * 257);
2887                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2888                         foreground = (uint)xcolor.pixel.ToInt32();
2889
2890                         xcolor.red = (ushort)(control.BackColor.R * 257);
2891                         xcolor.green = (ushort)(control.BackColor.G * 257);
2892                         xcolor.blue = (ushort)(control.BackColor.B * 257);
2893                         XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2894                         background = (uint)xcolor.pixel.ToInt32();
2895
2896                         uint mask = foreground ^ background; 
2897
2898                         XSetForeground(DisplayHandle, gc, (UIntPtr)0xffffffff);
2899                         XSetBackground(DisplayHandle, gc, (UIntPtr)background);
2900                         XSetFunction(DisplayHandle,   gc, GXFunction.GXxor);
2901                         XSetPlaneMask(DisplayHandle,  gc, (IntPtr)mask);
2902
2903                         if ((rect.Width > 0) && (rect.Height > 0)) {
2904                                 XDrawRectangle(DisplayHandle, hwnd.client_window, gc, rect.Left, rect.Top, rect.Width, rect.Height);
2905                         } else {
2906                                 if (rect.Width > 0) {
2907                                         XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.Right, rect.Y);
2908                                 } else {
2909                                         XDrawLine(DisplayHandle, hwnd.client_window, gc, rect.X, rect.Y, rect.X, rect.Bottom);
2910                                 }
2911                         }
2912                         XFreeGC(DisplayHandle, gc);
2913                 }
2914
2915                 internal override void DoEvents() {
2916                         MSG     msg = new MSG ();
2917                         XEventQueue queue;
2918
2919                         if (OverrideCursorHandle != IntPtr.Zero) {
2920                                 OverrideCursorHandle = IntPtr.Zero;
2921                         }
2922
2923                         queue = ThreadQueue(Thread.CurrentThread);
2924
2925                         queue.DispatchIdle = false;
2926
2927                         while (PeekMessage(queue, ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
2928                                 TranslateMessage (ref msg);
2929                                 DispatchMessage (ref msg);
2930                         }
2931
2932                         queue.DispatchIdle = true;
2933                 }
2934
2935                 internal override void EnableWindow(IntPtr handle, bool Enable) {
2936                         Hwnd    hwnd;
2937
2938                         hwnd = Hwnd.ObjectFromHandle(handle);
2939                         if (hwnd != null) {
2940                                 hwnd.Enabled = Enable;
2941                         }
2942                 }
2943
2944                 internal override void EndLoop(Thread thread) {
2945                         // This is where we one day will shut down the loop for the thread
2946                 }
2947
2948
2949                 internal override IntPtr GetActive() {
2950                         IntPtr  actual_atom;
2951                         int     actual_format;
2952                         IntPtr  nitems;
2953                         IntPtr  bytes_after;
2954                         IntPtr  prop = IntPtr.Zero;
2955                         IntPtr  active = IntPtr.Zero;
2956
2957                         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);
2958                         if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
2959                                 active = (IntPtr)Marshal.ReadInt32(prop);
2960                                 XFree(prop);
2961                         }
2962
2963                         if (active != IntPtr.Zero) {
2964                                 Hwnd    hwnd;
2965
2966                                 hwnd = Hwnd.GetObjectFromWindow(active);
2967                                 if (hwnd != null) {
2968                                         active = hwnd.Handle;
2969                                 } else {
2970                                         active = IntPtr.Zero;
2971                                 }
2972                         }
2973                         return active;
2974                 }
2975
2976                 internal override Region GetClipRegion(IntPtr handle) {
2977                         Hwnd    hwnd;
2978
2979                         hwnd = Hwnd.ObjectFromHandle(handle);
2980                         if (hwnd != null) {
2981                                 return hwnd.UserClip;
2982                         }
2983
2984                         return null;
2985                 }
2986
2987                 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
2988                         width = 20;
2989                         height = 20;
2990                         hotspot_x = 0;
2991                         hotspot_y = 0;
2992                 }
2993
2994                 internal override void GetDisplaySize(out Size size) {
2995                         XWindowAttributes       attributes=new XWindowAttributes();
2996
2997                         lock (XlibLock) {
2998                                 // FIXME - use _NET_WM messages instead?
2999                                 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
3000                         }
3001
3002                         size = new Size(attributes.width, attributes.height);
3003                 }
3004
3005                 internal override SizeF GetAutoScaleSize(Font font) {
3006                         Graphics        g;
3007                         float           width;
3008                         string          magic_string = "The quick brown fox jumped over the lazy dog.";
3009                         double          magic_number = 44.549996948242189;
3010
3011                         g = Graphics.FromHwnd(FosterParent);
3012
3013                         width = (float) (g.MeasureString (magic_string, font).Width / magic_number);
3014                         return new SizeF(width, font.Height);
3015                 }
3016
3017                 internal override IntPtr GetParent(IntPtr handle) {
3018                         Hwnd    hwnd;
3019
3020                         hwnd = Hwnd.ObjectFromHandle(handle);
3021                         if (hwnd != null && hwnd.parent != null) {
3022                                 return hwnd.parent.Handle;
3023                         }
3024                         return IntPtr.Zero;
3025                 }
3026
3027                 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
3028                         IntPtr  use_handle;
3029                         IntPtr  root;
3030                         IntPtr  child;
3031                         int     root_x;
3032                         int     root_y;
3033                         int     win_x;
3034                         int     win_y;
3035                         int     keys_buttons;
3036
3037                         if (handle != IntPtr.Zero) {
3038                                 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
3039                         } else {
3040                                 use_handle = RootWindow;
3041                         }
3042
3043                         lock (XlibLock) {
3044                                 QueryPointer (DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
3045                         }
3046
3047                         if (handle != IntPtr.Zero) {
3048                                 x = win_x;
3049                                 y = win_y;
3050                         } else {
3051                                 x = root_x;
3052                                 y = root_y;
3053                         }
3054                 }
3055
3056                 internal override IntPtr GetFocus() {
3057                         return FocusWindow;
3058                 }
3059
3060
3061                 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
3062                         return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
3063                 }
3064
3065                 internal override Point GetMenuOrigin(IntPtr handle) {
3066                         Hwnd    hwnd;
3067
3068                         hwnd = Hwnd.ObjectFromHandle(handle);
3069
3070                         if (hwnd != null) {
3071                                 return hwnd.MenuOrigin;
3072                         }
3073                         return Point.Empty;
3074                 }
3075
3076                 [MonoTODO("Implement filtering")]
3077                 internal override bool GetMessage(Object queue_id, ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
3078                         XEvent  xevent;
3079                         bool    client;
3080                         Hwnd    hwnd;
3081
3082                         ProcessNextMessage:
3083
3084                         if (((XEventQueue)queue_id).Count > 0) {
3085                                 xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3086                         } else {
3087                                 UpdateMessageQueue ((XEventQueue)queue_id);
3088
3089                                 if (((XEventQueue)queue_id).Count > 0) {
3090                                         xevent = (XEvent) ((XEventQueue)queue_id).Dequeue ();
3091                                 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3092                                         xevent = ((XEventQueue)queue_id).Paint.Dequeue();
3093                                 } else {
3094                                         if (!ThreadQueue(Thread.CurrentThread).PostQuitState) {
3095                                                 msg.hwnd= IntPtr.Zero;
3096                                                 msg.message = Msg.WM_ENTERIDLE;
3097                                                 return true;
3098                                         }
3099
3100                                         // We reset ourselves so GetMessage can be called again
3101                                         ThreadQueue(Thread.CurrentThread).PostQuitState = false;
3102
3103                                         return false;
3104                                 }
3105                         }
3106
3107                         hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
3108
3109                         // Handle messages for windows that are already or are about to be destroyed.
3110
3111                         // we need a special block for this because unless we remove the hwnd from the paint
3112                         // queue it will always stay there (since we don't handle the expose), and we'll
3113                         // effectively loop infinitely trying to repaint a non-existant window.
3114                         if (hwnd != null && hwnd.zombie && xevent.type == XEventName.Expose) {
3115                                 hwnd.expose_pending = hwnd.nc_expose_pending = false;
3116                                 hwnd.Queue.Paint.Remove (hwnd);
3117                                 goto ProcessNextMessage;
3118                         }
3119
3120                         // We need to make sure we only allow DestroyNotify events through for zombie
3121                         // hwnds, since much of the event handling code makes requests using the hwnd's
3122                         // client_window, and that'll result in BadWindow errors if there's some lag
3123                         // between the XDestroyWindow call and the DestroyNotify event.
3124                         if (hwnd == null || hwnd.zombie) {
3125                                 #if DriverDebug || DriverDebugDestroy
3126                                         Console.WriteLine("GetMessage(): Got message {0} for non-existent or already destroyed window {1:X}", xevent.type, xevent.AnyEvent.window.ToInt32());
3127                                 #endif
3128                                 goto ProcessNextMessage;
3129                         }
3130
3131                         if (hwnd.client_window == xevent.AnyEvent.window) {
3132                                 client = true;
3133                                 //Console.WriteLine("Client message {1}, sending to window {0:X}", msg.hwnd.ToInt32(), xevent.type);
3134                         } else {
3135                                 client = false;
3136                                 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
3137                         }
3138
3139                         msg.hwnd = hwnd.Handle;
3140
3141                         //
3142                         // If you add a new event to this switch make sure to add it in
3143                         // UpdateMessage also unless it is not coming through the X event system.
3144                         //
3145                         switch(xevent.type) {
3146                                 case XEventName.KeyPress: {
3147                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3148                                         break;
3149                                 }
3150
3151                                 case XEventName.KeyRelease: {
3152                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
3153                                         break;
3154                                 }
3155
3156                                 case XEventName.ButtonPress: {
3157                                         switch(xevent.ButtonEvent.button) {
3158                                                 case 1: {
3159                                                         MouseState |= MouseButtons.Left;
3160                                                         if (client) {
3161                                                                 msg.message = Msg.WM_LBUTTONDOWN;
3162                                                         } else {
3163                                                                 msg.message = Msg.WM_NCLBUTTONDOWN;
3164                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3165                                                         }
3166                                                         // TODO: For WM_NCLBUTTONDOWN wParam specifies a hit-test value not the virtual keys down
3167                                                         msg.wParam=GetMousewParam(0);
3168                                                         break;
3169                                                 }
3170
3171                                                 case 2: {
3172                                                         MouseState |= MouseButtons.Middle;
3173                                                         if (client) {
3174                                                                 msg.message = Msg.WM_MBUTTONDOWN;
3175                                                         } else {
3176                                                                 msg.message = Msg.WM_NCMBUTTONDOWN;
3177                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3178                                                         }
3179                                                         msg.wParam=GetMousewParam(0);
3180                                                         break;
3181                                                 }
3182
3183                                                 case 3: {
3184                                                         MouseState |= MouseButtons.Right;
3185                                                         if (client) {
3186                                                                 msg.message = Msg.WM_RBUTTONDOWN;
3187                                                         } else {
3188                                                                 msg.message = Msg.WM_NCRBUTTONDOWN;
3189                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3190                                                         }
3191                                                         msg.wParam=GetMousewParam(0);
3192                                                         break;
3193                                                 }
3194
3195                                                 case 4: {
3196                                                         msg.hwnd = FocusWindow;
3197                                                         msg.message=Msg.WM_MOUSEWHEEL;
3198                                                         msg.wParam=GetMousewParam(120);
3199                                                         break;
3200                                                 }
3201
3202                                                 case 5: {
3203                                                         msg.hwnd = FocusWindow;
3204                                                         msg.message=Msg.WM_MOUSEWHEEL;
3205                                                         msg.wParam=GetMousewParam(-120);
3206                                                         break;
3207                                                 }
3208
3209                                         }
3210
3211                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3212                                         MousePosition.X = xevent.ButtonEvent.x;
3213                                         MousePosition.Y = xevent.ButtonEvent.y;
3214
3215                                         if (!hwnd.Enabled) {
3216                                                 IntPtr dummy;
3217
3218                                                 msg.hwnd = hwnd.EnabledHwnd;
3219                                                 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);
3220                                                 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3221                                         }
3222
3223                                         if (Grab.Hwnd != IntPtr.Zero) {
3224                                                 msg.hwnd = Grab.Hwnd;
3225                                         }
3226
3227                                         if (ClickPending.Pending && ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message))) {
3228                                                 // Looks like a genuine double click, clicked twice on the same spot with the same keys
3229                                                 switch(xevent.ButtonEvent.button) {
3230                                                         case 1: {
3231                                                                 msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
3232                                                                 break;
3233                                                         }
3234
3235                                                         case 2: {
3236                                                                 msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
3237                                                                 break;
3238                                                         }
3239
3240                                                         case 3: {
3241                                                                 msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
3242                                                                 break;
3243                                                         }
3244                                                 }
3245                                                 ClickPending.Pending = false;
3246                                         } else {
3247                                                 ClickPending.Pending = true;
3248                                                 ClickPending.Hwnd = msg.hwnd;
3249                                                 ClickPending.Message = msg.message;
3250                                                 ClickPending.wParam = msg.wParam;
3251                                                 ClickPending.lParam = msg.lParam;
3252                                                 ClickPending.Time = (long)xevent.ButtonEvent.time;
3253                                         }
3254
3255                                         break;
3256                                 }
3257
3258                                 case XEventName.ButtonRelease: {
3259                                         if (Dnd.InDrag()) {
3260                                                 Dnd.HandleButtonRelease (ref xevent);
3261                                                 break;
3262                                         }
3263
3264                                         switch(xevent.ButtonEvent.button) {
3265                                                 case 1: {
3266                                                         if (client) {
3267                                                                 msg.message = Msg.WM_LBUTTONUP;
3268                                                         } else {
3269                                                                 msg.message = Msg.WM_NCLBUTTONUP;
3270                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3271                                                         }
3272                                                         msg.wParam=GetMousewParam(0);
3273                                                         MouseState &= ~MouseButtons.Left;
3274                                                         break;
3275                                                 }
3276
3277                                                 case 2: {
3278                                                         if (client) {
3279                                                                 msg.message = Msg.WM_MBUTTONUP;
3280                                                         } else {
3281                                                                 msg.message = Msg.WM_NCMBUTTONUP;
3282                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3283                                                         }
3284                                                         msg.wParam=GetMousewParam(0);
3285                                                         MouseState &= ~MouseButtons.Middle;
3286                                                         break;
3287                                                 }
3288
3289                                                 case 3: {
3290                                                         if (client) {
3291                                                                 msg.message = Msg.WM_RBUTTONUP;
3292                                                         } else {
3293                                                                 msg.message = Msg.WM_NCRBUTTONUP;
3294                                                                 MenuToScreen (xevent.AnyEvent.window, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);
3295                                                         }
3296                                                         msg.wParam=GetMousewParam(0);
3297                                                         MouseState &= ~MouseButtons.Right;
3298                                                         break;
3299                                                 }
3300
3301                                                 case 4: {
3302                                                         goto ProcessNextMessage;
3303                                                 }
3304
3305                                                 case 5: {
3306                                                         goto ProcessNextMessage;
3307                                                 }
3308                                         }
3309
3310                                         if (!hwnd.Enabled) {
3311                                                 IntPtr dummy;
3312
3313                                                 msg.hwnd = hwnd.EnabledHwnd;
3314                                                 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);
3315                                                 msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3316                                         }
3317
3318                                         if (Grab.Hwnd != IntPtr.Zero) {
3319                                                 msg.hwnd = Grab.Hwnd;
3320                                         }
3321
3322                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
3323                                         MousePosition.X = xevent.ButtonEvent.x;
3324                                         MousePosition.Y = xevent.ButtonEvent.y;
3325                                         break;
3326                                 }
3327
3328                                 case XEventName.MotionNotify: {
3329                                         if (client) {
3330                                                 #if DriverDebugExtra
3331                                                         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);
3332                                                 #endif
3333
3334                                                 if (Dnd.HandleMotionNotify (ref xevent))
3335                                                         goto ProcessNextMessage;
3336                                                 if (Grab.Hwnd != IntPtr.Zero) {
3337                                                         msg.hwnd = Grab.Hwnd;
3338                                                 } else {
3339                                                         NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
3340                                                 }
3341
3342                                                 msg.message = Msg.WM_MOUSEMOVE;
3343                                                 msg.wParam = GetMousewParam(0);
3344                                                 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x & 0xFFFF);
3345
3346                                                 if (!hwnd.Enabled) {
3347                                                         IntPtr dummy;
3348
3349                                                         msg.hwnd = hwnd.EnabledHwnd;
3350                                                         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);
3351                                                         msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3352                                                 }
3353
3354                                                 MousePosition.X = xevent.MotionEvent.x;
3355                                                 MousePosition.Y = xevent.MotionEvent.y;
3356
3357                                                 if ((HoverState.Timer.Enabled) &&
3358                                                     (((MousePosition.X + HoverState.Size.Width) < HoverState.X) ||
3359                                                     ((MousePosition.X - HoverState.Size.Width) > HoverState.X) ||
3360                                                     ((MousePosition.Y + HoverState.Size.Height) < HoverState.Y) ||
3361                                                     ((MousePosition.Y - HoverState.Size.Height) > HoverState.Y))) {
3362                                                         HoverState.Timer.Stop();
3363                                                         HoverState.Timer.Start();
3364                                                         HoverState.X = MousePosition.X;
3365                                                         HoverState.Y = MousePosition.Y;
3366                                                 }
3367
3368                                                 break;
3369                                         } else {
3370                                                 HitTest ht;
3371                                                 IntPtr dummy;
3372                                                 int screen_x;
3373                                                 int screen_y;
3374
3375                                                 #if DriverDebugExtra
3376                                                         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);
3377                                                 #endif
3378                                                 msg.message = Msg.WM_NCMOUSEMOVE;
3379
3380                                                 if (!hwnd.Enabled) {
3381                                                         msg.hwnd = hwnd.EnabledHwnd;
3382                                                         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);
3383                                                         msg.lParam = (IntPtr)(MousePosition.Y << 16 | MousePosition.X);
3384                                                 }
3385
3386                                                 // The hit test is sent in screen coordinates
3387                                                 XTranslateCoordinates (DisplayHandle, xevent.AnyEvent.window, RootWindow,
3388                                                                 xevent.MotionEvent.x, xevent.MotionEvent.y,
3389                                                                 out screen_x, out screen_y, out dummy);
3390
3391                                                 msg.lParam = (IntPtr) (screen_y << 16 | screen_x & 0xFFFF);
3392                                                 ht = (HitTest)NativeWindow.WndProc (hwnd.client_window, Msg.WM_NCHITTEST,
3393                                                                 IntPtr.Zero, msg.lParam).ToInt32 ();
3394                                                 NativeWindow.WndProc(hwnd.client_window, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)ht);
3395
3396                                                 MousePosition.X = xevent.MotionEvent.x;
3397                                                 MousePosition.Y = xevent.MotionEvent.y;
3398                                         }
3399
3400                                         break;
3401                                 }
3402
3403                                 case XEventName.EnterNotify: {
3404                                         if (!hwnd.Enabled) {
3405                                                 goto ProcessNextMessage;
3406                                         }
3407                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
3408                                                 goto ProcessNextMessage;
3409                                         }
3410                                         msg.message = Msg.WM_MOUSE_ENTER;
3411                                         HoverState.X = xevent.CrossingEvent.x;
3412                                         HoverState.Y = xevent.CrossingEvent.y;
3413                                         HoverState.Timer.Enabled = true;
3414                                         HoverState.Window = xevent.CrossingEvent.window;
3415                                         break;
3416                                 }
3417
3418                                 case XEventName.LeaveNotify: {
3419                                         if (!hwnd.Enabled) {
3420                                                 goto ProcessNextMessage;
3421                                         }
3422                                         if ((xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) || (xevent.CrossingEvent.window != hwnd.client_window)) {
3423                                                 goto ProcessNextMessage;
3424                                         }
3425                                         msg.message=Msg.WM_MOUSE_LEAVE;
3426                                         HoverState.Timer.Enabled = false;
3427                                         HoverState.Window = IntPtr.Zero;
3428                                         break;
3429                                 }
3430
3431                                 #if later
3432                                 case XEventName.CreateNotify: {
3433                                         if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
3434                                                 msg.message = WM_CREATE;
3435                                                 // Set up CreateStruct
3436                                         } else {
3437                                                 goto ProcessNextMessage;
3438                                         }
3439                                         break;
3440                                 }
3441                                 #endif
3442
3443
3444                                 case XEventName.ReparentNotify: {
3445                                         if (hwnd.parent == null) {      // Toplevel
3446                                                 if ((xevent.ReparentEvent.parent != IntPtr.Zero) && (xevent.ReparentEvent.window == hwnd.whole_window)) {
3447                                                         // We need to adjust x/y
3448                                                         // This sucks ass, part 2
3449                                                         // Every WM does the reparenting of toplevel windows different, so there's
3450                                                         // no standard way of getting our adjustment considering frames/decorations
3451                                                         // The code below is needed for metacity. KDE doesn't works just fine without this
3452                                                         int     dummy_int;
3453                                                         IntPtr  dummy_ptr;
3454                                                         int     new_x;
3455                                                         int     new_y;
3456                                                         int     frame_left;
3457                                                         int     frame_top;
3458
3459                                                         hwnd.Reparented = true;
3460
3461                                                         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);
3462                                                         FrameExtents(hwnd.whole_window, out frame_left, out frame_top);
3463                                                         if ((frame_left != 0) && (frame_top != 0) && (new_x != frame_left) && (new_y != frame_top)) {
3464                                                                 hwnd.x = new_x;
3465                                                                 hwnd.y = new_y;
3466                                                                 hwnd.whacky_wm = true;
3467                                                         }
3468
3469                                                         if (hwnd.opacity != 0xffffffff) {
3470                                                                 IntPtr opacity;
3471
3472                                                                 opacity = (IntPtr)(Int32)hwnd.opacity;
3473                                                                 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
3474                                                         }
3475                                                         SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, msg.wParam, msg.lParam);
3476                                                         goto ProcessNextMessage;
3477                                                 } else {
3478                                                         hwnd.Reparented = false;
3479                                                         goto ProcessNextMessage;
3480                                                 }
3481                                         }
3482                                         goto ProcessNextMessage;
3483                                 }
3484
3485                                 case XEventName.ConfigureNotify: {
3486                                         if (ThreadQueue(Thread.CurrentThread).PostQuitState|| !client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {      // Ignore events for children (SubstructureNotify) and client areas
3487                                                 #if DriverDebugExtra
3488                                                         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);
3489                                                 #endif
3490 //                                              if ((hwnd.x != xevent.ConfigureEvent.x) || (hwnd.y != xevent.ConfigureEvent.y) || (hwnd.width != xevent.ConfigureEvent.width) || (hwnd.height != xevent.ConfigureEvent.height)) {
3491                                                         SendMessage(msg.hwnd, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
3492                                                         hwnd.configure_pending = false;
3493
3494                                                         // We need to adjust our client window to track the resize of whole_window
3495                                                         if (hwnd.whole_window != hwnd.client_window)
3496                                                                 PerformNCCalc(hwnd);
3497 //                                              }
3498                                         }
3499                                         goto ProcessNextMessage;
3500                                 }
3501
3502                                 case XEventName.FocusIn: {
3503                                         // We received focus. We use X11 focus only to know if the app window does or does not have focus
3504                                         // We do not track the actual focussed window via it. Instead, this is done via FocusWindow internally
3505                                         // Receiving focus means we've gotten activated and therefore we need to let the actual FocusWindow know 
3506                                         // about it having focus again
3507                                         if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3508                                                 goto ProcessNextMessage;
3509                                         }
3510
3511                                         if (FocusWindow == IntPtr.Zero) {
3512                                                 Control c = Control.FromHandle (hwnd.client_window);
3513                                                 if (c == null)
3514                                                         goto ProcessNextMessage;
3515                                                 Form form = c.FindForm ();
3516                                                 if (form == null)
3517                                                         goto ProcessNextMessage;
3518                                                 ActiveWindow = form.Handle;
3519                                                 SendMessage (ActiveWindow, Msg.WM_ACTIVATE, (IntPtr) WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
3520                                                 goto ProcessNextMessage;
3521                                         }
3522                                         Keyboard.FocusIn(FocusWindow);
3523                                         SendMessage(FocusWindow, Msg.WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero);
3524                                         goto ProcessNextMessage;
3525                                 }
3526
3527                                 case XEventName.FocusOut: {
3528                                         // Se the comment for our FocusIn handler
3529                                         if (xevent.FocusChangeEvent.detail != NotifyDetail.NotifyNonlinear) {
3530                                                 goto ProcessNextMessage;
3531                                         }
3532                                         Keyboard.FocusOut(FocusWindow);
3533
3534                                         while (Keyboard.ResetKeyState(FocusWindow, ref msg)) {
3535                                                 SendMessage(FocusWindow, msg.message, msg.wParam, msg.lParam);
3536                                         }
3537
3538                                         SendMessage(FocusWindow, Msg.WM_KILLFOCUS, IntPtr.Zero, IntPtr.Zero);
3539                                         goto ProcessNextMessage;
3540                                 }
3541
3542                                 case XEventName.Expose: {
3543                                         if (ThreadQueue(Thread.CurrentThread).PostQuitState || !hwnd.Mapped) {
3544                                                 if (client) {
3545                                                         hwnd.expose_pending = false;
3546                                                 } else {
3547                                                         hwnd.nc_expose_pending = false;
3548                                                 }
3549                                                 goto ProcessNextMessage;
3550                                         }
3551
3552                                         if (client) {
3553                                                 if (!hwnd.expose_pending) {
3554                                                         goto ProcessNextMessage;
3555                                                 }
3556                                         } else {
3557                                                 if (!hwnd.nc_expose_pending) {
3558                                                         goto ProcessNextMessage;
3559                                                 }
3560
3561                                                 switch (hwnd.border_style) {
3562                                                         case FormBorderStyle.Fixed3D: {
3563                                                                 Graphics g;
3564
3565                                                                 g = Graphics.FromHwnd(hwnd.whole_window);
3566                                                                 ControlPaint.DrawBorder3D(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Border3DStyle.Sunken);
3567                                                                 g.Dispose();
3568                                                                 break;
3569                                                         }
3570
3571                                                         case FormBorderStyle.FixedSingle: {
3572                                                                 Graphics g;
3573
3574                                                                 g = Graphics.FromHwnd(hwnd.whole_window);
3575                                                                 ControlPaint.DrawBorder(g, new Rectangle(0, 0, hwnd.Width, hwnd.Height), Color.Black, ButtonBorderStyle.Solid);
3576                                                                 g.Dispose();
3577                                                                 break;
3578                                                         }
3579                                                 }
3580                                                 #if DriverDebugExtra
3581                                                         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);
3582                                                 #endif
3583
3584                                                 Rectangle rect = new Rectangle (xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
3585                                                 Region region = new Region (rect);
3586                                                 IntPtr hrgn = region.GetHrgn (null); // Graphics object isn't needed
3587                                                 msg.message = Msg.WM_NCPAINT;
3588                                                 msg.wParam = hrgn == IntPtr.Zero ? (IntPtr)1 : hrgn;
3589                                                 break;
3590                                         }
3591                                         #if DriverDebugExtra
3592                                                 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);
3593                                         #endif
3594                                         if (Caret.Visible == true) {
3595                                                 Caret.Paused = true;
3596                                                 HideCaret();
3597                                         }
3598
3599                                         if (Caret.Visible == true) {
3600                                                 ShowCaret();
3601                                                 Caret.Paused = false;
3602                                         }
3603                                         msg.message = Msg.WM_PAINT;
3604                                         break;
3605                                 }
3606
3607                                 case XEventName.DestroyNotify: {
3608
3609                                         // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
3610                                         hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
3611
3612                                         // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
3613                                         if ((hwnd != null) && (hwnd.client_window == xevent.DestroyWindowEvent.window)) {
3614                                                 CleanupCachedWindows (hwnd);
3615
3616                                                 #if DriverDebugDestroy
3617                                                         Console.WriteLine("Received X11 Destroy Notification for {0}", XplatUI.Window(hwnd.client_window));
3618                                                 #endif
3619
3620                                                 msg.hwnd = hwnd.client_window;
3621                                                 msg.message=Msg.WM_DESTROY;
3622                                                 hwnd.Dispose();
3623                                         } else {
3624                                                 goto ProcessNextMessage;
3625                                         }
3626
3627                                         break;
3628                                 }
3629
3630                                 case XEventName.ClientMessage: {
3631                                         if (Dnd.HandleClientMessage (ref xevent)) {
3632                                                 goto ProcessNextMessage;
3633                                         }
3634
3635                                         if (xevent.ClientMessageEvent.message_type == AsyncAtom) {
3636                                                 XplatUIDriverSupport.ExecuteClientMessage((GCHandle)xevent.ClientMessageEvent.ptr1);
3637                                                 goto ProcessNextMessage;
3638                                         }
3639
3640                                         if (xevent.ClientMessageEvent.message_type == HoverState.Atom) {
3641                                                 msg.message = Msg.WM_MOUSEHOVER;
3642                                                 msg.wParam = GetMousewParam(0);
3643                                                 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
3644                                                 return true;
3645                                         }
3646
3647                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
3648                                                 msg.hwnd = xevent.ClientMessageEvent.ptr1;
3649                                                 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
3650                                                 msg.wParam = xevent.ClientMessageEvent.ptr3;
3651                                                 msg.lParam = xevent.ClientMessageEvent.ptr4;
3652                                                 return true;
3653                                         }
3654
3655                                         #if dontcare
3656                                         if  (xevent.ClientMessageEvent.message_type == _XEMBED) {
3657                                                 Console.WriteLine("GOT EMBED MESSAGE {0:X}", xevent.ClientMessageEvent.ptr2.ToInt32());
3658                                                 break;
3659                                         }
3660                                         #endif
3661
3662                                         if  (xevent.ClientMessageEvent.message_type == WM_PROTOCOLS) {
3663                                                 if (xevent.ClientMessageEvent.ptr1 == WM_DELETE_WINDOW) {
3664                                                         msg.message = Msg.WM_CLOSE;
3665                                                         return true;
3666                                                 }
3667
3668                                                 // We should not get this, but I'll leave the code in case we need it in the future
3669                                                 if (xevent.ClientMessageEvent.ptr1 == WM_TAKE_FOCUS) {
3670                                                         goto ProcessNextMessage;
3671                                                 }
3672                                         }
3673                                         goto ProcessNextMessage;
3674                                 }
3675
3676                                 case XEventName.TimerNotify: {
3677                                         xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
3678                                         goto ProcessNextMessage;
3679                                 }
3680                                         
3681                                 default: {
3682                                         goto ProcessNextMessage;
3683                                 }
3684                         }
3685
3686                         return true;
3687                 }
3688
3689                 internal override bool GetText(IntPtr handle, out string text) {
3690                         IntPtr  textptr;
3691
3692                         textptr = IntPtr.Zero;
3693
3694                         lock (XlibLock) {
3695                                 // FIXME - use _NET properties
3696                                 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
3697                         }
3698                         if (textptr != IntPtr.Zero) {
3699                                 text = Marshal.PtrToStringAnsi(textptr);
3700                                 XFree(textptr);
3701                                 return true;
3702                         } else {
3703                                 text = "";
3704                                 return false;
3705                         }
3706                 }
3707
3708                 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) {
3709                         Hwnd            hwnd;
3710
3711                         hwnd = Hwnd.ObjectFromHandle(handle);
3712
3713                         if (hwnd != null) {
3714                                 x = hwnd.x;
3715                                 y = hwnd.y;
3716                                 width = hwnd.width;
3717                                 height = hwnd.height;
3718
3719                                 PerformNCCalc(hwnd);
3720
3721                                 client_width = hwnd.ClientRect.Width;
3722                                 client_height = hwnd.ClientRect.Height;
3723
3724                                 return;
3725                         }
3726
3727                         // Should we throw an exception or fail silently?
3728                         // throw new ArgumentException("Called with an invalid window handle", "handle");
3729
3730                         x = 0;
3731                         y = 0;
3732                         width = 0;
3733                         height = 0;
3734                         client_width = 0;
3735                         client_height = 0;
3736                 }
3737
3738                 internal override FormWindowState GetWindowState(IntPtr handle) {
3739                         IntPtr                  actual_atom;
3740                         int                     actual_format;
3741                         IntPtr                  nitems;
3742                         IntPtr                  bytes_after;
3743                         IntPtr                  prop = IntPtr.Zero;
3744                         IntPtr                  atom;
3745                         int                     maximized;
3746                         bool                    minimized;
3747                         XWindowAttributes       attributes;
3748                         Hwnd                    hwnd;
3749
3750                         hwnd = Hwnd.ObjectFromHandle(handle);
3751
3752                         maximized = 0;
3753                         minimized = false;
3754                         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);
3755                         if (((long)nitems > 0) && (prop != IntPtr.Zero)) {
3756                                 for (int i = 0; i < (long)nitems; i++) {
3757                                         atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
3758                                         if ((atom == _NET_WM_STATE_MAXIMIZED_HORZ) || (atom == _NET_WM_STATE_MAXIMIZED_VERT)) {
3759                                                 maximized++;
3760                                         } else if (atom == _NET_WM_STATE_HIDDEN) {
3761                                                 minimized = true;
3762                                         }
3763                                 }
3764                                 XFree(prop);
3765                         }
3766
3767                         if (minimized) {
3768                                 return FormWindowState.Minimized;
3769                         } else if (maximized == 2) {
3770                                 return FormWindowState.Maximized;
3771                         }
3772
3773                         attributes = new XWindowAttributes();
3774                         XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3775                         if (attributes.map_state == MapState.IsUnmapped) {
3776                                 return (FormWindowState)(-1);
3777                         }
3778
3779
3780                         return FormWindowState.Normal;
3781                 }
3782
3783                 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
3784                         handle = Grab.Hwnd;
3785                         GrabConfined = Grab.Confined;
3786                         GrabArea = Grab.Area;
3787                 }
3788
3789                 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
3790                         Hwnd    hwnd;
3791                         IntPtr  confine_to_window;
3792
3793                         confine_to_window = IntPtr.Zero;
3794
3795                         if (confine_to_handle != IntPtr.Zero) {
3796                                 XWindowAttributes       attributes = new XWindowAttributes();
3797
3798                                 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
3799
3800                                 lock (XlibLock) {
3801                                         XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
3802                                 }
3803                                 Grab.Area.X = attributes.x;
3804                                 Grab.Area.Y = attributes.y;
3805                                 Grab.Area.Width = attributes.width;
3806                                 Grab.Area.Height = attributes.height;
3807                                 Grab.Confined = true;
3808                                 confine_to_window = hwnd.client_window;
3809                         }
3810
3811                         Grab.Hwnd = handle;
3812
3813                         hwnd = Hwnd.ObjectFromHandle(handle);
3814
3815                         lock (XlibLock) {
3816                                 XGrabPointer(DisplayHandle, hwnd.client_window, false, 
3817                                         EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
3818                                         EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
3819                                         GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, IntPtr.Zero, IntPtr.Zero);
3820                         }
3821                 }
3822
3823                 internal override void UngrabWindow(IntPtr hwnd) {
3824                         lock (XlibLock) {
3825                                 XUngrabPointer(DisplayHandle, IntPtr.Zero);
3826                                 XFlush(DisplayHandle);
3827                         }
3828                         Grab.Hwnd = IntPtr.Zero;
3829                         Grab.Confined = false;
3830                 }
3831
3832                 internal override void HandleException(Exception e) {
3833                         StackTrace st = new StackTrace(e, true);
3834                         Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
3835                         Console.WriteLine("{0}{1}", e.Message, st.ToString());
3836                 }
3837
3838                 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
3839                         Hwnd    hwnd;
3840
3841                         hwnd = Hwnd.ObjectFromHandle(handle);
3842
3843                         if (clear) {
3844                                 AddExpose (hwnd, true, hwnd.X, hwnd.Y, hwnd.Width, hwnd.Height);
3845                         } else {
3846                                 AddExpose (hwnd, true, rc.X, rc.Y, rc.Width, rc.Height);
3847                         }
3848                 }
3849
3850                 internal override bool IsEnabled(IntPtr handle) {
3851                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3852                         return (hwnd != null && hwnd.Enabled);
3853                 }
3854                 
3855                 internal override bool IsVisible(IntPtr handle) {
3856                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
3857                         return (hwnd != null && hwnd.visible);
3858                 }
3859
3860                 internal override void KillTimer(Timer timer) {
3861                         XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
3862
3863                         if (queue == null) {
3864                                 // This isn't really an error, MS doesn't start the timer if
3865                                 // it has no assosciated queue
3866                                 return;
3867                         }
3868                         queue.timer_list.Remove (timer);
3869                 }
3870
3871                 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
3872                         int     dest_x_return;
3873                         int     dest_y_return;
3874                         IntPtr  child;
3875                         Hwnd    hwnd;
3876
3877                         hwnd = Hwnd.ObjectFromHandle(handle);
3878
3879                         lock (XlibLock) {
3880                                 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
3881                         }
3882
3883                         x = dest_x_return;
3884                         y = dest_y_return;
3885                 }
3886
3887                 internal override void OverrideCursor(IntPtr cursor) {
3888                         OverrideCursorHandle = cursor;
3889                 }
3890
3891                 internal override PaintEventArgs PaintEventStart(IntPtr handle, bool client) {
3892                         PaintEventArgs  paint_event;
3893                         Hwnd            hwnd;
3894
3895                         hwnd = Hwnd.ObjectFromHandle(handle);
3896
3897                         if (Caret.Visible == true) {
3898                                 Caret.Paused = true;
3899                                 HideCaret();
3900                         }
3901
3902                         Graphics dc;
3903
3904                         if (client) {
3905                                 dc = Graphics.FromHwnd (hwnd.client_window);
3906
3907                                 Region clip_region = new Region ();
3908                                 clip_region.MakeEmpty();
3909
3910                                 foreach (Rectangle r in hwnd.ClipRectangles) {
3911                                         clip_region.Union (r);
3912                                 }
3913
3914                                 if (hwnd.UserClip != null) {
3915                                         clip_region.Intersect(hwnd.UserClip);
3916                                 }
3917
3918                                 dc.Clip = clip_region;
3919                                 paint_event = new PaintEventArgs(dc, hwnd.Invalid);
3920                                 hwnd.expose_pending = false;
3921
3922                                 hwnd.ClearInvalidArea();
3923
3924                                 hwnd.drawing_stack.Push (dc);
3925
3926                                 return paint_event;
3927                         } else {
3928                                 dc = Graphics.FromHwnd (hwnd.whole_window);
3929
3930                                 if (!hwnd.nc_invalid.IsEmpty) {
3931                                         dc.SetClip (hwnd.nc_invalid);
3932                                         paint_event = new PaintEventArgs(dc, hwnd.nc_invalid);
3933                                 } else {
3934                                         paint_event = new PaintEventArgs(dc, new Rectangle(0, 0, hwnd.width, hwnd.height));
3935                                 }
3936                                 hwnd.nc_expose_pending = false;
3937
3938                                 hwnd.ClearNcInvalidArea ();
3939
3940                                 hwnd.drawing_stack.Push (dc);
3941
3942                                 return paint_event;
3943                         }
3944                 }
3945
3946                 internal override void PaintEventEnd(IntPtr handle, bool client) {
3947                         Hwnd    hwnd;
3948
3949                         hwnd = Hwnd.ObjectFromHandle(handle);
3950
3951                         Graphics dc = (Graphics)hwnd.drawing_stack.Pop ();
3952                         dc.Flush();
3953                         dc.Dispose();
3954
3955                         if (Caret.Visible == true) {
3956                                 ShowCaret();
3957                                 Caret.Paused = false;
3958                         }
3959                 }
3960
3961                 [MonoTODO("Implement filtering and PM_NOREMOVE")]
3962                 internal override bool PeekMessage(Object queue_id, ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
3963                         XEventQueue queue = (XEventQueue) queue_id;
3964                         bool    pending;
3965
3966                         if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {
3967                                 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet");    // FIXME - Implement PM_NOREMOVE flag
3968                         }
3969
3970                         pending = false;
3971                         if (queue.Count > 0) {
3972                                 pending = true;
3973                         } else {
3974                                 // Only call UpdateMessageQueue if real events are pending 
3975                                 // otherwise we go to sleep on the socket
3976                                 if (XPending(DisplayHandle) != 0) {
3977                                         UpdateMessageQueue((XEventQueue)queue_id);
3978                                         pending = true;
3979                                 } else if (((XEventQueue)queue_id).Paint.Count > 0) {
3980                                         pending = true;
3981                                 }
3982                         }
3983
3984                         CheckTimers(queue.timer_list, DateTime.UtcNow);
3985
3986                         if (!pending) {
3987                                 return false;
3988                         }
3989                         return GetMessage(queue_id, ref msg, hWnd, wFilterMin, wFilterMax);
3990                 }
3991
3992                 // FIXME - I think this should just enqueue directly
3993                 internal override bool PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
3994                         XEvent xevent = new XEvent ();
3995                         Hwnd hwnd = Hwnd.ObjectFromHandle(handle);
3996
3997                         xevent.type = XEventName.ClientMessage;
3998                         xevent.ClientMessageEvent.display = DisplayHandle;
3999
4000                         if (hwnd != null) {
4001                                 xevent.ClientMessageEvent.window = hwnd.whole_window;
4002                         } else {
4003                                 xevent.ClientMessageEvent.window = IntPtr.Zero;
4004                         }
4005
4006                         xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
4007                         xevent.ClientMessageEvent.format = 32;
4008                         xevent.ClientMessageEvent.ptr1 = handle;
4009                         xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
4010                         xevent.ClientMessageEvent.ptr3 = wparam;
4011                         xevent.ClientMessageEvent.ptr4 = lparam;
4012
4013                         hwnd.Queue.Enqueue (xevent);
4014
4015                         return true;
4016                 }
4017
4018                 internal override void PostQuitMessage(int exitCode) {
4019                         
4020                         XFlush(DisplayHandle);
4021                         ThreadQueue(Thread.CurrentThread).PostQuitState = true;
4022                 }
4023
4024                 internal override void RequestNCRecalc(IntPtr handle) {
4025                         Hwnd                            hwnd;
4026
4027                         hwnd = Hwnd.ObjectFromHandle(handle);
4028
4029                         if (hwnd == null) {
4030                                 return;
4031                         }
4032
4033                         PerformNCCalc(hwnd);
4034                         SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4035                         InvalidateWholeWindow(handle);
4036                 }
4037
4038                 internal override void ResetMouseHover(IntPtr handle) {
4039                         Hwnd    hwnd;
4040
4041                         hwnd = Hwnd.ObjectFromHandle(handle);
4042                         if (hwnd == null) {
4043                                 return;
4044                         }
4045
4046                         HoverState.Timer.Enabled = true;
4047                         HoverState.X = MousePosition.X;
4048                         HoverState.Y = MousePosition.Y;
4049                         HoverState.Window = handle;
4050                 }
4051
4052
4053                 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
4054                         int     dest_x_return;
4055                         int     dest_y_return;
4056                         IntPtr  child;
4057                         Hwnd    hwnd;
4058
4059                         hwnd = Hwnd.ObjectFromHandle(handle);
4060
4061                         lock (XlibLock) {
4062                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
4063                         }
4064
4065                         x = dest_x_return;
4066                         y = dest_y_return;
4067                 }
4068
4069                 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
4070                         int     dest_x_return;
4071                         int     dest_y_return;
4072                         IntPtr  child;
4073                         Hwnd    hwnd;
4074
4075                         hwnd = Hwnd.ObjectFromHandle(handle);
4076
4077                         lock (XlibLock) {
4078                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.whole_window, x, y, out dest_x_return, out dest_y_return, out child);
4079                         }
4080
4081                         x = dest_x_return;
4082                         y = dest_y_return;
4083                 }
4084
4085                 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
4086                         Hwnd            hwnd;
4087                         IntPtr          gc;
4088                         XGCValues       gc_values;
4089                         Rectangle       r;
4090
4091                         hwnd = Hwnd.ObjectFromHandle(handle);
4092
4093                         r = hwnd.Invalid;
4094                         if (r != Rectangle.Empty) {
4095                                 /* We have an invalid area in the window we're scrolling. 
4096                                    Adjust our stored invalid rectangle to to match the scrolled amount */
4097
4098                                 r.X += XAmount;
4099                                 r.Y += YAmount;
4100
4101                                 if (r.X < 0) {
4102                                         r.Width += r.X;
4103                                         r.X =0;
4104                                 }
4105
4106                                 if (r.Y < 0) {
4107                                         r.Height += r.Y;
4108                                         r.Y =0;
4109                                 }
4110
4111                                 hwnd.ClearInvalidArea();
4112                                 hwnd.AddInvalidArea(r);
4113                         }
4114
4115                         gc_values = new XGCValues();
4116
4117                         if (with_children) {
4118                                 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
4119                         }
4120
4121                         gc = XCreateGC(DisplayHandle, hwnd.client_window, IntPtr.Zero, ref gc_values);
4122
4123                         int src_x, src_y;
4124                         int dest_x, dest_y;
4125                         int width, height;
4126
4127                         if (YAmount > 0) {
4128                                 src_y = area.Y;
4129                                 height = area.Height - YAmount;
4130                                 dest_y = area.Y + YAmount;
4131                         }
4132                         else {
4133                                 src_y = area.Y - YAmount;
4134                                 height = area.Height + YAmount;
4135                                 dest_y = area.Y;
4136                         }
4137
4138                         if (XAmount > 0) {
4139                                 src_x = area.X;
4140                                 width = area.Width - XAmount;
4141                                 dest_x = area.X + XAmount;
4142                         }
4143                         else {
4144                                 src_x = area.X - XAmount;
4145                                 width = area.Width + XAmount;
4146                                 dest_x = area.X;
4147                         }
4148
4149                         XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, src_x, src_y, width, height, dest_x, dest_y);
4150
4151                         // Generate an expose for the area exposed by the horizontal scroll
4152                         // We don't use AddExpose since we're 
4153                         if (XAmount > 0) {
4154                                 AddExpose(hwnd, true, area.X, area.Y, XAmount, area.Height);
4155                         } else if (XAmount < 0) {
4156                                 AddExpose(hwnd, true, XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
4157                         }
4158
4159                         // Generate an expose for the area exposed by the vertical scroll
4160                         if (YAmount > 0) {
4161                                 AddExpose(hwnd, true, area.X, area.Y, area.Width, YAmount);
4162                         } else if (YAmount < 0) {
4163                                 AddExpose(hwnd, true, area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
4164                         }
4165                         XFreeGC(DisplayHandle, gc);
4166                 }
4167
4168                 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
4169                         Hwnd            hwnd;
4170                         Rectangle       rect;
4171
4172                         hwnd = Hwnd.GetObjectFromWindow(handle);
4173
4174                         rect = hwnd.ClientRect;
4175                         rect.X = 0;
4176                         rect.Y = 0;
4177                         ScrollWindow(handle, rect, XAmount, YAmount, with_children);
4178                 }
4179
4180                 internal override void SendAsyncMethod (AsyncMethodData method) {
4181                         Hwnd    hwnd;
4182                         XEvent  xevent = new XEvent ();
4183
4184                         hwnd = Hwnd.ObjectFromHandle(method.Handle);
4185
4186                         xevent.type = XEventName.ClientMessage;
4187                         xevent.ClientMessageEvent.display = DisplayHandle;
4188                         xevent.ClientMessageEvent.window = method.Handle;
4189                         xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
4190                         xevent.ClientMessageEvent.format = 32;
4191                         xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
4192
4193                         hwnd.Queue.EnqueueLocked (xevent);
4194
4195                         WakeupMain ();
4196                 }
4197
4198                 delegate IntPtr WndProcDelegate (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam);
4199
4200                 internal override IntPtr SendMessage (IntPtr hwnd, Msg message, IntPtr wParam, IntPtr lParam)
4201                 {
4202                         Hwnd    h;
4203                         h = Hwnd.ObjectFromHandle(hwnd);
4204
4205                         if (h != null && h.queue != ThreadQueue (Thread.CurrentThread)) {
4206                                 AsyncMethodResult       result;
4207                                 AsyncMethodData         data;
4208
4209                                 result = new AsyncMethodResult ();
4210                                 data = new AsyncMethodData ();
4211
4212                                 data.Handle = hwnd;
4213                                 data.Method = new WndProcDelegate (NativeWindow.WndProc);
4214                                 data.Args = new object[] { hwnd, message, wParam, lParam };
4215                                 data.Result = result;
4216                                 
4217                                 SendAsyncMethod (data);
4218                                 #if DriverDebug || DriverDebugThreads
4219                                 Console.WriteLine ("Sending {0} message across.", message);
4220                                 #endif
4221
4222                                 return IntPtr.Zero;
4223                         }
4224                         return NativeWindow.WndProc(hwnd, message, wParam, lParam);
4225                 }
4226
4227                 internal override void SetAllowDrop (IntPtr handle, bool value)
4228                 {
4229                         // We allow drop on all windows
4230                 }
4231
4232                 internal override DragDropEffects StartDrag (IntPtr handle, object data,
4233                                 DragDropEffects allowed_effects)
4234                 {
4235                         Hwnd hwnd = Hwnd.ObjectFromHandle (handle);
4236
4237                         if (hwnd == null)
4238                                 throw new ArgumentException ("Attempt to begin drag from invalid window handle (" + handle.ToInt32 () + ").");
4239
4240                         return Dnd.StartDrag (hwnd.client_window, data, allowed_effects);
4241                 }
4242
4243                 internal override void SetBorderStyle(IntPtr handle, FormBorderStyle border_style) {
4244                         Hwnd    hwnd;
4245
4246                         hwnd = Hwnd.ObjectFromHandle(handle);
4247
4248                         Form form = Control.FromHandle (handle) as Form;
4249                         if (form != null && form.window_manager == null && (border_style == FormBorderStyle.FixedToolWindow ||
4250                                         border_style == FormBorderStyle.SizableToolWindow)) {
4251                                 form.window_manager = new InternalWindowManager (form);
4252                         }
4253                         
4254                         hwnd.border_style = border_style;
4255                         RequestNCRecalc(handle);
4256                 }
4257
4258                 internal override void SetCaretPos(IntPtr handle, int x, int y) {
4259                         if (Caret.Hwnd == handle) {
4260                                 Caret.Timer.Stop();
4261                                 HideCaret();
4262
4263                                 Caret.X = x;
4264                                 Caret.Y = y;
4265
4266                                 if (Caret.Visible == true) {
4267                                         ShowCaret();
4268                                         Caret.Timer.Start();
4269                                 }
4270                         }
4271                 }
4272
4273                 internal override void SetClipRegion(IntPtr handle, Region region) {
4274                         Hwnd    hwnd;
4275
4276                         hwnd = Hwnd.ObjectFromHandle(handle);
4277                         if (hwnd == null) {
4278                                 return;
4279                         }
4280
4281                         hwnd.UserClip = region;
4282                         Invalidate(handle, new Rectangle(0, 0, hwnd.Width, hwnd.Height), false);
4283                 }
4284
4285                 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
4286                         Hwnd    hwnd;
4287
4288                         if (OverrideCursorHandle == IntPtr.Zero) {
4289                                 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
4290                                         return;
4291                                 }
4292
4293                                 LastCursorHandle = cursor;
4294                                 LastCursorWindow = handle;
4295
4296                                 hwnd = Hwnd.ObjectFromHandle(handle);
4297                                 lock (XlibLock) {
4298                                         if (cursor != IntPtr.Zero) {
4299                                                 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
4300                                         } else {
4301                                                 XUndefineCursor(DisplayHandle, hwnd.whole_window);
4302                                         }
4303                                         XFlush(DisplayHandle);
4304                                 }
4305                                 return;
4306                         }
4307
4308                         hwnd = Hwnd.ObjectFromHandle(handle);
4309                         lock (XlibLock) {
4310                                 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
4311                         }
4312                 }
4313
4314                 private void QueryPointer (IntPtr display, IntPtr w, out IntPtr root, out IntPtr child,
4315                                            out int root_x, out int root_y, out int child_x, out int child_y,
4316                                            out int mask)
4317                 {
4318                         /* this code was written with the help of
4319                         glance at gdk.  I never would have realized we
4320                         needed a loop in order to traverse down in the
4321                         hierarchy.  I would have assumed you'd get the
4322                         most deeply nested child and have to do
4323                         XQueryTree to move back up the hierarchy..
4324                         stupid me, of course. */
4325                         IntPtr c;
4326
4327                         XGrabServer (display);
4328
4329                         XQueryPointer(display, w, out root, out c,
4330                                       out root_x, out root_y, out child_x, out child_y,
4331                                       out mask);
4332
4333                         if (root != w)
4334                                 c = root;
4335
4336                         IntPtr child_last = IntPtr.Zero;
4337                         while (c != IntPtr.Zero) {
4338                                 child_last = c;
4339                                 XQueryPointer(display, c, out root, out c,
4340                                               out root_x, out root_y, out child_x, out child_y,
4341                                               out mask);
4342                         }
4343                         XUngrabServer (display);
4344
4345                         child = child_last;
4346                 }
4347
4348                 internal override void SetCursorPos(IntPtr handle, int x, int y) {
4349                         if (handle == IntPtr.Zero) {
4350                                 lock (XlibLock) {
4351                                         IntPtr root, child;
4352                                         int root_x, root_y, child_x, child_y, mask;
4353
4354                                         /* we need to do a
4355                                          * QueryPointer before warping
4356                                          * because if the warp is on
4357                                          * the RootWindow, the x/y are
4358                                          * relative to the current
4359                                          * mouse position
4360                                          */
4361                                         QueryPointer (DisplayHandle, RootWindow,
4362                                                       out root,
4363                                                       out child,
4364                                                       out root_x, out root_y,
4365                                                       out child_x, out child_y,
4366                                                       out mask);
4367
4368                                         XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x - root_x, y - root_y);
4369
4370                                         XFlush (DisplayHandle);
4371
4372                                         /* then we need to a
4373                                          * QueryPointer after warping
4374                                          * to manually generate a
4375                                          * motion event for the window
4376                                          * we move into.
4377                                          */
4378                                         QueryPointer (DisplayHandle, RootWindow,
4379                                                       out root,
4380                                                       out child,
4381                                                       out root_x, out root_y,
4382                                                       out child_x, out child_y,
4383                                                       out mask);
4384
4385                                         Hwnd child_hwnd = Hwnd.ObjectFromHandle(child);
4386                                         if (child_hwnd == null) {
4387                                                 return;
4388                                         }
4389
4390                                         XEvent xevent = new XEvent ();
4391
4392                                         xevent.type = XEventName.MotionNotify;
4393                                         xevent.MotionEvent.display = DisplayHandle;
4394                                         xevent.MotionEvent.window = child_hwnd.client_window;
4395                                         xevent.MotionEvent.root = RootWindow;
4396                                         xevent.MotionEvent.x = child_x;
4397                                         xevent.MotionEvent.y = child_y;
4398                                         xevent.MotionEvent.x_root = root_x;
4399                                         xevent.MotionEvent.y_root = root_y;
4400                                         xevent.MotionEvent.state = mask;
4401
4402                                         child_hwnd.Queue.Enqueue (xevent);
4403                                 }
4404                         } else {
4405                                 Hwnd    hwnd;
4406
4407                                 hwnd = Hwnd.ObjectFromHandle(handle);
4408                                 lock (XlibLock) {
4409                                         XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
4410                                 }
4411                         }
4412                 }
4413
4414                 internal override void SetFocus(IntPtr handle) {
4415                         Hwnd    hwnd;
4416                         IntPtr  prev_focus_window;
4417
4418                         hwnd = Hwnd.ObjectFromHandle(handle);
4419
4420                         if (hwnd.client_window == FocusWindow) {
4421                                 return;
4422                         }
4423
4424                         prev_focus_window = FocusWindow;
4425                         FocusWindow = hwnd.client_window;
4426
4427                         if (prev_focus_window != IntPtr.Zero) {
4428                                 SendMessage(prev_focus_window, Msg.WM_KILLFOCUS, FocusWindow, IntPtr.Zero);
4429                         }
4430                         SendMessage(FocusWindow, Msg.WM_SETFOCUS, prev_focus_window, IntPtr.Zero);
4431
4432                         //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
4433                 }
4434
4435                 internal override void SetIcon(IntPtr handle, Icon icon) {
4436                         Hwnd    hwnd;
4437
4438                         hwnd = Hwnd.ObjectFromHandle(handle);
4439                         if (hwnd != null) {
4440                                 SetIcon(hwnd, icon);
4441                         }
4442                 }
4443
4444                 internal override void SetMenu(IntPtr handle, Menu menu) {
4445                         Hwnd    hwnd;
4446
4447                         hwnd = Hwnd.ObjectFromHandle(handle);
4448                         hwnd.menu = menu;
4449
4450                         RequestNCRecalc(handle);
4451                 }
4452
4453                 internal override void SetModal(IntPtr handle, bool Modal) {
4454                         if (Modal) {
4455                                 ModalWindows.Push(handle);
4456                         } else {
4457                                 if (ModalWindows.Contains(handle)) {
4458                                         ModalWindows.Pop();
4459                                 }
4460                                 if (ModalWindows.Count > 0) {
4461                                         Activate((IntPtr)ModalWindows.Peek());
4462                                 }
4463                         }
4464                 }
4465
4466                 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
4467                         Hwnd    hwnd;
4468
4469                         hwnd = Hwnd.ObjectFromHandle(handle);
4470                         hwnd.parent = Hwnd.ObjectFromHandle(parent);
4471
4472                         lock (XlibLock) {
4473                                 #if DriverDebug || DriverDebugParent
4474                                         Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
4475                                 #endif
4476                                 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent == null ? FosterParent : hwnd.parent.client_window, hwnd.x, hwnd.y);
4477                         }
4478
4479                         return IntPtr.Zero;
4480                 }
4481
4482                 internal override void SetTimer (Timer timer) {
4483                         XEventQueue queue = (XEventQueue) MessageQueues [timer.thread];
4484
4485                         if (queue == null) {
4486                                 // This isn't really an error, MS doesn't start the timer if
4487                                 // it has no assosciated queue
4488                                 return;
4489                         }
4490                         queue.timer_list.Add (timer);
4491                         WakeupMain ();
4492                 }
4493
4494                 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
4495                         Hwnd    hwnd;
4496                         Hwnd    hwnd_owner;
4497
4498                         hwnd = Hwnd.ObjectFromHandle(handle);
4499
4500                         if (handle_owner != IntPtr.Zero) {
4501                                 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
4502                         } else {
4503                                 hwnd_owner = null;
4504                         }
4505
4506                         if (enabled) {
4507                                 lock (XlibLock) {
4508                                         int[]   atoms;
4509
4510                                         atoms = new int[8];
4511
4512                                         atoms[0] = _NET_WM_WINDOW_TYPE_NORMAL.ToInt32();
4513                                         XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_WINDOW_TYPE, (IntPtr)Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, 1);
4514
4515                                         if (hwnd_owner != null) {
4516                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
4517                                         } else {
4518                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, RootWindow);
4519                                         }
4520                                 }
4521                         } else {
4522                                 lock (XlibLock) {
4523                                         XDeleteProperty(DisplayHandle, hwnd.whole_window, (IntPtr)Atom.XA_WM_TRANSIENT_FOR);
4524                                 }
4525                         }
4526                         return true;
4527                 }
4528
4529                 internal override bool SetVisible(IntPtr handle, bool visible, bool activate) {
4530                         Hwnd    hwnd;
4531
4532                         hwnd = Hwnd.ObjectFromHandle(handle);
4533                         hwnd.visible = visible;
4534
4535                         lock (XlibLock) {
4536                                 if (visible) {
4537                                         if (Control.FromHandle(handle) is Form) {
4538                                                 FormWindowState s;
4539
4540                                                 s = ((Form)Control.FromHandle(handle)).WindowState;
4541
4542                                                 MapWindow(hwnd, WindowType.Both);
4543
4544                                                 switch(s) {
4545                                                         case FormWindowState.Minimized: SetWindowState(handle, FormWindowState.Minimized); break;
4546                                                         case FormWindowState.Maximized: SetWindowState(handle, FormWindowState.Maximized); break;
4547                                                 }
4548
4549                                         } else {
4550                                                 MapWindow(hwnd, WindowType.Both);
4551                                         }
4552                                         SendMessage(handle, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4553                                 } else {
4554                                         UnmapWindow(hwnd, WindowType.Whole);
4555                                 }
4556                         }
4557                         return true;
4558                 }
4559
4560                 internal override void SetWindowMinMax(IntPtr handle, Rectangle maximized, Size min, Size max) {
4561                         Hwnd            hwnd;
4562                         XSizeHints      hints;
4563                         IntPtr          dummy;
4564
4565                         hwnd = Hwnd.ObjectFromHandle(handle);
4566                         if (hwnd == null) {
4567                                 return;
4568                         }
4569
4570                         hints = new XSizeHints();
4571
4572                         XGetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints, out dummy);
4573                         if ((min != Size.Empty) && (min.Width > 0) && (min.Height > 0)) {
4574                                 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMinSize);
4575                                 hints.min_width = min.Width;
4576                                 hints.min_height = min.Height;
4577                         }
4578
4579                         if ((max != Size.Empty) && (max.Width > 0) && (max.Height > 0)) {
4580                                 hints.flags = (IntPtr)((int)hints.flags | (int)XSizeHintsFlags.PMaxSize);
4581                                 hints.max_width = max.Width;
4582                                 hints.max_height = max.Height;
4583                         }
4584
4585                         if (hints.flags != IntPtr.Zero) {
4586                                 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref hints);
4587                         }
4588
4589                         if ((maximized != Rectangle.Empty) && (maximized.Width > 0) && (maximized.Height > 0)) {
4590                                 hints.flags = (IntPtr)XSizeHintsFlags.PPosition;
4591                                 hints.x = maximized.X;
4592                                 hints.y = maximized.Y;
4593                                 hints.width = maximized.Width;
4594                                 hints.height = maximized.Height;
4595
4596                                 // Metacity does not seem to follow this constraint for maximized (zoomed) windows
4597                                 XSetZoomHints(DisplayHandle, hwnd.whole_window, ref hints);
4598                         }
4599                 }
4600
4601
4602                 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
4603                         Hwnd            hwnd;
4604
4605                         hwnd = Hwnd.ObjectFromHandle(handle);
4606
4607                         if (hwnd == null) {
4608                                 return;
4609                         }
4610
4611                         // X requires a sanity check for width & height; otherwise it dies
4612                         if (hwnd.zero_sized && width > 0 && height > 0) {
4613                                 if (hwnd.visible) {
4614                                         MapWindow(hwnd, WindowType.Whole);
4615                                 }
4616                                 hwnd.zero_sized = false;
4617                         }
4618
4619                         if ((width < 1) || (height < 1)) {
4620                                 hwnd.zero_sized = true;
4621                                 UnmapWindow(hwnd, WindowType.Whole);
4622                         }
4623
4624                         // Save a server roundtrip (and prevent a feedback loop)
4625                         if ((hwnd.x == x) && (hwnd.y == y) && 
4626                                 (hwnd.width == width) && (hwnd.height == height)) {
4627                                 return;
4628                         }
4629
4630                         if (!hwnd.zero_sized) {
4631                                 //Hack?
4632                                 hwnd.x = x;
4633                                 hwnd.y = y;
4634                                 hwnd.width = width;
4635                                 hwnd.height = height;
4636                                 SendMessage(hwnd.client_window, Msg.WM_WINDOWPOSCHANGED, IntPtr.Zero, IntPtr.Zero);
4637
4638                                 if (hwnd.fixed_size) {
4639                                         SetWindowMinMax(handle, Rectangle.Empty, new Size(width, height), new Size(width, height));
4640                                 }
4641
4642                                 lock (XlibLock) {
4643                                         XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
4644                                         PerformNCCalc(hwnd);
4645                                 }
4646                         }
4647
4648                         // Update our position/size immediately, so
4649                         // that future calls to SetWindowPos aren't
4650                         // kept from calling XMoveResizeWindow (by the
4651                         // "Save a server roundtrip" block above).
4652                         hwnd.x = x;
4653                         hwnd.y = y;
4654                         hwnd.width = width;
4655                         hwnd.height = height;
4656                         hwnd.ClientRect = Rectangle.Empty;
4657                 }
4658
4659                 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
4660                         FormWindowState current_state;
4661                         Hwnd            hwnd;
4662
4663                         hwnd = Hwnd.ObjectFromHandle(handle);
4664
4665                         current_state = GetWindowState(handle);
4666
4667                         if (current_state == state) {
4668                                 return;
4669                         }
4670
4671                         switch(state) {
4672                                 case FormWindowState.Normal: {
4673                                         lock (XlibLock) {
4674                                                 if (current_state == FormWindowState.Minimized) {
4675                                                         MapWindow(hwnd, WindowType.Both);
4676                                                 } else if (current_state == FormWindowState.Maximized) {
4677                                                         SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4678                                                 }
4679                                         }
4680                                         Activate(handle);
4681                                         return;
4682                                 }
4683
4684                                 case FormWindowState.Minimized: {
4685                                         lock (XlibLock) {
4686                                                 if (current_state == FormWindowState.Maximized) {
4687                                                         SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)2 /* toggle */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4688                                                 }
4689                                                 XIconifyWindow(DisplayHandle, hwnd.whole_window, ScreenNo);
4690                                         }
4691                                         return;
4692                                 }
4693
4694                                 case FormWindowState.Maximized: {
4695                                         lock (XlibLock) {
4696                                                 if (current_state == FormWindowState.Minimized) {
4697                                                         MapWindow(hwnd, WindowType.Both);
4698                                                 }
4699
4700                                                 SendNetWMMessage(hwnd.whole_window, _NET_WM_STATE, (IntPtr)1 /* Add */, _NET_WM_STATE_MAXIMIZED_HORZ, _NET_WM_STATE_MAXIMIZED_VERT);
4701                                         }
4702                                         Activate(handle);
4703                                         return;
4704                                 }
4705                         }
4706                 }
4707
4708                 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
4709                         Hwnd    hwnd;
4710
4711                         hwnd = Hwnd.ObjectFromHandle(handle);
4712                         SetHwndStyles(hwnd, cp);
4713                         SetWMStyles(hwnd, cp);
4714                 }
4715
4716                 internal override void SetWindowTransparency(IntPtr handle, double transparency, Color key) {
4717                         Hwnd    hwnd;
4718                         IntPtr  opacity;
4719
4720                         hwnd = Hwnd.ObjectFromHandle(handle);
4721
4722                         if (hwnd == null) {
4723                                 return;
4724                         }
4725
4726                         hwnd.opacity = (uint)(0xffffffff * transparency);
4727                         opacity = (IntPtr)((int)hwnd.opacity);
4728
4729                         if (hwnd.reparented) {
4730                                 XChangeProperty(DisplayHandle, XGetParent(hwnd.whole_window), _NET_WM_WINDOW_OPACITY, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, ref opacity, 1);
4731                         }
4732                 }
4733
4734                 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
4735                         Hwnd    hwnd = Hwnd.ObjectFromHandle(handle);
4736
4737                         if (!hwnd.mapped) {
4738                                 return false;
4739                         }
4740
4741                         if (top) {
4742                                 lock (XlibLock) {
4743                                         XRaiseWindow(DisplayHandle, hwnd.whole_window);
4744                                 }
4745                                 return true;
4746                         } else if (!bottom) {
4747                                 Hwnd    after_hwnd = null;
4748
4749                                 if (after_handle != IntPtr.Zero) {
4750                                         after_hwnd = Hwnd.ObjectFromHandle(after_handle);
4751                                 }
4752
4753                                 XWindowChanges  values = new XWindowChanges();
4754
4755                                 if (after_hwnd == null) {
4756                                         // Work around metacity 'issues'
4757                                         int[]   atoms;
4758
4759                                         atoms = new int[2];
4760                                         atoms[0] = unixtime();
4761                                         XChangeProperty(DisplayHandle, hwnd.whole_window, _NET_WM_USER_TIME, (IntPtr)Atom.XA_CARDINAL, 32, PropertyMode.Replace, atoms, 1);
4762
4763                                         XRaiseWindow(DisplayHandle, hwnd.whole_window);
4764                                         SendNetWMMessage(hwnd.whole_window, _NET_ACTIVE_WINDOW, (IntPtr)1, IntPtr.Zero, IntPtr.Zero);
4765                                         return true;
4766                                         //throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
4767                                 }
4768
4769                                 values.sibling = after_hwnd.whole_window;
4770                                 values.stack_mode = StackMode.Below;
4771
4772                                 lock (XlibLock) {
4773                                         XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
4774                                 }
4775                         } else {
4776                                 // Bottom
4777                                 lock (XlibLock) {
4778                                         XLowerWindow(DisplayHandle, hwnd.whole_window);
4779                                 }
4780                                 return true;
4781                         }
4782                         return false;
4783                 }
4784
4785                 internal override void ShowCursor(bool show) {
4786                         ;       // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
4787                 }
4788
4789                 internal override object StartLoop(Thread thread) {
4790                         return (Object) ThreadQueue(thread);
4791                 }
4792
4793                 internal override bool SupportsTransparency() {
4794                         // We need to check if the x compositing manager is running
4795                         return true;
4796                 }
4797
4798                 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
4799                         GetSystrayManagerWindow();
4800
4801                         if (SystrayMgrWindow != IntPtr.Zero) {
4802                                 XSizeHints      size_hints;
4803                                 Hwnd            hwnd;
4804
4805                                 hwnd = Hwnd.ObjectFromHandle(handle);
4806                                 #if DriverDebug
4807                                         Console.WriteLine("Adding Systray Whole:{0:X}, Client:{1:X}", hwnd.whole_window.ToInt32(), hwnd.client_window.ToInt32());
4808                                 #endif
4809
4810                                 // Oh boy.
4811                                 if (hwnd.client_window != hwnd.whole_window) {
4812                                         XDestroyWindow(DisplayHandle, hwnd.client_window);
4813                                         hwnd.client_window = hwnd.whole_window;
4814
4815                                         /* by virtue of the way the tests are ordered when determining if it's PAINT
4816                                            or NCPAINT, client_window == whole_window will always be PAINT.  So, if we're
4817                                            waiting on an nc_expose, drop it and remove the hwnd from the list (unless
4818                                            there's a pending expose). */
4819                                         if (hwnd.nc_expose_pending) {
4820                                                 hwnd.nc_expose_pending = false;
4821                                                 if (!hwnd.expose_pending)
4822                                                         hwnd.Queue.Paint.Remove (hwnd);
4823                                         }
4824                                 }
4825
4826                                 size_hints = new XSizeHints();
4827
4828                                 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
4829
4830                                 size_hints.min_width = 24;
4831                                 size_hints.min_height = 24;
4832                                 size_hints.max_width = 24;
4833                                 size_hints.max_height = 24;
4834                                 size_hints.base_width = 24;
4835                                 size_hints.base_height = 24;
4836
4837                                 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
4838
4839                                 int[] atoms = new int[2];
4840                                 atoms [0] = 1;                  // Version 1
4841                                 atoms [1] = 1;                  // we want to be mapped
4842
4843                                 // This line cost me 3 days...
4844                                 XChangeProperty(DisplayHandle, hwnd.whole_window, _XEMBED_INFO, _XEMBED_INFO, 32, PropertyMode.Replace, atoms, 2);
4845
4846                                 // Need to pick some reasonable defaults
4847                                 tt = new ToolTip();
4848                                 tt.AutomaticDelay = 100;
4849                                 tt.InitialDelay = 250;
4850                                 tt.ReshowDelay = 250;
4851                                 tt.ShowAlways = true;
4852
4853                                 if ((tip != null) && (tip != string.Empty)) {
4854                                         tt.SetToolTip(Control.FromHandle(handle), tip);
4855                                         tt.Active = true;
4856                                 } else {
4857                                         tt.Active = false;
4858                                 }
4859
4860                                 SendNetClientMessage(SystrayMgrWindow, _NET_SYSTEM_TRAY_OPCODE, IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
4861
4862                                 return true;
4863                         }
4864                         tt = null;
4865                         return false;
4866                 }
4867
4868                 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
4869                         Control control;
4870
4871                         control = Control.FromHandle(handle);
4872                         if (control != null && tt != null) {
4873                                 tt.SetToolTip(control, tip);
4874                                 tt.Active = true;
4875                                 return true;
4876                         } else {
4877                                 return false;
4878                         }
4879                 }
4880
4881                 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
4882
4883 #if GTKSOCKET_SUPPORTS_REPARENTING
4884                         Hwnd    hwnd;
4885
4886                         hwnd = Hwnd.ObjectFromHandle(handle);
4887
4888                         /* in the XEMBED spec, it mentions 3 ways for a client window to break the protocol with the embedder.
4889                          * 1. The embedder can unmap the window and reparent to the root window (we should probably handle this...)
4890                          * 2. The client can reparent its window out of the embedder window.
4891                          * 3. The client can destroy its window.
4892                          *
4893                          * this call to SetParent is case 2, but in
4894                          * the spec it also mentions that gtk doesn't
4895                          * support this at present.  Looking at HEAD
4896                          * gtksocket-x11.c jives with this statement.
4897                          *
4898                          * so we can't reparent.  we have to destroy.
4899                          */
4900                         SetParent(hwnd.whole_window, FosterParent);
4901 #else
4902                         Control control = Control.FromHandle(handle);
4903                         if (control is NotifyIcon.NotifyIconWindow)
4904                                 ((NotifyIcon.NotifyIconWindow)control).InternalRecreateHandle ();
4905 #endif
4906
4907                         // The caller can now re-dock it later...
4908                         if (tt != null) {
4909                                 tt.Dispose();
4910                                 tt = null;
4911                         }
4912                 }
4913
4914                 internal override bool Text(IntPtr handle, string text) {
4915                         lock (XlibLock) {
4916                                 // FIXME - use _NET properties
4917                                 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
4918                         }
4919                         return true;
4920                 }
4921
4922                 internal override bool TranslateMessage(ref MSG msg) {
4923                         return Keyboard.TranslateMessage (ref msg);
4924                 }
4925
4926                 internal override void UpdateWindow(IntPtr handle) {
4927                         Hwnd    hwnd;
4928
4929                         hwnd = Hwnd.ObjectFromHandle(handle);
4930
4931                         if (!hwnd.visible || !hwnd.expose_pending || !hwnd.Mapped) {
4932                                 return;
4933                         }
4934
4935                         SendMessage(handle, Msg.WM_PAINT, IntPtr.Zero, IntPtr.Zero);
4936                         hwnd.Queue.Paint.Remove(hwnd);
4937                 }
4938
4939                 #endregion      // Public Static Methods
4940
4941                 #region Events
4942                 internal override event EventHandler Idle;
4943                 #endregion      // Events
4944
4945                 #region X11 Imports
4946                 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
4947                 internal extern static IntPtr XOpenDisplay(IntPtr display);
4948                 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
4949                 internal extern static int XCloseDisplay(IntPtr display);                                                   
4950                 [DllImport ("libX11", EntryPoint="XSynchronize")]
4951                 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
4952
4953                 [DllImport ("libX11", EntryPoint="XCreateWindow")]
4954                 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);
4955                 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
4956                 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, UIntPtr border, UIntPtr background);
4957                 [DllImport ("libX11", EntryPoint="XMapWindow")]
4958                 internal extern static int XMapWindow(IntPtr display, IntPtr window);
4959                 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
4960                 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
4961                 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
4962                 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
4963                 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
4964                 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
4965                 [DllImport ("libX11", EntryPoint="XRootWindow")]
4966                 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
4967                 [DllImport ("libX11", EntryPoint="XNextEvent")]
4968                 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
4969                 [DllImport ("libX11")]
4970                 internal extern static int XConnectionNumber (IntPtr diplay);
4971                 [DllImport ("libX11")]
4972                 internal extern static int XPending (IntPtr diplay);
4973                 [DllImport ("libX11", EntryPoint="XSelectInput")]
4974                 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, IntPtr mask);
4975
4976                 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
4977                 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
4978
4979                 [DllImport ("libX11", EntryPoint="XReparentWindow")]
4980                 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
4981                 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
4982                 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
4983
4984                 [DllImport ("libX11", EntryPoint="XResizeWindow")]
4985                 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
4986
4987                 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
4988                 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
4989
4990                 [DllImport ("libX11", EntryPoint="XFlush")]
4991                 internal extern static int XFlush(IntPtr display);
4992
4993                 [DllImport ("libX11", EntryPoint="XSetWMName")]
4994                 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
4995
4996                 [DllImport ("libX11", EntryPoint="XStoreName")]
4997                 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
4998
4999                 [DllImport ("libX11", EntryPoint="XFetchName")]
5000                 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
5001
5002                 [DllImport ("libX11", EntryPoint="XSendEvent")]
5003                 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, IntPtr event_mask, ref XEvent send_event);
5004
5005                 [DllImport ("libX11", EntryPoint="XQueryTree")]
5006                 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);
5007
5008                 [DllImport ("libX11", EntryPoint="XFree")]
5009                 internal extern static int XFree(IntPtr data);
5010
5011                 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
5012                 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
5013
5014                 [DllImport ("libX11", EntryPoint="XLowerWindow")]
5015                 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
5016
5017                 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
5018                 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
5019
5020                 [DllImport ("libX11", EntryPoint="XInternAtom")]
5021                 internal extern static IntPtr XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
5022
5023                 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
5024                 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, IntPtr[] protocols, int count);
5025
5026                 [DllImport ("libX11", EntryPoint="XGrabPointer")]
5027                 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);
5028
5029                 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
5030                 internal extern static int XUngrabPointer(IntPtr display, IntPtr timestamp);
5031
5032                 [DllImport ("libX11", EntryPoint="XQueryPointer")]
5033                 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);
5034
5035                 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
5036                 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);
5037
5038                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5039                 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);
5040
5041                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5042                 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);
5043
5044                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5045                 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);
5046
5047                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
5048                 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);
5049
5050                 [DllImport ("libX11", EntryPoint="XWarpPointer")]
5051                 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);
5052
5053                 [DllImport ("libX11", EntryPoint="XClearWindow")]
5054                 internal extern static int XClearWindow(IntPtr display, IntPtr window);
5055
5056                 [DllImport ("libX11", EntryPoint="XClearArea")]
5057                 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
5058
5059                 // Colormaps
5060                 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
5061                 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
5062
5063                 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
5064                 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
5065
5066                 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
5067                 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
5068
5069                 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
5070                 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
5071
5072                 [DllImport ("libX11", EntryPoint="XDefaultScreen")]
5073                 internal extern static int XDefaultScreen(IntPtr display);
5074
5075                 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
5076                 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
5077
5078                 [DllImport ("libX11", EntryPoint="XLookupColor")]
5079                 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
5080
5081                 [DllImport ("libX11", EntryPoint="XAllocColor")]
5082                 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
5083
5084                 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
5085                 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
5086
5087                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5088                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
5089
5090                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5091                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref uint value, int nelements);
5092
5093                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5094                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, ref IntPtr value, int nelements);
5095
5096                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5097                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, uint[] data, int nelements);
5098
5099                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5100                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, int[] data, int nelements);
5101
5102                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5103                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr[] data, int nelements);
5104
5105                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
5106                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, IntPtr atoms, int nelements);
5107
5108                 [DllImport ("libX11", EntryPoint="XChangeProperty", CharSet=CharSet.Ansi)]
5109                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, PropertyMode mode, string text, int text_length);
5110
5111                 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
5112                 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
5113
5114                 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
5115                 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
5116
5117                 // Drawing
5118                 [DllImport ("libX11", EntryPoint="XCreateGC")]
5119                 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, IntPtr valuemask, ref XGCValues values);
5120
5121                 [DllImport ("libX11", EntryPoint="XFreeGC")]
5122                 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
5123
5124                 [DllImport ("libX11", EntryPoint="XSetFunction")]
5125                 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
5126
5127                 [DllImport ("libX11", EntryPoint="XDrawLine")]
5128                 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
5129
5130                 [DllImport ("libX11", EntryPoint="XDrawRectangle")]
5131                 internal extern static int XDrawRectangle(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int width, int height);
5132
5133                 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
5134                 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
5135
5136                 [DllImport ("libX11", EntryPoint="XCopyArea")]
5137                 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);
5138
5139                 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
5140                 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);
5141
5142                 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
5143                 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
5144
5145                 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
5146                 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
5147
5148                 [DllImport ("libX11", EntryPoint="XDefineCursor")]
5149                 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
5150
5151                 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
5152                 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
5153
5154                 [DllImport ("libX11", EntryPoint="XFreeCursor")]
5155                 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
5156
5157                 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
5158                 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
5159
5160                 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
5161                 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);
5162
5163                 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
5164                 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
5165
5166                 [DllImport ("libX11", EntryPoint="XFreePixmap")]
5167                 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
5168
5169                 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
5170                 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
5171
5172                 [DllImport ("libX11", EntryPoint="XWhitePixel")]
5173                 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
5174
5175                 [DllImport ("libX11", EntryPoint="XBlackPixel")]
5176                 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
5177
5178                 [DllImport ("libX11", EntryPoint="XGrabServer")]
5179                 internal extern static void XGrabServer(IntPtr display);
5180
5181                 [DllImport ("libX11", EntryPoint="XUngrabServer")]
5182                 internal extern static void XUngrabServer(IntPtr display);
5183
5184                 [DllImport ("libX11", EntryPoint="XGetWMNormalHints")]
5185                 internal extern static void XGetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints, out IntPtr supplied_return);
5186
5187                 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
5188                 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5189
5190                 [DllImport ("libX11", EntryPoint="XSetZoomHints")]
5191                 internal extern static void XSetZoomHints(IntPtr display, IntPtr window, ref XSizeHints hints);
5192
5193                 [DllImport ("libX11", EntryPoint="XSetWMHints")]
5194                 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
5195
5196                 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
5197                 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
5198
5199                 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
5200                 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
5201
5202                 [DllImport ("libX11", EntryPoint="XGetErrorText")]
5203                 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
5204
5205                 [DllImport ("libX11", EntryPoint="XInitThreads")]
5206                 internal extern static int XInitThreads();
5207
5208                 [DllImport ("libX11", EntryPoint="XConvertSelection")]
5209                 internal extern static int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, IntPtr time);
5210
5211                 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
5212                 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
5213
5214                 [DllImport ("libX11", EntryPoint="XSetSelectionOwner")]
5215                 internal extern static int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, IntPtr time);
5216
5217                 [DllImport ("libX11", EntryPoint="XSetPlaneMask")]
5218                 internal extern static int XSetPlaneMask(IntPtr display, IntPtr gc, IntPtr mask);
5219
5220                 [DllImport ("libX11", EntryPoint="XSetForeground")]
5221                 internal extern static int XSetForeground(IntPtr display, IntPtr gc, UIntPtr foreground);
5222
5223                 [DllImport ("libX11", EntryPoint="XSetBackground")]
5224                 internal extern static int XSetBackground(IntPtr display, IntPtr gc, UIntPtr background);
5225
5226                 [DllImport ("libX11", EntryPoint="XBell")]
5227                 internal extern static int XBell(IntPtr display, int percent);
5228
5229                 [DllImport ("libX11", EntryPoint="XChangeActivePointerGrab")]
5230                 internal extern static int XChangeActivePointerGrab (IntPtr display, EventMask event_mask, IntPtr cursor, IntPtr time);
5231
5232                 [DllImport ("libX11", EntryPoint="XFilterEvent")]
5233                 internal extern static bool XFilterEvent(ref XEvent xevent, IntPtr window);
5234
5235                 [DllImport ("libX11")]
5236                 internal extern static void XkbSetDetectableAutoRepeat (IntPtr display, bool detectable, IntPtr supported);
5237
5238                 [DllImport ("libX11")]
5239                 internal extern static void XPeekEvent (IntPtr display, ref XEvent xevent);
5240                 #endregion
5241         }
5242 }