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