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