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