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