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