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