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