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