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