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