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