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