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