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