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