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