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