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