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