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