* ImageList.cs: When the image stream is set pull all the images
[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-2005 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
45 using System;
46 using System.ComponentModel;
47 using System.Collections;
48 using System.Diagnostics;
49 using System.Drawing;
50 using System.Drawing.Imaging;
51 using System.IO;
52 using System.Net;
53 using System.Net.Sockets;
54 using System.Reflection;
55 using System.Runtime.InteropServices;
56 using System.Text;
57 using System.Threading;
58
59 // Only do the poll when building with mono for now
60 #if __MonoCS__
61 using Mono.Unix;
62 #endif
63
64 /// X11 Version
65 namespace System.Windows.Forms {
66         internal class XplatUIX11 : XplatUIDriver {
67                 #region Local Variables
68                 // General
69                 private static XplatUIX11       Instance;
70                 private static int              RefCount;
71                 private static object           XlibLock;               // Our locking object
72                 private static bool             ThemesEnabled;
73
74                 // General X11
75                 private static IntPtr           DisplayHandle;          // X11 handle to display
76                 private static int              ScreenNo;               // Screen number used
77                 private static IntPtr           DefaultColormap;        // Colormap for screen
78                 private static IntPtr           RootWindow;             // Handle of the root window for the screen/display
79                 private static IntPtr           FosterParent;           // Container to hold child windows until their parent exists
80                 private static XErrorHandler    ErrorHandler;           // Error handler delegate
81                 private static bool             ErrorExceptions;        // Throw exceptions on X errors
82
83                 // Communication
84                 private static int              PostAtom;               // PostMessage atom
85                 private static int              AsyncAtom;              // Support for async messages
86
87                 // Message Loop
88                 private static bool             GetMessageResult;       // Value returned by GetMessage()
89                 private static XEventQueue      MessageQueue;           // Holds our queued up events
90                 #if __MonoCS__                                          //
91                 private static Pollfd[]         pollfds;                // For watching the X11 socket
92                 #endif                                                  //
93                 private static X11Keyboard      Keyboard;               //
94                 private static Socket           listen;                 //
95                 private static Socket           wake;                   //
96
97
98                 // Focus tracking
99                 private static IntPtr           ActiveWindow;           // Handle of the active window
100                 private static IntPtr           FocusWindow;            // Handle of the window with keyboard focus (if any)
101
102                 // Modality support
103                 private static Stack            ModalWindows;           // Stack of our modal windows
104
105                 // Systray
106                 private static IntPtr           SystrayMgrWindow;       // Handle of the Systray Manager window
107
108                 // Cursors
109                 private static IntPtr           LastCursorWindow;       // The last window we set the cursor on
110                 private static IntPtr           LastCursorHandle;       // The handle that was last set on LastCursorWindow
111                 private static IntPtr           OverrideCursorHandle;   // The cursor that is set to override any other cursors
112
113                 // Caret
114                 private static CaretStruct      Caret;                  //
115
116                 // Support for Window Styles
117                 private static int[]            NetAtoms;               // All atoms we know
118
119                 // mouse hover message generation
120                 private static HoverStruct      HoverState;             //
121
122                 // double click message generation
123                 private static ClickStruct      ClickPending;           //
124
125                 // Support for mouse grab
126                 private static GrabStruct       Grab;                   //
127
128                 // State
129                 private static Point            MousePosition;          // Last position of mouse, in screen coords
130                 private static MouseButtons     MouseState;             // Last state of mouse buttons
131
132                 // Timers
133                 private static ArrayList        TimerList;              // Holds SWF.Timers
134
135                 // 'Constants'
136                 private static int              DoubleClickInterval;    // msec; max interval between clicks to count as double click
137
138                 private static readonly EventMask  SelectInputMask =    EventMask.ButtonPressMask | 
139                                                                         EventMask.ButtonReleaseMask | 
140                                                                         EventMask.KeyPressMask | 
141                                                                         EventMask.KeyReleaseMask | 
142                                                                         EventMask.EnterWindowMask | 
143                                                                         EventMask.LeaveWindowMask |
144                                                                         EventMask.ExposureMask |
145                                                                         EventMask.FocusChangeMask |
146                                                                         EventMask.PointerMotionMask | 
147                                                                         EventMask.VisibilityChangeMask |
148                                                                         EventMask.SubstructureNotifyMask |
149                                                                         EventMask.StructureNotifyMask;
150                 #endregion      // Local Variables
151
152                 #region Constructors
153                 private XplatUIX11() {
154                         // Handle singleton stuff first
155                         RefCount = 0;
156
157                         // Now regular initialization
158                         XlibLock = new object ();
159                         MessageQueue = new XEventQueue ();
160                         TimerList = new ArrayList ();
161                         XInitThreads();\r
162
163                         ErrorExceptions = false;
164
165                         // X11 Initialization
166                         SetDisplay(XOpenDisplay(IntPtr.Zero));
167                 }
168
169                 ~XplatUIX11() {
170                         lock (this) {
171                                 if (DisplayHandle!=IntPtr.Zero) {
172                                         XCloseDisplay(DisplayHandle);
173                                         DisplayHandle=IntPtr.Zero;
174                                 }
175                         }
176                 }
177                 #endregion      // Constructors
178
179                 #region Singleton Specific Code
180                 public static XplatUIX11 GetInstance() {
181                         lock (typeof(XplatUIX11)) {
182                                 if (Instance == null) {
183                                         Instance=new XplatUIX11();
184                                 }
185                                 RefCount++;
186                         }
187                         return Instance;
188                 }
189
190                 public int Reference {
191                         get {
192                                 return RefCount;
193                         }
194                 }
195                 #endregion
196
197                 #region XExceptionClass
198                 internal class XException : ApplicationException {
199                         IntPtr          Display;
200                         IntPtr          ResourceID;
201                         IntPtr          Serial;
202                         XRequest        RequestCode;
203                         byte            ErrorCode;
204                         byte            MinorCode;
205
206                         public XException(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
207                                 this.Display = Display;
208                                 this.ResourceID = ResourceID;
209                                 this.Serial = Serial;
210                                 this.RequestCode = RequestCode;
211                                 this.ErrorCode = ErrorCode;
212                                 this.MinorCode = MinorCode;
213                         }
214
215                         public override string Message {
216                                 get {
217                                         return GetMessage(Display, ResourceID, Serial, ErrorCode, RequestCode, MinorCode);
218                                 }
219                         }
220
221                         public static string GetMessage(IntPtr Display, IntPtr ResourceID, IntPtr Serial, byte ErrorCode, XRequest RequestCode, byte MinorCode) {
222                                 StringBuilder   sb;
223                                 string          x_error_text;
224                                 string          error;
225
226                                 sb = new StringBuilder(160);
227                                 XGetErrorText(Display, ErrorCode, sb, sb.Capacity);
228                                 x_error_text = sb.ToString();
229
230                                 error = String.Format("\n  Error: {0}\n  Request:     {1:D} ({2})\n  Resource ID: 0x{3:x}\n  Serial:      {4}", x_error_text, RequestCode, RequestCode, ResourceID.ToInt32(), Serial);
231                                 return error;
232                         }
233                 }
234                 #endregion      // XExceptionClass
235
236                 #region Internal Methods
237                 internal void SetDisplay(IntPtr display_handle) {
238                         if (display_handle != IntPtr.Zero) {
239                                 if ((DisplayHandle != IntPtr.Zero) && (FosterParent != IntPtr.Zero)) {
240                                         XDestroyWindow(DisplayHandle, FosterParent);
241                                 }
242
243                                 if (DisplayHandle != IntPtr.Zero) {
244                                         XCloseDisplay(DisplayHandle);
245                                 }
246
247                                 DisplayHandle=display_handle;
248
249                                 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
250                                 // been hacked to do this for us.
251                                 Graphics.FromHdcInternal (DisplayHandle);
252
253                                 // Debugging support
254                                 if (Environment.GetEnvironmentVariable ("MONO_XSYNC") != null) {
255                                         XSynchronize(DisplayHandle, true);
256                                 }
257
258                                 if (Environment.GetEnvironmentVariable ("MONO_XEXCEPTIONS") != null) {
259                                         ErrorExceptions = true;
260                                 }
261
262                                 // Generic X11 setup
263                                 ScreenNo = 0;
264                                 RootWindow = XRootWindow(DisplayHandle, ScreenNo);
265                                 DefaultColormap = XDefaultColormap(DisplayHandle, ScreenNo);
266
267                                 // Create the foster parent
268                                 FosterParent=XCreateSimpleWindow(DisplayHandle, RootWindow, 0, 0, 1, 1, 4, 0, 0);
269                                 if (FosterParent==IntPtr.Zero) {
270                                         Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
271                                 }
272
273
274                                 // For sleeping on the X11 socket
275                                 listen = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
276                                 IPEndPoint ep = new IPEndPoint(IPAddress.Loopback, 0);
277                                 listen.Bind(ep);
278                                 listen.Listen(1);
279
280                                 // To wake up when a timer is ready
281                                 wake = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
282                                 wake.Connect(listen.LocalEndPoint);
283
284                                 #if __MonoCS__
285                                 pollfds = new Pollfd [2];
286                                 pollfds [0] = new Pollfd ();
287                                 pollfds [0].fd = XConnectionNumber (DisplayHandle);
288                                 pollfds [0].events = PollEvents.POLLIN;
289
290                                 pollfds [1] = new Pollfd ();
291                                 pollfds [1].fd = wake.Handle.ToInt32 ();
292                                 pollfds [1].events = PollEvents.POLLIN;
293                                 #endif
294
295                                 Keyboard = new X11Keyboard(DisplayHandle);
296
297                                 GetMessageResult = true;
298
299                                 DoubleClickInterval = 500;
300
301                                 HoverState.Interval = 500;
302                                 HoverState.Timer = new Timer();
303                                 HoverState.Timer.Enabled = false;
304                                 HoverState.Timer.Interval = HoverState.Interval;
305                                 HoverState.Timer.Tick +=new EventHandler(MouseHover);
306                                 HoverState.X = -1;
307                                 HoverState.Y = -1;
308
309                                 ActiveWindow = IntPtr.Zero;
310                                 FocusWindow = IntPtr.Zero;
311                                 ModalWindows = new Stack(3);
312
313                                 MouseState = MouseButtons.None;
314                                 MousePosition = new Point(0, 0);
315
316                                 Caret.Timer = new Timer();
317                                 Caret.Timer.Interval = 500;             // FIXME - where should this number come from?
318                                 Caret.Timer.Tick += new EventHandler(CaretCallback);
319
320                                 SetupAtoms();
321
322                                 // Grab atom changes off the root window to catch certain WM events
323                                 XSelectInput(DisplayHandle, RootWindow, EventMask.PropertyChangeMask);
324
325                                 // Handle any upcoming errors
326                                 ErrorHandler = new XErrorHandler(HandleError);
327                                 XSetErrorHandler(ErrorHandler);
328                         } else {
329                                 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
330                         }
331                 }
332
333                 internal static void Where() {
334                         Console.WriteLine("Here: {0}\n", WhereString());
335                 }
336
337                 internal static string WhereString() {
338                         StackTrace      stack;
339                         StackFrame      frame;
340                         string          newline;
341                         string          unknown;
342                         StringBuilder   sb;
343                         MethodBase      method;
344
345                         newline = String.Format("{0}\t {1} ", Environment.NewLine, Locale.GetText("at"));
346                         unknown = Locale.GetText("<unknown method>");
347                         sb = new StringBuilder();
348                         stack = new StackTrace(true);
349
350                         for (int i = 0; i < stack.FrameCount; i++) {
351                                 frame = stack.GetFrame(i);
352                                 sb.Append(newline);
353
354                                 method = frame.GetMethod();
355                                 if (method != null) {
356                                         #if not
357                                                 sb.AppendFormat(frame.ToString());
358                                         #endif
359                                         if (frame.GetFileLineNumber() != 0) {
360                                                 sb.AppendFormat("{0}.{1} () [{2}:{3}]", method.DeclaringType.FullName, method.Name, Path.GetFileName(frame.GetFileName()), frame.GetFileLineNumber());
361                                         } else {
362                                                 sb.AppendFormat("{0}.{1} ()", method.DeclaringType.FullName, method.Name);
363                                         }
364                                 } else { 
365                                         sb.Append(unknown);
366                                 }
367                         }
368                         return sb.ToString();
369                 }
370                 #endregion      // Internal Methods
371
372                 #region Private Methods
373                 private static void SetupAtoms() {
374                         NetAtoms = new int[(int)NA.LAST_NET_ATOM];
375
376                         NetAtoms[(int)NA.WM_PROTOCOLS] = XInternAtom(DisplayHandle, "WM_PROTOCOLS", false);
377                         NetAtoms[(int)NA.WM_DELETE_WINDOW] = XInternAtom(DisplayHandle, "WM_DELETE_WINDOW", false);
378                         NetAtoms[(int)NA.WM_TAKE_FOCUS] = XInternAtom(DisplayHandle, "WM_TAKE_FOCUS", false);
379
380                         NetAtoms[(int)NA._NET_SUPPORTED] = XInternAtom(DisplayHandle, "_NET_SUPPORTED", false);
381                         NetAtoms[(int)NA._NET_CLIENT_LIST] = XInternAtom(DisplayHandle, "_NET_CLIENT_LIST", false);
382                         NetAtoms[(int)NA._NET_NUMBER_OF_DESKTOPS] = XInternAtom(DisplayHandle, "_NET_NUMBER_OF_DESKTOPS", false);
383                         NetAtoms[(int)NA._NET_DESKTOP_GEOMETRY] = XInternAtom(DisplayHandle, "_NET_DESKTOP_GEOMETRY", false);
384                         NetAtoms[(int)NA._NET_DESKTOP_VIEWPORT] = XInternAtom(DisplayHandle, "_NET_DESKTOP_VIEWPORT", false);
385                         NetAtoms[(int)NA._NET_CURRENT_DESKTOP] = XInternAtom(DisplayHandle, "_NET_CURRENT_DESKTOP", false);
386                         NetAtoms[(int)NA._NET_DESKTOP_NAMES] = XInternAtom(DisplayHandle, "_NET_DESKTOP_NAMES", false);
387                         NetAtoms[(int)NA._NET_ACTIVE_WINDOW] = XInternAtom(DisplayHandle, "_NET_ACTIVE_WINDOW", false);
388                         NetAtoms[(int)NA._NET_WORKAREA] = XInternAtom(DisplayHandle, "_NET_WORKAREA", false);
389                         NetAtoms[(int)NA._NET_SUPPORTING_WM_CHECK] = XInternAtom(DisplayHandle, "_NET_SUPPORTING_WM_CHECK", false);
390                         NetAtoms[(int)NA._NET_VIRTUAL_ROOTS] = XInternAtom(DisplayHandle, "_NET_VIRTUAL_ROOTS", false);
391                         NetAtoms[(int)NA._NET_DESKTOP_LAYOUT] = XInternAtom(DisplayHandle, "_NET_DESKTOP_LAYOUT", false);
392                         NetAtoms[(int)NA._NET_SHOWING_DESKTOP] = XInternAtom(DisplayHandle, "_NET_SHOWING_DESKTOP", false);
393
394                         NetAtoms[(int)NA._NET_CLOSE_WINDOW] = XInternAtom(DisplayHandle, "_NET_CLOSE_WINDOW", false);
395                         NetAtoms[(int)NA._NET_MOVERESIZE_WINDOW] = XInternAtom(DisplayHandle, "_NET_MOVERESIZE_WINDOW", false);
396                         NetAtoms[(int)NA._NET_WM_MOVERESIZE] = XInternAtom(DisplayHandle, "_NET_WM_MOVERESIZE", false);
397                         NetAtoms[(int)NA._NET_RESTACK_WINDOW] = XInternAtom(DisplayHandle, "_NET_RESTACK_WINDOW", false);
398                         NetAtoms[(int)NA._NET_REQUEST_FRAME_EXTENTS] = XInternAtom(DisplayHandle, "_NET_REQUEST_FRAME_EXTENTS", false);
399
400                         NetAtoms[(int)NA._NET_WM_NAME] = XInternAtom(DisplayHandle, "_NET_WM_NAME", false);
401                         NetAtoms[(int)NA._NET_WM_VISIBLE_NAME] = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_NAME", false);
402                         NetAtoms[(int)NA._NET_WM_ICON_NAME] = XInternAtom(DisplayHandle, "_NET_WM_ICON_NAME", false);
403                         NetAtoms[(int)NA._NET_WM_VISIBLE_ICON_NAME] = XInternAtom(DisplayHandle, "_NET_WM_VISIBLE_ICON_NAME", false);
404                         NetAtoms[(int)NA._NET_WM_DESKTOP] = XInternAtom(DisplayHandle, "_NET_WM_DESKTOP", false);
405                         NetAtoms[(int)NA._NET_WM_WINDOW_TYPE] = XInternAtom(DisplayHandle, "_NET_WM_WINDOW_TYPE", false);
406                         NetAtoms[(int)NA._NET_WM_STATE] = XInternAtom(DisplayHandle, "_NET_WM_STATE", false);
407                         NetAtoms[(int)NA._NET_WM_ALLOWED_ACTIONS] = XInternAtom(DisplayHandle, "_NET_WM_ALLOWED_ACTIONS", false);
408                         NetAtoms[(int)NA._NET_WM_STRUT] = XInternAtom(DisplayHandle, "_NET_WM_STRUT", false);
409                         NetAtoms[(int)NA._NET_WM_STRUT_PARTIAL] = XInternAtom(DisplayHandle, "_NET_WM_STRUT_PARTIAL", false);
410                         NetAtoms[(int)NA._NET_WM_ICON_GEOMETRY] = XInternAtom(DisplayHandle, "_NET_WM_ICON_GEOMETRY", false);
411                         NetAtoms[(int)NA._NET_WM_ICON] = XInternAtom(DisplayHandle, "_NET_WM_ICON", false);
412                         NetAtoms[(int)NA._NET_WM_PID] = XInternAtom(DisplayHandle, "_NET_WM_PID", false);
413                         NetAtoms[(int)NA._NET_WM_HANDLED_ICONS] = XInternAtom(DisplayHandle, "_NET_WM_HANDLED_ICONS", false);
414                         NetAtoms[(int)NA._NET_WM_USER_TIME] = XInternAtom(DisplayHandle, "_NET_WM_USER_TIME", false);
415                         NetAtoms[(int)NA._NET_FRAME_EXTENTS] = XInternAtom(DisplayHandle, "_NET_FRAME_EXTENTS", false);
416
417                         NetAtoms[(int)NA._NET_WM_PING] = XInternAtom(DisplayHandle, "_NET_WM_PING", false);
418                         NetAtoms[(int)NA._NET_WM_SYNC_REQUEST] = XInternAtom(DisplayHandle, "_NET_WM_SYNC_REQUEST", false);
419
420                         NetAtoms[(int)NA._NET_SYSTEM_TRAY_S] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_S" + ScreenNo.ToString(), false);
421                         NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_OPCODE", false);
422                         NetAtoms[(int)NA._NET_SYSTEM_TRAY_ORIENTATION] = XInternAtom(DisplayHandle, "_NET_SYSTEM_TRAY_ORIENTATION", false);
423
424                         NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_HORZ", false);
425                         NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MAXIMIZED_VERT", false);
426
427                         NetAtoms[(int)NA._XEMBED] = XInternAtom(DisplayHandle, "_XEMBED", false);
428                         NetAtoms[(int)NA._XEMBED_INFO] = XInternAtom(DisplayHandle, "_XEMBED_INFO", false);
429
430                         NetAtoms[(int)NA._MOTIF_WM_HINTS] = XInternAtom(DisplayHandle, "_MOTIF_WM_HINTS", false);
431
432                         NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR] = XInternAtom(DisplayHandle, "_NET_WM_STATE_NO_TASKBAR", false);
433                         NetAtoms[(int)NA._NET_WM_STATE_ABOVE] = XInternAtom(DisplayHandle, "_NET_WM_STATE_ABOVE", false);
434                         NetAtoms[(int)NA._NET_WM_STATE_MODAL] = XInternAtom(DisplayHandle, "_NET_WM_STATE_MODAL", false);
435                         NetAtoms[(int)NA._NET_WM_CONTEXT_HELP] = XInternAtom(DisplayHandle, "_NET_WM_CONTEXT_HELP", false);
436
437                         // Special Atoms
438                         AsyncAtom = XInternAtom(DisplayHandle, "_SWF_AsyncAtom", false);
439                         PostAtom = XInternAtom (DisplayHandle, "_SWF_PostMessageAtom", false);
440                         HoverState.Atom = XInternAtom(DisplayHandle, "_SWF_HoverAtom", false);
441                 }
442
443                 private void GetSystrayManagerWindow() {
444                         XGrabServer(DisplayHandle);
445                         SystrayMgrWindow = XGetSelectionOwner(DisplayHandle, (IntPtr)NetAtoms[(int)NA._NET_SYSTEM_TRAY_S]);
446                         XUngrabServer(DisplayHandle);
447                         XFlush(DisplayHandle);
448                 }
449
450                 private void SendNetWMMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
451                         XEvent  xev;
452
453                         xev = new XEvent();
454                         xev.ClientMessageEvent.type = XEventName.ClientMessage;
455                         xev.ClientMessageEvent.send_event = true;
456                         xev.ClientMessageEvent.window = window;
457                         xev.ClientMessageEvent.message_type = message_type;
458                         xev.ClientMessageEvent.format = 32;
459                         xev.ClientMessageEvent.ptr1 = l0;
460                         xev.ClientMessageEvent.ptr2 = l1;
461                         xev.ClientMessageEvent.ptr3 = l2;
462                         XSendEvent(DisplayHandle, RootWindow, false, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xev);
463                 }
464
465                 private void SendNetClientMessage(IntPtr window, IntPtr message_type, IntPtr l0, IntPtr l1, IntPtr l2) {
466                         XEvent  xev;
467
468                         xev = new XEvent();
469                         xev.ClientMessageEvent.type = XEventName.ClientMessage;
470                         xev.ClientMessageEvent.send_event = true;
471                         xev.ClientMessageEvent.window = window;
472                         xev.ClientMessageEvent.message_type = message_type;
473                         xev.ClientMessageEvent.format = 32;
474                         xev.ClientMessageEvent.ptr1 = l0;
475                         xev.ClientMessageEvent.ptr2 = l1;
476                         xev.ClientMessageEvent.ptr3 = l2;
477                         XSendEvent(DisplayHandle, window, false, EventMask.NoEventMask, ref xev);
478                 }
479
480                 private void SetHwndStyles(Hwnd hwnd, CreateParams cp) {
481                         if ((cp.Style & (int)WindowStyles.WS_CHILD) != 0) {
482                                 if ((cp.Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
483                                         hwnd.BorderStyle = BorderStyle.Fixed3D;
484                                 } else if ((cp.Style & (int)WindowStyles.WS_BORDER) != 0) {
485                                         hwnd.BorderStyle = BorderStyle.FixedSingle;
486                                 }
487                         }
488
489                         if ((cp.ExStyle & (int)WindowStyles.WS_EX_CLIENTEDGE) != 0) {
490                                 hwnd.edge_style = Border3DStyle.Sunken;
491                         } else if ((cp.ExStyle & (int)WindowStyles.WS_EX_STATICEDGE) != 0) {
492                                 hwnd.edge_style = Border3DStyle.Flat;
493                         } else if ((cp.ExStyle & (int)WindowStyles.WS_EX_WINDOWEDGE) != 0) {
494                                 hwnd.edge_style = Border3DStyle.Raised;
495                         } else if ((cp.ExStyle & (int)WindowStyles.WS_EX_WINDOWEDGE) != 0) {
496                                 hwnd.edge_style = Border3DStyle.Raised;
497                         }
498
499                         if ((cp.Style & (int)WindowStyles.WS_CAPTION) != 0) {
500                                 if ((cp.ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
501                                         hwnd.title_style = TitleStyle.Tool;
502                                 } else {
503                                         hwnd.title_style = TitleStyle.Normal;
504                                 }
505                         }
506                 }
507
508                 private void SetWMStyles(Hwnd hwnd, CreateParams cp) {
509                         MotifWmHints            mwmHints;
510                         MotifFunctions          functions;
511                         MotifDecorations        decorations;
512                         uint[]                  atoms;
513                         int                     atom_count;
514                         Rectangle               client_rect;
515
516                         mwmHints = new MotifWmHints();
517                         functions = 0;
518                         decorations = 0;
519
520                         mwmHints.flags = (IntPtr)(MotifFlags.Functions | MotifFlags.Decorations);
521                         mwmHints.functions = (IntPtr)0;
522                         mwmHints.decorations = (IntPtr)0;
523
524                         if ((cp.Style & (int)WindowStyles.WS_CAPTION) != 0) {
525                                 functions |= MotifFunctions.Move;
526                                 decorations |= MotifDecorations.Title | MotifDecorations.Menu;
527                         }
528
529                         if ((cp.Style & ((int)WindowStyles.WS_THICKFRAME)) != 0) {
530                                 functions |= MotifFunctions.Move | MotifFunctions.Resize;
531                                 decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
532                         }
533
534                         if ((cp.Style & ((int)WindowStyles.WS_MINIMIZEBOX)) != 0) {
535                                 functions |= MotifFunctions.Minimize;
536                                 decorations |= MotifDecorations.Minimize;
537                         }
538
539                         if ((cp.Style & ((int)WindowStyles.WS_MAXIMIZEBOX)) != 0) {
540                                 functions |= MotifFunctions.Maximize;
541                                 decorations |= MotifDecorations.Maximize;
542                         }
543
544                         if ((cp.Style & ((int)WindowStyles.WS_SYSMENU)) != 0) {
545                                 functions |= MotifFunctions.Close;
546                         }
547
548                         if ((cp.ExStyle & ((int)WindowStyles.WS_EX_DLGMODALFRAME)) != 0) {
549                                 decorations |= MotifDecorations.Border;
550                         }
551
552                         if ((cp.Style & ((int)WindowStyles.WS_DLGFRAME)) != 0) {
553                                 decorations |= MotifDecorations.Border;
554                         }
555
556                         if ((cp.Style & ((int)WindowStyles.WS_BORDER)) != 0) {
557                                 decorations |= MotifDecorations.Border;
558                         }
559
560                         if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
561                                 functions = 0;
562                                 decorations = 0;
563                         }
564
565                         mwmHints.functions = (IntPtr)functions;
566                         mwmHints.decorations = (IntPtr)decorations;
567
568
569                         client_rect = hwnd.ClientRect;
570                         lock (XlibLock) {
571                                 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._MOTIF_WM_HINTS], NetAtoms[(int)NA._MOTIF_WM_HINTS], 32, PropertyMode.Replace, ref mwmHints, 5);
572
573                                 if (((cp.Style & (int)WindowStyles.WS_POPUP) != 0)  && (hwnd.parent != null) && (hwnd.parent.whole_window != IntPtr.Zero)) {
574                                         XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd.parent.whole_window);
575                                 }
576                                 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
577
578                                 atoms = new uint[8];
579                                 atom_count = 0;
580
581                                 if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
582                                         atoms[atom_count++] = (uint)NetAtoms[(int)NA._NET_WM_STATE_ABOVE];
583                                         atoms[atom_count++] = (uint)NetAtoms[(int)NA._NET_WM_STATE_NO_TASKBAR];
584                                 }
585
586                                 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], Atom.XA_ATOM, 32, PropertyMode.Replace, atoms, atom_count);
587
588                                 atom_count = 0;
589                                 atoms[atom_count++] = (uint)NetAtoms[(int)NA.WM_DELETE_WINDOW];
590                                 if ((cp.ExStyle & (int)WindowStyles.WS_EX_CONTEXTHELP) != 0) {
591                                         atoms[atom_count++] = (uint)NetAtoms[(int)NA._NET_WM_CONTEXT_HELP];
592                                 }
593
594                                 XSetWMProtocols(DisplayHandle, hwnd.whole_window, atoms, atom_count);
595                         }
596                 }
597
598                 private void SetIcon(Hwnd hwnd, Icon icon) {
599                         Bitmap          bitmap;
600                         int             size;
601                         uint[]          data;
602                         int             index;
603
604                         bitmap = icon.ToBitmap();
605                         index = 0;
606                         size = bitmap.Width * bitmap.Height + 2;
607                         data = new uint[size];
608
609                         data[index++] = (uint)bitmap.Width;
610                         data[index++] = (uint)bitmap.Height;
611
612                         for (int y = 0; y < bitmap.Height; y++) {
613                                 for (int x = 0; x < bitmap.Width; x++) {
614                                         data[index++] = (uint)bitmap.GetPixel(x, y).ToArgb();
615                                 }
616                         }
617                         XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_ICON], Atom.XA_CARDINAL, 32, PropertyMode.Replace, data, size);
618                 }
619
620                 private void WakeupMain () {
621                         wake.BeginSend (new byte [] { 0xFF }, 0, 1, SocketFlags.None, null, null);
622                 }
623
624                 private void AddExpose (XEvent xevent) {
625                         Hwnd    hwnd;
626
627                         hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
628
629                         // Don't waste time
630                         if (hwnd == null || !hwnd.visible) {
631                                 return;
632                         }
633
634                         if (xevent.AnyEvent.window == hwnd.client_window) {
635                                 hwnd.AddInvalidArea(xevent.ExposeEvent.x, xevent.ExposeEvent.y, xevent.ExposeEvent.width, xevent.ExposeEvent.height);
636
637                                 if (!hwnd.expose_pending) {
638                                         MessageQueue.Enqueue(xevent);
639                                         hwnd.expose_pending = true;
640                                 }
641                         } else {
642                                 if (!hwnd.nc_expose_pending) {
643                                         MessageQueue.Enqueue(xevent);
644                                         hwnd.nc_expose_pending = true;
645                                 }
646                         }
647                 }
648
649                 private void AddConfigureNotify (XEvent xevent) {
650                         Hwnd    hwnd;
651
652                         hwnd = Hwnd.GetObjectFromWindow(xevent.ConfigureEvent.window);
653
654                         // Don't waste time
655                         if (hwnd == null) {
656                                 return;
657                         }
658
659                         if (xevent.ConfigureEvent.window == hwnd.whole_window) {
660                                 if (hwnd.parent != null) {
661                                         hwnd.x = xevent.ConfigureEvent.x;
662                                         hwnd.y = xevent.ConfigureEvent.y;
663                                 } else {
664                                         IntPtr  child;
665
666                                         // We need to 'discount' the window the WM has put us in
667                                         XTranslateCoordinates(DisplayHandle, XGetParent(hwnd.whole_window), RootWindow, xevent.ConfigureEvent.x, xevent.ConfigureEvent.y, out hwnd.x, out hwnd.y, out child);
668                                 }
669
670                                 hwnd.width = xevent.ConfigureEvent.width;
671                                 hwnd.height = xevent.ConfigureEvent.height;
672
673                                 if (!hwnd.configure_pending) {
674                                         MessageQueue.Enqueue(xevent);
675                                         hwnd.configure_pending = true;
676                                 }
677                         }
678                         // We drop configure events for Client windows
679                 }
680
681                 private void ShowCaret() {
682                         if ((Caret.gc == IntPtr.Zero) || Caret.On) {
683                                 return;
684                         }
685                         Caret.On = true;
686
687                         lock (XlibLock) {
688                                 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
689                         }
690                 }
691
692                 private void HideCaret() {
693                         if ((Caret.gc == IntPtr.Zero) || !Caret.On) {
694                                 return;
695                         }
696                         Caret.On = false;
697
698                         lock (XlibLock) {
699                                 XDrawLine(DisplayHandle, Caret.Window, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
700                         }
701                 }
702
703                 private int NextTimeout (DateTime now) {
704                         int timeout = Int32.MaxValue; 
705                         lock (TimerList) {
706                                 foreach (Timer timer in TimerList) {
707                                         int next = (int) (timer.Expires - now).TotalMilliseconds;
708                                         if (next < 0) {
709                                                 return 0; // Have a timer that has already expired
710                                         }
711
712                                         if (next < timeout) {
713                                                 timeout = next;
714                                         }
715                                 }
716                         }
717                         if (timeout < Timer.Minimum) {
718                                 timeout = Timer.Minimum;
719                         }
720
721                         return timeout;
722                 }
723
724                 private void CheckTimers (DateTime now) {
725                         lock (TimerList) {
726                                 int count;
727
728                                 count = TimerList.Count;
729
730                                 if (count == 0) {
731                                         return;
732                                 }
733
734                                 for (int i = 0; i < TimerList.Count; i++) {
735                                         Timer timer;
736
737                                         timer = (Timer) TimerList[i];
738
739                                         if (timer.Enabled && timer.Expires <= now) {
740                                                 timer.FireTick ();
741                                                 timer.Update (now);
742                                         }
743                                 }
744                         }
745                 }
746
747                 private void UpdateMessageQueue () {
748                         DateTime        now;
749                         int             pending;
750
751                         now = DateTime.Now;
752
753                         lock (XlibLock) {
754                                 pending = XPending (DisplayHandle);
755                         }
756
757                         if (pending == 0) {
758                                 if (Idle != null) {
759                                         Idle (this, EventArgs.Empty);
760                                 }
761
762                                 lock (XlibLock) {
763                                         pending = XPending (DisplayHandle);
764                                 }
765                         }
766
767                         if (pending == 0) {
768                                 int     timeout;
769
770                                 timeout = NextTimeout (now);
771                                 if (timeout > 0) {
772                                         #if __MonoCS__
773                                         Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
774                                         #endif
775                                         lock (XlibLock) {
776                                                 pending = XPending (DisplayHandle);
777                                         }
778                                 }
779                         }
780
781                         CheckTimers (now);
782
783                         if (pending == 0) {
784                                 lock (XlibLock) {
785                                         pending = XPending (DisplayHandle);
786                                 }
787                         }
788
789                         while (pending > 0) {
790                                 XEvent xevent = new XEvent ();
791
792                                 lock (XlibLock) {
793                                         XNextEvent (DisplayHandle, ref xevent);
794                                 }
795                                 
796                                 switch (xevent.type) {
797                                         case XEventName.Expose:
798                                                 AddExpose (xevent);
799                                                 break;
800
801                                         case XEventName.KeyPress:
802                                         case XEventName.KeyRelease:
803                                         case XEventName.ButtonPress:
804                                         case XEventName.ButtonRelease:
805                                         case XEventName.MotionNotify:
806                                         case XEventName.EnterNotify:
807                                         case XEventName.LeaveNotify:
808                                         case XEventName.CreateNotify:
809                                         case XEventName.DestroyNotify:
810                                         case XEventName.FocusIn:
811                                         case XEventName.FocusOut:
812                                         case XEventName.ClientMessage:
813                                                 MessageQueue.Enqueue (xevent);
814                                                 break;
815
816                                         case XEventName.ConfigureNotify:
817                                                 AddConfigureNotify(xevent);
818                                                 break;
819
820                                         case XEventName.PropertyNotify:
821                                                 if (xevent.PropertyEvent.atom == NetAtoms[(int)NA._NET_ACTIVE_WINDOW]) {
822                                                         Atom    actual_atom;
823                                                         int     actual_format;
824                                                         int     nitems;
825                                                         int     bytes_after;
826                                                         IntPtr  prop = IntPtr.Zero;
827                                                         IntPtr  prev_active;;
828
829                                                         prev_active = ActiveWindow;
830                                                         XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], 0, 1, false, Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
831                                                         if ((nitems > 0) && (prop != IntPtr.Zero)) {
832                                                                 ActiveWindow = Hwnd.GetHandleFromWindow((IntPtr)Marshal.ReadInt32(prop));
833                                                                 XFree(prop);
834
835                                                                 if (prev_active != ActiveWindow) {
836                                                                         if (prev_active != IntPtr.Zero) {
837                                                                                 PostMessage(prev_active, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_INACTIVE, IntPtr.Zero);
838                                                                         }
839                                                                         if (ActiveWindow != IntPtr.Zero) {
840                                                                                 PostMessage(ActiveWindow, Msg.WM_ACTIVATE, (IntPtr)WindowActiveFlags.WA_ACTIVE, IntPtr.Zero);
841                                                                         }
842                                                                 }
843                                                                 if (ModalWindows.Count == 0) {
844                                                                         break;
845                                                                 } else {
846                                                                         // Modality handling, if we are modal and the new active window is one
847                                                                         // of ours but not the modal one, switch back to the modal window
848
849                                                                         if (NativeWindow.FindWindow(ActiveWindow) != null) {
850                                                                                 if (ActiveWindow != (IntPtr)ModalWindows.Peek()) {
851                                                                                         Activate((IntPtr)ModalWindows.Peek());
852                                                                                 }
853                                                                         }
854                                                                         break;
855                                                                 }
856                                                         }
857                                                 }
858                                                 break;
859
860                                 }
861
862                                 lock (XlibLock) {
863                                         pending = XPending (DisplayHandle);
864                                 }
865                         }
866                 }
867
868                 private IntPtr GetMousewParam(int Delta) {
869                         int     result = 0;
870
871                         if ((MouseState & MouseButtons.Left) != 0) {
872                                 result |= (int)MsgButtons.MK_LBUTTON;
873                         }
874
875                         if ((MouseState & MouseButtons.Middle) != 0) {
876                                 result |= (int)MsgButtons.MK_MBUTTON;
877                         }
878
879                         if ((MouseState & MouseButtons.Right) != 0) {
880                                 result |= (int)MsgButtons.MK_RBUTTON;
881                         }
882
883                         Keys mods = ModifierKeys;
884                         if ((mods & Keys.Control) != 0) {
885                                 result |= (int)MsgButtons.MK_CONTROL;
886                         }
887
888                         if ((mods & Keys.Shift) != 0) {
889                                 result |= (int)MsgButtons.MK_SHIFT;
890                         }
891
892                         result |= Delta << 16;
893
894                         return (IntPtr)result;
895                 }
896                 private IntPtr XGetParent(IntPtr handle) {
897                         IntPtr  Root;
898                         IntPtr  Parent;
899                         IntPtr  Children;
900                         int     ChildCount;
901
902                         lock (XlibLock) {
903                                 XQueryTree(DisplayHandle, handle, out Root, out Parent, out Children, out ChildCount);
904                         }
905
906                         if (Children!=IntPtr.Zero) {
907                                 lock (XlibLock) {
908                                         XFree(Children);
909                                 }
910                         }
911                         return Parent;
912                 }
913
914                 private int HandleError(IntPtr display, ref XErrorEvent error_event) {
915                         if (ErrorExceptions) {
916                                 throw new XException(error_event.display, error_event.resourceid, error_event.serial, error_event.error_code, error_event.request_code, error_event.minor_code);
917                         } else {
918                                 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());
919                         }
920                         return 0;
921                 }
922                 #endregion      // Private Methods
923
924                 #region Callbacks
925                 private void MouseHover(object sender, EventArgs e) {
926                         if ((HoverState.X == MousePosition.X) && (HoverState.Y == MousePosition.Y)) {
927                                 XEvent xevent;
928
929                                 HoverState.Timer.Enabled = false;
930
931                                 if (HoverState.Window != IntPtr.Zero) {
932                                         xevent = new XEvent ();
933
934                                         xevent.type = XEventName.ClientMessage;
935                                         xevent.ClientMessageEvent.display = DisplayHandle;
936                                         xevent.ClientMessageEvent.window = (IntPtr)HoverState.Window;
937                                         xevent.ClientMessageEvent.message_type = (IntPtr)HoverState.Atom;
938                                         xevent.ClientMessageEvent.format = 32;
939                                         xevent.ClientMessageEvent.ptr1 = (IntPtr) (HoverState.Y << 16 | HoverState.X);
940
941                                         MessageQueue.EnqueueLocked (xevent);
942
943                                         WakeupMain ();
944                                 }
945                         }
946                 }
947
948                 private void CaretCallback(object sender, EventArgs e) {
949                         if (Caret.Paused) {
950                                 return;
951                         }
952                         Caret.On = !Caret.On;
953
954                         XDrawLine(DisplayHandle, Caret.Hwnd, Caret.gc, Caret.X, Caret.Y, Caret.X, Caret.Y + Caret.Height);
955                 }
956                 #endregion      // Callbacks
957
958                 #region Public Properties
959                 internal override  Size CursorSize {
960                         get {
961                                 int     x;
962                                 int     y;
963
964                                 if (XQueryBestCursor(DisplayHandle, RootWindow, 32, 32, out x, out y) != 0) {
965                                         return new Size(x, y);
966                                 } else {
967                                         return new Size(16, 16);
968                                 }
969                         }
970                 } 
971
972                 internal override  bool DragFullWindows {
973                         get {
974                                 return true;
975                         }
976                 } 
977
978                 internal override  Size DragSize {
979                         get {
980                                 return new Size(4, 4);
981                         }
982                 } 
983
984                 internal override  Size IconSize {
985                         get {
986                                 IntPtr          list;
987                                 XIconSize       size;
988                                 int             count;
989
990                                 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
991                                         long            current;
992                                         int             largest;
993
994                                         current = (long)list;
995                                         largest = 0;
996
997                                         size = new XIconSize();
998
999                                         for (int i = 0; i < count; i++) {
1000                                                 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1001                                                 current += Marshal.SizeOf(size);
1002
1003                                                 // Look for our preferred size
1004                                                 if (size.min_width == 32) {
1005                                                         XFree(list);
1006                                                         return new Size(32, 32);
1007                                                 }
1008
1009                                                 if (size.max_width == 32) {
1010                                                         XFree(list);
1011                                                         return new Size(32, 32);
1012                                                 }
1013
1014                                                 if (size.min_width < 32 && size.max_width > 32) {
1015                                                         int     x;
1016
1017                                                         // check if we can fit one
1018                                                         x = size.min_width;
1019                                                         while (x < size.max_width) {
1020                                                                 x += size.width_inc;
1021                                                                 if (x == 32) {
1022                                                                         XFree(list);
1023                                                                         return new Size(32, 32);
1024                                                                 }
1025                                                         }
1026                                                 }
1027
1028                                                 if (largest < size.max_width) {
1029                                                         largest = size.max_width;
1030                                                 }
1031                                         }
1032
1033                                         // We didn't find a match or we wouldn't be here
1034                                         return new Size(largest, largest);
1035
1036                                 } else {
1037                                         return new Size(32, 32);
1038                                 }
1039                         }
1040                 } 
1041
1042                 internal override int KeyboardSpeed {
1043                         get{
1044                                 //
1045                                 // A lot harder: need to do:
1046                                 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)       = 1
1047                                 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)        = 0x080517a8
1048                                 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58)                   = 0
1049                                 //
1050                                 // And from that we can tell the repetition rate
1051                                 //
1052                                 // Notice, the values must map to:
1053                                 //   [0, 31] which maps to 2.5 to 30 repetitions per second.
1054                                 //
1055                                 return 0;
1056                         }
1057                 }
1058
1059                 internal override int KeyboardDelay {
1060                         get {
1061                                 //
1062                                 // Return values must range from 0 to 4, 0 meaning 250ms,
1063                                 // and 4 meaning 1000 ms.
1064                                 //
1065                                 return 1; // ie, 500 ms
1066                         }
1067                 } 
1068
1069                 internal override  Size MaxWindowTrackSize {
1070                         get {
1071                                 return new Size (WorkingArea.Width, WorkingArea.Height);
1072                         }
1073                 } 
1074
1075                 internal override  Size MinimizedWindowSize {
1076                         get {
1077                                 return new Size(1, 1);
1078                         }
1079                 } 
1080
1081                 internal override  Size MinimizedWindowSpacingSize {
1082                         get {
1083                                 return new Size(1, 1);
1084                         }
1085                 } 
1086
1087                 internal override  Size MinimumWindowSize {
1088                         get {
1089                                 return new Size(1, 1);
1090                         }
1091                 } 
1092
1093                 internal override  Size MinWindowTrackSize {
1094                         get {
1095                                 return new Size(1, 1);
1096                         }
1097                 } 
1098
1099                 internal override  Size SmallIconSize {
1100                         get {
1101                                 IntPtr          list;
1102                                 XIconSize       size;
1103                                 int             count;
1104
1105                                 if (XGetIconSizes(DisplayHandle, RootWindow, out list, out count) != 0) {
1106                                         long            current;
1107                                         int             smallest;
1108
1109                                         current = (long)list;
1110                                         smallest = 0;
1111
1112                                         size = new XIconSize();
1113
1114                                         for (int i = 0; i < count; i++) {
1115                                                 size = (XIconSize)Marshal.PtrToStructure((IntPtr)current, size.GetType());
1116                                                 current += Marshal.SizeOf(size);
1117
1118                                                 // Look for our preferred size
1119                                                 if (size.min_width == 16) {
1120                                                         XFree(list);
1121                                                         return new Size(16, 16);
1122                                                 }
1123
1124                                                 if (size.max_width == 16) {
1125                                                         XFree(list);
1126                                                         return new Size(16, 16);
1127                                                 }
1128
1129                                                 if (size.min_width < 16 && size.max_width > 16) {
1130                                                         int     x;
1131
1132                                                         // check if we can fit one
1133                                                         x = size.min_width;
1134                                                         while (x < size.max_width) {
1135                                                                 x += size.width_inc;
1136                                                                 if (x == 16) {
1137                                                                         XFree(list);
1138                                                                         return new Size(16, 16);
1139                                                                 }
1140                                                         }
1141                                                 }
1142
1143                                                 if (smallest == 0 || smallest > size.min_width) {
1144                                                         smallest = size.min_width;
1145                                                 }
1146                                         }
1147
1148                                         // We didn't find a match or we wouldn't be here
1149                                         return new Size(smallest, smallest);
1150
1151                                 } else {
1152                                         return new Size(16, 16);
1153                                 }
1154                         }
1155                 } 
1156
1157                 internal override  int MouseButtonCount {
1158                         get {
1159                                 return 3;
1160                         }
1161                 } 
1162
1163                 internal override  bool MouseButtonsSwapped {
1164                         get {
1165                                 return false;   // FIXME - how to detect?
1166                         }
1167                 } 
1168
1169                 internal override  bool MouseWheelPresent {
1170                         get {
1171                                 return true;    // FIXME - how to detect?
1172                         }
1173                 } 
1174
1175                 internal override  Rectangle VirtualScreen {
1176                         get {
1177                                 return WorkingArea;
1178                         }
1179                 } 
1180
1181                 internal override  Rectangle WorkingArea {
1182                         get {
1183                                 Atom                    actual_atom;
1184                                 int                     actual_format;
1185                                 int                     nitems;
1186                                 int                     bytes_after;
1187                                 IntPtr                  prop = IntPtr.Zero;
1188                                 int                     width;
1189                                 int                     height;
1190
1191                                 XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_DESKTOP_GEOMETRY], 0, 256, false, Atom.XA_CARDINAL, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1192                                 if ((nitems == 2) && (prop != IntPtr.Zero)) {
1193                                         width = Marshal.ReadInt32(prop, 0);
1194                                         height = Marshal.ReadInt32(prop, 4);
1195
1196                                         XFree(prop);
1197                                         return new Rectangle(0, 0, width, height);
1198                                 } else {
1199                                         XWindowAttributes       attributes=new XWindowAttributes();
1200
1201                                         lock (XlibLock) {
1202                                                 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
1203                                         }
1204
1205                                         return new Rectangle(0, 0, attributes.width, attributes.height);
1206                                 }
1207                         }
1208                 } 
1209                 #endregion      // Public properties
1210
1211                 #region Public Static Methods
1212                 internal override IntPtr InitializeDriver() {
1213                         lock (this) {
1214                                 if (DisplayHandle==IntPtr.Zero) {
1215                                         SetDisplay(XOpenDisplay(IntPtr.Zero));
1216                                 }
1217                         }
1218                         return IntPtr.Zero;
1219                 }
1220
1221                 internal override void ShutdownDriver(IntPtr token) {
1222                         lock (this) {
1223                                 if (DisplayHandle!=IntPtr.Zero) {
1224                                         XCloseDisplay(DisplayHandle);
1225                                         DisplayHandle=IntPtr.Zero;
1226                                 }
1227                         }
1228                 }
1229
1230                 internal override void EnableThemes() {
1231                         ThemesEnabled = true;
1232                 }
1233
1234
1235                 internal override void Activate(IntPtr handle) {
1236                         lock (XlibLock) {
1237                                 SendNetWMMessage(Hwnd.ObjectFromHandle(handle).whole_window, (IntPtr)NetAtoms[(int)NA._NET_ACTIVE_WINDOW], IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
1238                                 //XRaiseWindow(DisplayHandle, handle);
1239                         }
1240                         return;
1241                 }
1242
1243                 internal override void CaretVisible(IntPtr handle, bool visible) {
1244                         // Visible is cumulative; two hides require two shows before the caret is visible again
1245                         if (Caret.Hwnd == handle) {
1246                                 if (visible) {
1247                                         if (Caret.Visible < 1) {
1248                                                 Caret.Visible++;
1249                                                 Caret.On = false;
1250                                                 if (Caret.Visible == 1) {
1251                                                         ShowCaret();
1252                                                         Caret.Timer.Start();
1253                                                 }
1254                                         }
1255                                 } else {
1256                                         Caret.Visible--;
1257                                         if (Caret.Visible == 0) {
1258                                                 Caret.Timer.Stop();
1259                                                 HideCaret();
1260                                         }
1261                                 }
1262                         }
1263                 }
1264
1265                 internal override bool CalculateWindowRect(IntPtr handle, ref Rectangle ClientRect, int Style, int ExStyle, IntPtr MenuHandle, out Rectangle WindowRect) {
1266                         BorderStyle     border_style;
1267                         TitleStyle      title_style;
1268
1269                         title_style = TitleStyle.None;
1270                         if ((Style & (int)WindowStyles.WS_CAPTION) != 0) {
1271                                 if ((ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
1272                                         title_style = TitleStyle.Tool;
1273                                 } else {
1274                                         title_style = TitleStyle.Normal;
1275                                 }
1276                         }
1277
1278                         border_style = BorderStyle.None;
1279                         if ((Style & (int)WindowStyles.WS_CHILD) != 0) {
1280                                 if ((Style & (int)WindowStyles.WS_THICKFRAME) != 0) {
1281                                         border_style = BorderStyle.Fixed3D;
1282                                 } else if ((Style & (int)WindowStyles.WS_BORDER) != 0) {
1283                                         border_style = BorderStyle.FixedSingle;
1284                                 }
1285                         }
1286
1287                         WindowRect = Hwnd.GetWindowRectangle(border_style, MenuHandle, title_style, ClientRect);
1288
1289                         return true;
1290                 }
1291
1292                 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
1293                         int     dest_x_return;
1294                         int     dest_y_return;
1295                         IntPtr  child;
1296                         Hwnd    hwnd;
1297
1298                         hwnd = Hwnd.ObjectFromHandle(handle);
1299
1300                         lock (XlibLock) {
1301                                 XTranslateCoordinates(DisplayHandle, hwnd.client_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
1302                         }
1303
1304                         x = dest_x_return;
1305                         y = dest_y_return;
1306                 }
1307
1308                 internal override void CreateCaret(IntPtr handle, int width, int height) {
1309                         XGCValues       gc_values;
1310                         Hwnd            hwnd;
1311
1312                         hwnd = Hwnd.ObjectFromHandle(handle);
1313
1314                         if (Caret.Hwnd != IntPtr.Zero) {
1315                                 DestroyCaret(Caret.Hwnd);
1316                         }
1317
1318                         Caret.Hwnd = handle;
1319                         Caret.Window = hwnd.client_window;
1320                         Caret.Width = width;
1321                         Caret.Height = height;
1322                         Caret.Visible = 0;
1323                         Caret.On = false;
1324
1325                         gc_values = new XGCValues();
1326                         gc_values.line_width = width;
1327
1328                         Caret.gc = XCreateGC(DisplayHandle, Caret.Window, GCFunction.GCLineWidth, ref gc_values);
1329                         if (Caret.gc == IntPtr.Zero) {
1330                                 Caret.Hwnd = IntPtr.Zero;
1331                                 return;
1332                         }
1333
1334                         XSetFunction(DisplayHandle, Caret.gc, GXFunction.GXinvert);
1335                 }
1336
1337                 internal override IntPtr CreateWindow(CreateParams cp) {
1338                         XSetWindowAttributes    Attributes;
1339                         Hwnd                    hwnd;
1340                         int                     X;
1341                         int                     Y;
1342                         int                     Width;
1343                         int                     Height;
1344                         IntPtr                  ParentHandle;
1345                         IntPtr                  WholeWindow;
1346                         IntPtr                  ClientWindow;
1347                         Rectangle               ClientRect;
1348
1349
1350                         hwnd = new Hwnd();
1351
1352                         SetHwndStyles(hwnd, cp);
1353
1354                         Attributes = new XSetWindowAttributes();
1355                         X = cp.X;
1356                         Y = cp.Y;
1357                         Width = cp.Width;
1358                         Height = cp.Height;
1359
1360                         if (Width<1) Width=1;
1361                         if (Height<1) Height=1;
1362
1363                         if (cp.Parent != IntPtr.Zero) {
1364                                 ParentHandle = Hwnd.ObjectFromHandle(cp.Parent).client_window;
1365                         } else {
1366                                 if ((cp.Style & (int)WindowStyles.WS_CHILD) != 0) {
1367                                         // We need to use our foster parent window until this poor child gets it's parent assigned
1368                                         ParentHandle=FosterParent;
1369                                 } else if ((cp.Style & (int)WindowStyles.WS_POPUP) != 0) {
1370                                         ParentHandle=RootWindow;
1371                                 } else {
1372                                         // Default position on screen, if window manager doesn't place us somewhere else
1373                                         if (X<1) X = 50;
1374                                         if (Y<1) Y = 50;
1375                                         ParentHandle=RootWindow;
1376                                 }
1377                         }
1378
1379                         // Save what's under the toolwindow
1380                         if ((cp.ExStyle & (int)WindowStyles.WS_EX_TOOLWINDOW) != 0) {
1381                                 Attributes.save_under = true;
1382                         }
1383
1384
1385                         // If we're a popup without caption we override the WM
1386                         if ((cp.Style & ((int)WindowStyles.WS_POPUP)) != 0) {
1387                                 if ((cp.Style & (int)WindowStyles.WS_CAPTION) == 0) {
1388                                         Attributes.override_redirect = true;
1389                                 }
1390                         }
1391                         
1392                         Attributes.bit_gravity = Gravity.NorthWestGravity;
1393                         Attributes.win_gravity = Gravity.NorthWestGravity;
1394
1395                         hwnd.x = X;
1396                         hwnd.y = Y;
1397                         hwnd.width = Width;
1398                         hwnd.height = Height;
1399                         hwnd.parent = Hwnd.ObjectFromHandle(cp.Parent);
1400
1401                         ClientRect = hwnd.ClientRect;
1402                         ClientWindow = IntPtr.Zero;
1403
1404                         lock (XlibLock) {
1405                                 WholeWindow = XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity | SetWindowValuemask.SaveUnder | SetWindowValuemask.OverrideRedirect, ref Attributes);
1406                                 if (WholeWindow != IntPtr.Zero) {
1407                                         ClientWindow = XCreateWindow(DisplayHandle, WholeWindow, ClientRect.X, ClientRect.Y, ClientRect.Width, ClientRect.Height, 0, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, SetWindowValuemask.Nothing, ref Attributes);
1408                                 }
1409                         }
1410
1411                         if ((WholeWindow == IntPtr.Zero) || (ClientWindow == IntPtr.Zero)) {
1412                                 throw new Exception("Could not create X11 windows");
1413                         }
1414
1415                         hwnd.WholeWindow = WholeWindow;
1416                         hwnd.ClientWindow = ClientWindow;
1417
1418                         #if DriverDebug
1419                                 Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0);
1420                         #endif
1421                                        
1422                         lock (XlibLock) {
1423                                 XSelectInput(DisplayHandle, hwnd.whole_window, SelectInputMask);
1424                                 XSelectInput(DisplayHandle, hwnd.client_window, SelectInputMask);
1425
1426                                 if ((cp.Style & (int)WindowStyles.WS_VISIBLE) != 0) {
1427                                         XMapWindow(DisplayHandle, hwnd.whole_window);
1428                                         XMapWindow(DisplayHandle, hwnd.client_window);
1429                                         hwnd.visible = true;
1430                                 }
1431                         }
1432
1433                         SetWMStyles(hwnd, cp);
1434
1435                         return hwnd.Handle;
1436                 }
1437
1438                 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
1439                         CreateParams create_params = new CreateParams();
1440
1441                         create_params.Caption = "";
1442                         create_params.X = X;
1443                         create_params.Y = Y;
1444                         create_params.Width = Width;
1445                         create_params.Height = Height;
1446
1447                         create_params.ClassName=XplatUI.DefaultClassName;
1448                         create_params.ClassStyle = 0;
1449                         create_params.ExStyle=0;
1450                         create_params.Parent=IntPtr.Zero;
1451                         create_params.Param=0;
1452
1453                         return CreateWindow(create_params);
1454                 }
1455
1456                 internal override IntPtr DefineCursor(Bitmap bitmap, Bitmap mask, Color cursor_pixel, Color mask_pixel, int xHotSpot, int yHotSpot) {
1457                         IntPtr  cursor;
1458                         Bitmap  cursor_bitmap;
1459                         Bitmap  cursor_mask;
1460                         Byte[]  cursor_bits;
1461                         Byte[]  mask_bits;
1462                         Color   c_pixel;
1463                         Color   m_pixel;
1464                         int     width;
1465                         int     height;
1466                         IntPtr  cursor_pixmap;
1467                         IntPtr  mask_pixmap;
1468                         XColor  fg;
1469                         XColor  bg;
1470                         bool    and;
1471                         bool    xor;
1472
1473                         if (XQueryBestCursor(DisplayHandle, RootWindow, bitmap.Width, bitmap.Height, out width, out height) == 0) {
1474                                 return IntPtr.Zero;
1475                         }
1476
1477                         // Win32 only allows creation cursors of a certain size
1478                         if ((bitmap.Width != width) || (bitmap.Width != height)) {
1479                                 cursor_bitmap = new Bitmap(bitmap, new Size(width, height));
1480                                 cursor_mask = new Bitmap(mask, new Size(width, height));
1481                         } else {
1482                                 cursor_bitmap = bitmap;
1483                                 cursor_mask = mask;
1484                         }
1485
1486                         width = cursor_bitmap.Width;
1487                         height = cursor_bitmap.Height;
1488
1489                         cursor_bits = new Byte[(width / 8) * height];
1490                         mask_bits = new Byte[(width / 8) * height];
1491
1492                         for (int y = 0; y < height; y++) {
1493                                 for (int x = 0; x < width; x++) {
1494                                         c_pixel = cursor_bitmap.GetPixel(x, y);
1495                                         m_pixel = cursor_mask.GetPixel(x, y);
1496
1497                                         and = c_pixel == cursor_pixel;
1498                                         xor = m_pixel == mask_pixel;
1499
1500                                         if (!and && !xor) {
1501                                                 // Black
1502                                                 // cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));       // The bit already is 0
1503                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
1504                                         } else if (!and && xor) {
1505                                                 // White
1506                                                 cursor_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
1507                                                 mask_bits[y * width / 8 + x / 8] |= (byte)(1 << (x % 8));
1508 #if notneeded
1509                                         } else if (and && !xor) {
1510                                                 // Screen
1511                                         } else if (and && xor) {
1512                                                 // Inverse Screen
1513
1514                                                 // X11 doesn't know the 'reverse screen' concept, so we'll treat them the same
1515                                                 // we want both to be 0 so nothing to be done
1516                                                 //cursor_bits[y * width / 8 + x / 8] &= (byte)~((1 << (x % 8)));
1517                                                 //mask_bits[y * width / 8 + x / 8] |= (byte)(01 << (x % 8));
1518 #endif
1519                                         }
1520                                 }
1521                         }
1522
1523                         cursor_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, cursor_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
1524                         mask_pixmap = XCreatePixmapFromBitmapData(DisplayHandle, RootWindow, mask_bits, width, height, (IntPtr)1, (IntPtr)0, 1);
1525                         fg = new XColor();
1526                         bg = new XColor();
1527
1528                         fg.pixel = XWhitePixel(DisplayHandle, ScreenNo);
1529                         fg.red = (ushort)65535;
1530                         fg.green = (ushort)65535;
1531                         fg.blue = (ushort)65535;
1532
1533                         bg.pixel = XBlackPixel(DisplayHandle, ScreenNo);
1534
1535                         cursor = XCreatePixmapCursor(DisplayHandle, cursor_pixmap, mask_pixmap, ref fg, ref bg, xHotSpot, yHotSpot);
1536
1537                         XFreePixmap(DisplayHandle, cursor_pixmap);
1538                         XFreePixmap(DisplayHandle, mask_pixmap);
1539
1540                         return cursor;
1541                 }
1542
1543                 internal override IntPtr DefineStdCursor(StdCursor id) {
1544                         CursorFontShape shape;
1545                         IntPtr          cursor;
1546
1547                         // FIXME - define missing shapes
1548
1549                         switch (id) {
1550                                 case StdCursor.AppStarting: {
1551                                         shape = CursorFontShape.XC_watch;
1552                                         break;
1553                                 }
1554
1555                                 case StdCursor.Arrow: {
1556                                         return IntPtr.Zero;
1557                                 }
1558
1559                                 case StdCursor.Cross: {
1560                                         shape = CursorFontShape.XC_crosshair;
1561                                         break;
1562                                 }
1563
1564                                 case StdCursor.Default: {
1565                                         return IntPtr.Zero;
1566                                 }
1567
1568                                 case StdCursor.Hand: {
1569                                         shape = CursorFontShape.XC_hand2;
1570                                         break;
1571                                 }
1572
1573                                 case StdCursor.Help: {
1574                                         shape = CursorFontShape.XC_question_arrow;
1575                                         break;
1576                                 }
1577
1578                                 case StdCursor.HSplit: {
1579                                         shape = CursorFontShape.XC_sb_h_double_arrow;
1580                                         break;
1581                                 }
1582
1583                                 case StdCursor.IBeam: {
1584                                         shape = CursorFontShape.XC_xterm; 
1585                                         break;
1586                                 }
1587
1588                                 case StdCursor.No: {
1589                                         shape = CursorFontShape.XC_circle; 
1590                                         break;
1591                                 }
1592
1593                                 case StdCursor.NoMove2D: {
1594                                         shape = CursorFontShape.XC_fleur; 
1595                                         break;
1596                                 }
1597
1598                                 case StdCursor.NoMoveHoriz: {
1599                                         shape = CursorFontShape.XC_fleur; 
1600                                         break;
1601                                 }
1602
1603                                 case StdCursor.NoMoveVert: {
1604                                         shape = CursorFontShape.XC_fleur; 
1605                                         break;
1606                                 }
1607
1608                                 case StdCursor.PanEast: {
1609                                         shape = CursorFontShape.XC_fleur; 
1610                                         break;
1611                                 }
1612
1613                                 case StdCursor.PanNE: {
1614                                         shape = CursorFontShape.XC_fleur; 
1615                                         break;
1616                                 }
1617
1618                                 case StdCursor.PanNorth: {
1619                                         shape = CursorFontShape.XC_fleur; 
1620                                         break;
1621                                 }
1622
1623                                 case StdCursor.PanNW: {
1624                                         shape = CursorFontShape.XC_fleur; 
1625                                         break;
1626                                 }
1627
1628                                 case StdCursor.PanSE: {
1629                                         shape = CursorFontShape.XC_fleur; 
1630                                         break;
1631                                 }
1632
1633                                 case StdCursor.PanSouth: {
1634                                         shape = CursorFontShape.XC_fleur; 
1635                                         break;
1636                                 }
1637
1638                                 case StdCursor.PanSW: {
1639                                         shape = CursorFontShape.XC_fleur; 
1640                                         break;
1641                                 }
1642
1643                                 case StdCursor.PanWest: {
1644                                         shape = CursorFontShape.XC_sizing; 
1645                                         break;
1646                                 }
1647
1648                                 case StdCursor.SizeAll: {
1649                                         shape = CursorFontShape.XC_fleur; 
1650                                         break;
1651                                 }
1652
1653                                 case StdCursor.SizeNESW: {
1654                                         shape = CursorFontShape.XC_sizing; 
1655                                         break;
1656                                 }
1657
1658                                 case StdCursor.SizeNS: {
1659                                         shape = CursorFontShape.XC_fleur; 
1660                                         break;
1661                                 }
1662
1663                                 case StdCursor.SizeNWSE: {
1664                                         shape = CursorFontShape.XC_bottom_right_corner; 
1665                                         break;
1666                                 }
1667
1668                                 case StdCursor.SizeWE: {
1669                                         shape = CursorFontShape.XC_fleur; 
1670                                         break;
1671                                 }
1672
1673                                 case StdCursor.UpArrow: {
1674                                         shape = CursorFontShape.XC_center_ptr; 
1675                                         break;
1676                                 }
1677
1678                                 case StdCursor.VSplit: {
1679                                         shape = CursorFontShape.XC_sb_v_double_arrow; 
1680                                         break;
1681                                 }
1682
1683                                 case StdCursor.WaitCursor: {
1684                                         shape = CursorFontShape.XC_watch; 
1685                                         break;
1686                                 }
1687
1688                                 default: {
1689                                         return IntPtr.Zero;
1690                                 }
1691                         }
1692
1693                         lock (XlibLock) {
1694                                 cursor = XCreateFontCursor(DisplayHandle, shape);
1695                         }
1696                         return cursor;
1697                 }
1698
1699                 internal override IntPtr DefWndProc(ref Message msg) {
1700                         switch((Msg)msg.Msg) {
1701                                 case Msg.WM_ERASEBKGND: {
1702                                         Hwnd    hwnd;
1703
1704                                         hwnd = Hwnd.ObjectFromHandle(msg.HWnd);
1705                                         XClearArea(DisplayHandle, hwnd.client_window, hwnd.invalid.X, hwnd.invalid.Y, hwnd.invalid.Width, hwnd.invalid.Height, false);
1706
1707                                         return (IntPtr)1;
1708                                 }
1709                         }
1710                         return IntPtr.Zero;
1711                 }
1712
1713                 internal override void DestroyCaret(IntPtr handle) {
1714                         if (Caret.Hwnd == handle) {
1715                                 if (Caret.Visible == 1) {
1716                                         Caret.Timer.Stop();
1717                                         HideCaret();
1718                                 }
1719                                 if (Caret.gc != IntPtr.Zero) {
1720                                         XFreeGC(DisplayHandle, Caret.gc);
1721                                         Caret.gc = IntPtr.Zero;
1722                                 }
1723                                 Caret.Hwnd = IntPtr.Zero;
1724                                 Caret.Visible = 0;
1725                                 Caret.On = false;
1726                         }
1727                 }
1728
1729                 internal override void DestroyCursor(IntPtr cursor) {
1730                         lock (XlibLock) {
1731                                 XFreeCursor(DisplayHandle, cursor);
1732                         }
1733                 }
1734
1735                 internal override void DestroyWindow(IntPtr handle) {
1736                         Hwnd    hwnd;
1737
1738                         hwnd = Hwnd.ObjectFromHandle(handle);
1739
1740                         if (hwnd == null) {
1741                                 #if DriverDebug
1742                                         Console.WriteLine("window {0:X} already destroyed", handle.ToInt32());
1743                                 #endif
1744                                 return;
1745                         }
1746
1747                         #if DriverDebug
1748                                 Console.WriteLine("Destroying window {0:X}", handle.ToInt32());
1749                         #endif
1750
1751                         // Make sure if the caret is in the window, that we destroy the caret, too
1752                         if (Caret.Hwnd == hwnd.client_window) {
1753                                 DestroyCaret(handle);
1754                         }
1755
1756                         lock (XlibLock) {
1757                                 if (hwnd.client_window != IntPtr.Zero) {
1758                                         XDestroyWindow(DisplayHandle, hwnd.client_window);
1759                                 }
1760
1761                                 if (hwnd.whole_window != IntPtr.Zero) {
1762                                         XDestroyWindow(DisplayHandle, hwnd.whole_window);
1763                                 }
1764                         }
1765
1766                         hwnd.Dispose();
1767                 }
1768
1769                 internal override IntPtr DispatchMessage(ref MSG msg) {
1770                         return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
1771                 }
1772
1773                 internal override void DoEvents() {
1774                         MSG msg = new MSG ();
1775                         while (PeekMessage(ref msg, IntPtr.Zero, 0, 0, (uint)PeekMessageFlags.PM_REMOVE)) {
1776                                 if (msg.message == Msg.WM_PAINT) {
1777                                         TranslateMessage (ref msg);
1778                                         DispatchMessage (ref msg);
1779                                 }
1780                         }
1781                 }
1782
1783                 internal override void EnableWindow(IntPtr handle, bool Enable) {
1784                         // We do nothing; On X11 SetModal is used to create modal dialogs, on Win32 this function is used (see comment there)
1785                 }
1786
1787                 internal override void EraseWindowBackground(IntPtr handle, IntPtr wParam) {\r
1788                         Hwnd    hwnd;\r
1789 \r
1790                         hwnd = Hwnd.ObjectFromHandle(handle);\r
1791 \r
1792                         lock (XlibLock) {
1793                                 XClearArea (DisplayHandle, hwnd.client_window, hwnd.invalid.Left, hwnd.invalid.Top, hwnd.invalid.Width, hwnd.invalid.Height, false);
1794                         }
1795                 }\r
1796
1797                 internal override void Exit() {
1798                         GetMessageResult = false;
1799                 }
1800
1801                 internal override IntPtr GetActive() {
1802                         Atom    actual_atom;
1803                         int     actual_format;
1804                         int     nitems;
1805                         int     bytes_after;
1806                         IntPtr  prop = IntPtr.Zero;
1807                         IntPtr  active = IntPtr.Zero;
1808
1809                         XGetWindowProperty(DisplayHandle, RootWindow, NetAtoms[(int)NA._NET_ACTIVE_WINDOW], 0, 1, false, Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
1810                         if ((nitems > 0) && (prop != IntPtr.Zero)) {
1811                                 active = (IntPtr)Marshal.ReadInt32(prop);
1812                                 XFree(prop);
1813                         }
1814
1815                         if (active != IntPtr.Zero) {
1816                                 Hwnd    hwnd;
1817
1818                                 hwnd = Hwnd.GetObjectFromWindow(active);
1819                                 if (hwnd != null) {
1820                                         active = hwnd.Handle;
1821                                 } else {
1822                                         active = IntPtr.Zero;
1823                                 }
1824                         }
1825                         return active;
1826                 }
1827
1828                 internal override void GetCursorInfo(IntPtr cursor, out int width, out int height, out int hotspot_x, out int hotspot_y) {
1829                         throw new NotImplementedException ();
1830                 }
1831
1832                 internal override void GetDisplaySize(out Size size) {
1833                         XWindowAttributes       attributes=new XWindowAttributes();
1834
1835                         lock (XlibLock) {
1836                                 // FIXME - use _NET_WM messages instead?
1837                                 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
1838                         }
1839
1840                         size = new Size(attributes.width, attributes.height);
1841                 }
1842
1843                 internal override IntPtr GetParent(IntPtr handle) {
1844                         Hwnd    hwnd;
1845
1846                         hwnd = Hwnd.ObjectFromHandle(handle);
1847                         if (hwnd != null && hwnd.parent != null) {
1848                                 return hwnd.parent.Handle;
1849                         }
1850                         return IntPtr.Zero;
1851                 }
1852
1853                 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
1854                         IntPtr  use_handle;
1855                         IntPtr  root;
1856                         IntPtr  child;
1857                         int     root_x;
1858                         int     root_y;
1859                         int     win_x;
1860                         int     win_y;
1861                         int     keys_buttons;
1862
1863                         if (handle != IntPtr.Zero) {
1864                                 use_handle = Hwnd.ObjectFromHandle(handle).client_window;
1865                         } else {
1866                                 use_handle = RootWindow;
1867                         }
1868
1869                         lock (XlibLock) {
1870                                 XQueryPointer(DisplayHandle, use_handle, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
1871                         }
1872
1873                         if (handle != IntPtr.Zero) {
1874                                 x = win_x;
1875                                 y = win_y;
1876                         } else {
1877                                 x = root_x;
1878                                 y = root_y;
1879                         }
1880                 }
1881
1882                 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {
1883                         return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);
1884                 }
1885
1886                 internal override Graphics GetMenuDC(IntPtr handle, IntPtr ncpaint_region) {
1887                         Hwnd            hwnd;
1888
1889                         hwnd = Hwnd.ObjectFromHandle(handle);
1890
1891                         return Graphics.FromHwnd(hwnd.whole_window);
1892                 }
1893
1894                 internal override Point GetMenuOrigin(IntPtr handle) {
1895                         Hwnd    hwnd;
1896
1897                         hwnd = Hwnd.ObjectFromHandle(handle);
1898
1899                         if (hwnd != null) {
1900                                 return hwnd.MenuOrigin;
1901                         }
1902                         return Point.Empty;
1903                 }
1904
1905                 internal override bool GetMessage(ref MSG msg, IntPtr handle, int wFilterMin, int wFilterMax) {
1906                         XEvent  xevent;
1907                         bool    client;
1908                         Hwnd    hwnd;
1909
1910                         ProcessNextMessage:
1911
1912                         if (MessageQueue.Count > 0) {
1913                                 xevent = (XEvent) MessageQueue.Dequeue ();
1914                         } else {
1915                                 UpdateMessageQueue ();
1916
1917                                 if (MessageQueue.Count > 0) {
1918                                         xevent = (XEvent) MessageQueue.Dequeue ();
1919                                 } else {
1920                                         msg.hwnd= IntPtr.Zero;
1921                                         msg.message = Msg.WM_ENTERIDLE;
1922                                         return true;
1923                                 }
1924                         }
1925
1926                         // FIXME - handle filtering
1927
1928                         hwnd = Hwnd.GetObjectFromWindow(xevent.AnyEvent.window);
1929
1930                         // Handle messages for windows that are already destroyed
1931                         if (hwnd == null) {
1932                                 #if DriverDebug
1933                                         Console.WriteLine("GetMessage(): Got message for non-existent window {0:X}", xevent.AnyEvent.window.ToInt32());
1934                                 #endif
1935                                 goto ProcessNextMessage;
1936                         }
1937
1938                         if (hwnd.client_window == xevent.AnyEvent.window) {
1939                                 client = true;
1940                                 //Console.WriteLine("Client message, sending to window {0:X}", msg.hwnd.ToInt32());
1941                         } else {
1942                                 client = false;
1943                                 //Console.WriteLine("Non-Client message, sending to window {0:X}", msg.hwnd.ToInt32());
1944                         }
1945
1946                         msg.hwnd = hwnd.Handle;
1947
1948                         //
1949                         // If you add a new event to this switch make sure to add it in
1950                         // UpdateMessage also unless it is not coming through the X event system.
1951                         //
1952                         switch(xevent.type) {
1953                                 case XEventName.KeyPress: {
1954                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
1955                                         break;
1956                                 }
1957
1958                                 case XEventName.KeyRelease: {
1959                                         Keyboard.KeyEvent (FocusWindow, xevent, ref msg);
1960                                         break;
1961                                 }
1962
1963                                 case XEventName.ButtonPress: {
1964                                         switch(xevent.ButtonEvent.button) {
1965                                                 case 1: {
1966                                                         MouseState |= MouseButtons.Left;
1967                                                         if (client) {
1968                                                                 msg.message = Msg.WM_LBUTTONDOWN;
1969                                                         } else {
1970                                                                 msg.message = Msg.WM_NCLBUTTONDOWN;
1971                                                                 ClientToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);\r
1972                                                         }
1973                                                         msg.wParam=GetMousewParam(0);
1974                                                         break;
1975                                                 }
1976
1977                                                 case 2: {
1978                                                         MouseState |= MouseButtons.Middle;
1979                                                         if (client) {
1980                                                                 msg.message = Msg.WM_MBUTTONDOWN;
1981                                                         } else {
1982                                                                 msg.message = Msg.WM_NCMBUTTONDOWN;
1983                                                                 ClientToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);\r
1984                                                         }
1985                                                         msg.wParam=GetMousewParam(0);
1986                                                         break;
1987                                                 }
1988
1989                                                 case 3: {
1990                                                         MouseState |= MouseButtons.Right;
1991                                                         if (client) {
1992                                                                 msg.message = Msg.WM_RBUTTONDOWN;
1993                                                         } else {
1994                                                                 msg.message = Msg.WM_NCRBUTTONDOWN;
1995                                                                 ClientToScreen (msg.hwnd, ref xevent.ButtonEvent.x, ref xevent.ButtonEvent.y);\r
1996                                                         }
1997                                                         msg.wParam=GetMousewParam(0);
1998                                                         break;
1999                                                 }
2000
2001                                                 case 4: {
2002                                                         msg.message=Msg.WM_MOUSEWHEEL;
2003                                                         msg.wParam=GetMousewParam(120);
2004                                                         break;
2005                                                 }
2006
2007                                                 case 5: {
2008                                                         msg.message=Msg.WM_MOUSEWHEEL;
2009                                                         msg.wParam=GetMousewParam(-120);
2010                                                         break;
2011                                                 }
2012
2013                                         }
2014
2015                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
2016                                         MousePosition.X = xevent.ButtonEvent.x;
2017                                         MousePosition.Y = xevent.ButtonEvent.y;
2018
2019                                         if (!ClickPending.Pending) {
2020                                                 ClickPending.Pending = true;
2021                                                 ClickPending.Hwnd = msg.hwnd;
2022                                                 ClickPending.Message = msg.message;
2023                                                 ClickPending.wParam = msg.wParam;
2024                                                 ClickPending.lParam = msg.lParam;
2025                                                 ClickPending.Time = (long)xevent.ButtonEvent.time;
2026                                         } else {
2027                                                 if ((((long)xevent.ButtonEvent.time - ClickPending.Time) < DoubleClickInterval) && (msg.wParam == ClickPending.wParam) && (msg.lParam == ClickPending.lParam) && (msg.message == ClickPending.Message)) {
2028                                                         // Looks like a genuine double click, clicked twice on the same spot with the same keys
2029                                                         switch(xevent.ButtonEvent.button) {
2030                                                                 case 1: {
2031                                                                         msg.message = client ? Msg.WM_LBUTTONDBLCLK : Msg.WM_NCLBUTTONDBLCLK;
2032                                                                         break;
2033                                                                 }
2034
2035                                                                 case 2: {
2036                                                                         msg.message = client ? Msg.WM_MBUTTONDBLCLK : Msg.WM_NCMBUTTONDBLCLK;
2037                                                                         break;
2038                                                                 }
2039
2040                                                                 case 3: {
2041                                                                         msg.message = client ? Msg.WM_RBUTTONDBLCLK : Msg.WM_NCRBUTTONDBLCLK;
2042                                                                         break;
2043                                                                 }
2044                                                         }
2045                                                 }
2046                                                 ClickPending.Pending = false;
2047                                         }
2048
2049                                         break;
2050                                 }
2051
2052                                 case XEventName.ButtonRelease: {
2053                                         switch(xevent.ButtonEvent.button) {
2054                                                 case 1: {
2055                                                         MouseState &= ~MouseButtons.Left;
2056                                                         msg.message = client ? Msg.WM_LBUTTONUP : Msg.WM_NCLBUTTONUP;
2057                                                         msg.wParam=GetMousewParam(0);
2058                                                         break;
2059                                                 }
2060
2061                                                 case 2: {
2062                                                         MouseState &= ~MouseButtons.Middle;
2063                                                         msg.message = client ? Msg.WM_MBUTTONUP : Msg.WM_NCMBUTTONUP;
2064                                                         msg.wParam=GetMousewParam(0);
2065                                                         break;
2066                                                 }
2067
2068                                                 case 3: {
2069                                                         MouseState &= ~MouseButtons.Right;
2070                                                         msg.message = client ? Msg.WM_RBUTTONUP : Msg.WM_NCRBUTTONUP;
2071                                                         msg.wParam=GetMousewParam(0);
2072                                                         break;
2073                                                 }
2074
2075                                                 case 4: {
2076                                                         return true;
2077                                                 }
2078
2079                                                 case 5: {
2080                                                         return true;
2081                                                 }
2082                                         }
2083
2084                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
2085                                         MousePosition.X = xevent.ButtonEvent.x;
2086                                         MousePosition.Y = xevent.ButtonEvent.y;
2087                                         break;
2088                                 }
2089
2090                                 case XEventName.MotionNotify: {
2091                                         if (client) {
2092                                                 NativeWindow.WndProc(msg.hwnd, Msg.WM_SETCURSOR, msg.hwnd, (IntPtr)HitTest.HTCLIENT);
2093
2094                                                 msg.message = Msg.WM_MOUSEMOVE;
2095                                                 msg.wParam = GetMousewParam(0);
2096                                                 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x);
2097
2098                                                 HoverState.X = MousePosition.X = xevent.MotionEvent.x;
2099                                                 HoverState.Y = MousePosition.Y = xevent.MotionEvent.y;
2100
2101                                                 break;
2102                                         } else {
2103                                                 msg.message = Msg.WM_NCHITTEST;
2104                                                 msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x);
2105
2106                                                 MousePosition.X = xevent.MotionEvent.x;
2107                                                 MousePosition.Y = xevent.MotionEvent.y;
2108                                         }
2109
2110                                         break;
2111                                 }
2112
2113                                 case XEventName.EnterNotify: {
2114                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
2115                                                 return true;
2116                                         }
2117                                         msg.message = Msg.WM_MOUSE_ENTER;
2118                                         HoverState.Timer.Enabled = true;
2119                                         HoverState.Window = xevent.CrossingEvent.window;
2120                                         break;
2121                                 }
2122
2123                                 case XEventName.LeaveNotify: {
2124                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
2125                                                 return true;
2126                                         }
2127                                         msg.message=Msg.WM_MOUSE_LEAVE;
2128                                         HoverState.Timer.Enabled = false;
2129                                         HoverState.Window = IntPtr.Zero;
2130                                         break;
2131                                 }
2132
2133                                 #if later
2134                                 case XEventName.CreateNotify: {
2135                                         if (client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {
2136                                                 msg.message = WM_CREATE;
2137                                                 // Set up CreateStruct
2138                                         } else {
2139                                                 goto ProcessNextMessage;
2140                                         }
2141                                         break;
2142                                 }
2143                                 #endif
2144
2145                                 case XEventName.ConfigureNotify: {
2146                                         if (!client && (xevent.ConfigureEvent.xevent == xevent.ConfigureEvent.window)) {        // Ignore events for children (SubstructureNotify) and client areas
2147                                                 XplatUIWin32.NCCALCSIZE_PARAMS  ncp;
2148                                                 IntPtr                          ptr;
2149                                                 Rectangle                       rect;
2150
2151                                                 #if DriverDebugExtra
2152                                                         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);
2153                                                 #endif
2154                                                 msg.message = Msg.WM_WINDOWPOSCHANGED;
2155                                                 hwnd.configure_pending = false;
2156
2157                                                 // We need to adjust our client window to track the resize of whole_window
2158                                                 rect = hwnd.DefaultClientRect;
2159
2160                                                 ncp = new XplatUIWin32.NCCALCSIZE_PARAMS();
2161                                                 ptr = Marshal.AllocHGlobal(Marshal.SizeOf(ncp));
2162
2163                                                 ncp.rgrc1.left = rect.Left;
2164                                                 ncp.rgrc1.top = rect.Top;
2165                                                 ncp.rgrc1.right = rect.Right;
2166                                                 ncp.rgrc1.bottom = rect.Bottom;
2167
2168                                                 Marshal.StructureToPtr(ncp, ptr, true);
2169                                                 NativeWindow.WndProc(hwnd.client_window, Msg.WM_NCCALCSIZE, (IntPtr)1, ptr);
2170                                                 ncp = (XplatUIWin32.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(ptr, typeof(XplatUIWin32.NCCALCSIZE_PARAMS));
2171                                                 Marshal.FreeHGlobal(ptr);
2172
2173                                                 // FIXME - debug this with Menus, need to set hwnd.ClientRect
2174
2175                                                 rect = new Rectangle(ncp.rgrc1.left, ncp.rgrc1.top, ncp.rgrc1.right - ncp.rgrc1.left, ncp.rgrc1.bottom - ncp.rgrc1.top);
2176
2177                                                 XMoveResizeWindow(DisplayHandle, hwnd.client_window, rect.X, rect.Y, rect.Width, rect.Height);
2178                                         } else {
2179                                                 goto ProcessNextMessage;
2180                                         }
2181
2182                                         msg.lParam=IntPtr.Zero;         // FIXME - Generate LPWINDOWPOS structure and pass on
2183                                         break;
2184                                 }
2185
2186                                 case XEventName.FocusIn: {
2187                                         msg.message=Msg.WM_SETFOCUS;
2188                                         msg.wParam=IntPtr.Zero;
2189                                         break;
2190                                 }
2191
2192                                 case XEventName.FocusOut: {
2193                                         msg.message=Msg.WM_KILLFOCUS;
2194                                         msg.wParam=IntPtr.Zero;
2195                                         break;
2196                                 }
2197
2198                                 case XEventName.Expose: {
2199                                         if (!client) {
2200                                                 #if DriverDebugExtra
2201                                                         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);
2202                                                 #endif
2203                                                 msg.message = Msg.WM_NCPAINT;
2204                                                 hwnd.nc_expose_pending = false;
2205                                                 break;
2206                                         }
2207                                         #if DriverDebugExtra
2208                                                 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);
2209                                         #endif
2210                                         if (Caret.Visible == 1) {
2211                                                 Caret.Paused = true;
2212                                                 HideCaret();
2213                                         }
2214
2215                                         if (Caret.Visible == 1) {
2216                                                 ShowCaret();
2217                                                 Caret.Paused = false;
2218                                         }
2219                                         msg.message = Msg.WM_PAINT;
2220                                         break;
2221                                 }
2222
2223                                 case XEventName.DestroyNotify: {
2224
2225                                         // This is a bit tricky, we don't receive our own DestroyNotify, we only get those for our children
2226                                         hwnd = Hwnd.ObjectFromHandle(xevent.DestroyWindowEvent.window);
2227
2228                                         // We may get multiple for the same window, act only one the first (when Hwnd still knows about it)
2229                                         if (hwnd != null) {
2230                                                 msg.hwnd = hwnd.client_window;
2231                                                 msg.message=Msg.WM_DESTROY;
2232                                                 hwnd.Dispose();
2233
2234                                                 #if DriverDebug
2235                                                         Console.WriteLine("Got DestroyNotify on Window {0:X}", msg.hwnd.ToInt32());
2236                                                 #endif
2237                                         } else {
2238                                                 goto ProcessNextMessage;
2239                                         }
2240
2241                                         break;
2242                                 }
2243
2244                                 case XEventName.ClientMessage: {
2245                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)AsyncAtom) {
2246                                                 GCHandle                gchandle;
2247                                                 AsyncMethodData         data;
2248                                                 AsyncMethodResult       result;
2249                                                 object                  ret;
2250
2251                                                 gchandle = (GCHandle)xevent.ClientMessageEvent.ptr1;
2252                                                 data = (AsyncMethodData)gchandle.Target;
2253                                                 result = data.Result.Target as AsyncMethodResult;
2254                                                 ret = data.Method.DynamicInvoke (data.Args);
2255
2256                                                 if (result != null) {
2257                                                         result.Complete (ret);
2258                                                 }
2259                                                 gchandle.Free ();
2260                                                 break;
2261                                         }
2262
2263                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)HoverState.Atom) {
2264                                                 msg.message = Msg.WM_MOUSEHOVER;
2265                                                 msg.wParam = GetMousewParam(0);
2266                                                 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
2267                                                 break;
2268                                         }
2269
2270                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)PostAtom) {
2271                                                 msg.hwnd = xevent.ClientMessageEvent.ptr1;
2272                                                 msg.message = (Msg) xevent.ClientMessageEvent.ptr2.ToInt32 ();
2273                                                 msg.wParam = xevent.ClientMessageEvent.ptr3;
2274                                                 msg.lParam = xevent.ClientMessageEvent.ptr4;
2275                                                 break;
2276                                         }
2277
2278                                         if  (xevent.ClientMessageEvent.message_type == (IntPtr)NetAtoms[(int)NA.WM_PROTOCOLS]) {
2279                                                 if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms[(int)NA.WM_DELETE_WINDOW]) {
2280                                                         msg.message = Msg.WM_CLOSE;
2281                                                         break;
2282                                                 }
2283
2284                                                 // We should not get this, but I'll leave the code in case we need it in the future
2285                                                 if (xevent.ClientMessageEvent.ptr1 == (IntPtr)NetAtoms[(int)NA.WM_TAKE_FOCUS]) {
2286                                                         goto ProcessNextMessage;
2287                                                 }
2288                                         }
2289                                         break;
2290                                 }
2291
2292                                 case XEventName.TimerNotify: {
2293                                         xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
2294                                         break;
2295                                 }
2296                                         
2297                                 default: {
2298                                         goto ProcessNextMessage;
2299                                 }
2300                         }
2301
2302                         return GetMessageResult;
2303                 }
2304
2305                 internal override bool GetText(IntPtr handle, out string text) {
2306                         IntPtr  textptr;
2307
2308                         textptr = IntPtr.Zero;
2309
2310                         lock (XlibLock) {
2311                                 // FIXME - use _NET properties
2312                                 XFetchName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, ref textptr);
2313                         }
2314                         if (textptr != IntPtr.Zero) {
2315                                 text = Marshal.PtrToStringAnsi(textptr);
2316                                 XFree(textptr);
2317                                 return true;
2318                         } else {
2319                                 text = "";
2320                                 return false;
2321                         }
2322                 }
2323
2324                 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) {
2325                         Hwnd            hwnd;
2326                         Rectangle       rect;
2327
2328                         hwnd = Hwnd.ObjectFromHandle(handle);
2329
2330                         if (hwnd != null) {
2331                                 rect = hwnd.ClientRect;
2332
2333                                 x = hwnd.x;
2334                                 y = hwnd.y;
2335                                 width = hwnd.width;
2336                                 height = hwnd.height;
2337
2338                                 client_width = rect.Width;
2339                                 client_height = rect.Height;
2340
2341                                 return;
2342                         }
2343
2344                         // Should we throw an exception or fail silently?
2345                         // throw new ArgumentException("Called with an invalid window handle", "handle");
2346
2347                         x = 0;
2348                         y = 0;
2349                         width = 0;
2350                         height = 0;
2351                         client_width = 0;
2352                         client_height = 0;
2353                 }
2354
2355                 internal override FormWindowState GetWindowState(IntPtr handle) {
2356                         Atom                    actual_atom;
2357                         int                     actual_format;
2358                         int                     nitems;
2359                         int                     bytes_after;
2360                         IntPtr                  prop = IntPtr.Zero;
2361                         IntPtr                  atom;
2362                         int                     maximized;
2363                         XWindowAttributes       attributes;
2364                         Hwnd                    hwnd;
2365
2366                         hwnd = Hwnd.ObjectFromHandle(handle);
2367
2368                         maximized = 0;
2369                         XGetWindowProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._NET_WM_STATE], 0, 256, false, Atom.XA_ATOM, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
2370                         if ((nitems > 0) && (prop != IntPtr.Zero)) {
2371                                 for (int i = 0; i < nitems; i++) {
2372                                         atom = (IntPtr)Marshal.ReadInt32(prop, i * 4);
2373                                         if ((atom == (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ]) || (atom == (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT])) {
2374                                                 maximized++;
2375                                         }
2376                                 }
2377                                 XFree(prop);
2378                         }
2379
2380                         if (maximized == 2) {
2381                                 return FormWindowState.Maximized;
2382                         }
2383
2384
2385                         attributes = new XWindowAttributes();
2386                         XGetWindowAttributes(DisplayHandle, handle, ref attributes);
2387                         if (attributes.map_state == MapState.IsUnmapped) {
2388                                 return FormWindowState.Minimized;
2389                         }
2390
2391                         return FormWindowState.Normal;
2392                 }
2393
2394                 internal override void GrabInfo(out IntPtr handle, out bool GrabConfined, out Rectangle GrabArea) {
2395                         handle = Grab.Hwnd;
2396                         GrabConfined = Grab.Confined;
2397                         GrabArea = Grab.Area;
2398                 }
2399
2400                 internal override void GrabWindow(IntPtr handle, IntPtr confine_to_handle) {
2401                         Hwnd    hwnd;
2402                         IntPtr  confine_to_window;      
2403
2404                         confine_to_window = IntPtr.Zero;
2405
2406                         if (confine_to_handle != IntPtr.Zero) {
2407                                 XWindowAttributes       attributes = new XWindowAttributes();
2408
2409                                 hwnd = Hwnd.ObjectFromHandle(confine_to_handle);
2410
2411                                 lock (XlibLock) {
2412                                         XGetWindowAttributes(DisplayHandle, hwnd.client_window, ref attributes);
2413                                 }
2414                                 Grab.Area.X = attributes.x;
2415                                 Grab.Area.Y = attributes.y;
2416                                 Grab.Area.Width = attributes.width;
2417                                 Grab.Area.Height = attributes.height;
2418                                 Grab.Confined = true;
2419                                 confine_to_window = hwnd.client_window;
2420                         }
2421
2422                         Grab.Hwnd = handle;
2423
2424                         hwnd = Hwnd.ObjectFromHandle(handle);
2425
2426                         lock (XlibLock) {
2427                                 XGrabPointer(DisplayHandle, hwnd.client_window, false, 
2428                                         EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
2429                                         EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
2430                                         GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_to_window, 0, 0);
2431                         }
2432                 }
2433
2434                 internal override void UngrabWindow(IntPtr hwnd) {
2435                         lock (XlibLock) {
2436                                 XUngrabPointer(DisplayHandle, 0);
2437                         }
2438                         Grab.Hwnd = IntPtr.Zero;
2439                         Grab.Confined = false;
2440                 }
2441
2442                 internal override void HandleException(Exception e) {
2443                         StackTrace st = new StackTrace(e, true);
2444                         Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
2445                         Console.WriteLine("{0}{1}", e.Message, st.ToString());
2446                 }
2447
2448                 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
2449                         Hwnd    hwnd;
2450                         XEvent  xevent;
2451
2452                         hwnd = Hwnd.ObjectFromHandle(handle);
2453
2454
2455                         xevent = new XEvent ();
2456                         xevent.type = XEventName.Expose;
2457                         xevent.ExposeEvent.display = DisplayHandle;
2458                         xevent.ExposeEvent.window = Hwnd.ObjectFromHandle(handle).client_window;
2459
2460                         if (clear) {
2461                                 hwnd.erase_pending = true;
2462                                 xevent.ExposeEvent.x = hwnd.X;
2463                                 xevent.ExposeEvent.y = hwnd.Y;
2464                                 xevent.ExposeEvent.width = hwnd.Width;
2465                                 xevent.ExposeEvent.height = hwnd.Height;
2466                         } else {
2467                                 xevent.ExposeEvent.x = rc.X;
2468                                 xevent.ExposeEvent.y = rc.Y;
2469                                 xevent.ExposeEvent.width = rc.Width;
2470                                 xevent.ExposeEvent.height = rc.Height;
2471                         }
2472
2473                         AddExpose (xevent);
2474                 }
2475
2476                 internal override bool IsVisible(IntPtr handle) {
2477                         return Hwnd.ObjectFromHandle(handle).visible;
2478                 }
2479
2480                 internal override void KillTimer(Timer timer) {
2481                         lock (TimerList) {
2482                                 TimerList.Remove(timer);
2483                         }
2484                 }
2485
2486                 internal override void MenuToScreen(IntPtr handle, ref int x, ref int y) {
2487                         int     dest_x_return;
2488                         int     dest_y_return;
2489                         IntPtr  child;
2490                         Hwnd    hwnd;
2491
2492                         hwnd = Hwnd.ObjectFromHandle(handle);
2493
2494                         lock (XlibLock) {
2495                                 XTranslateCoordinates(DisplayHandle, hwnd.whole_window, RootWindow, x, y, out dest_x_return, out dest_y_return, out child);
2496                         }
2497
2498                         x = dest_x_return;
2499                         y = dest_y_return;
2500                 }
2501
2502                 internal override void OverrideCursor(IntPtr cursor) {
2503                         OverrideCursorHandle = cursor;
2504                 }
2505
2506                 internal override PaintEventArgs PaintEventStart(IntPtr handle) {
2507                         PaintEventArgs  paint_event;
2508                         Hwnd            hwnd;
2509
2510                         hwnd = Hwnd.ObjectFromHandle(handle);
2511
2512                         if (Caret.Visible == 1) {
2513                                 Caret.Paused = true;
2514                                 HideCaret();
2515                         }
2516
2517                         if (hwnd.erase_pending) {
2518                                 // In our implementation WM_ERASEBKGND always returns 1; otherwise we'd check the result and only call clear if it returned 0
2519                                 NativeWindow.WndProc(hwnd.client_window, Msg.WM_ERASEBKGND, IntPtr.Zero, IntPtr.Zero);
2520                                 hwnd.erase_pending = false;
2521                         }
2522
2523
2524                         hwnd.client_dc  = Graphics.FromHwnd (hwnd.client_window);
2525                         paint_event = new PaintEventArgs(hwnd.client_dc, hwnd.invalid);
2526
2527                         return paint_event;
2528                 }
2529
2530                 internal override void PaintEventEnd(IntPtr handle) {
2531                         Hwnd    hwnd;
2532
2533                         hwnd = Hwnd.ObjectFromHandle(handle);
2534
2535                         hwnd.ClearInvalidArea();
2536
2537                         hwnd.client_dc.Flush();
2538                         hwnd.client_dc.Dispose();
2539                         hwnd.client_dc = null;
2540
2541                         if (Caret.Visible == 1) {
2542                                 ShowCaret();
2543                                 Caret.Paused = false;
2544                         }
2545                 }
2546
2547                 internal override bool PeekMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
2548                         bool     pending;
2549
2550                         // FIXME - imlement filtering
2551
2552                         if ((flags & (uint)PeekMessageFlags.PM_REMOVE) == 0) {          
2553                                 throw new NotImplementedException("PeekMessage PM_NOREMOVE is not implemented yet");    // FIXME - Implement PM_NOREMOVE flag
2554                         }
2555
2556                         pending = false;
2557                         if (MessageQueue.Count > 0) {
2558                                 pending = true;
2559                         } else {
2560                                 // Only call UpdateMessageQueue if real events are pending 
2561                                 // otherwise we go to sleep on the socket
2562                                 if (XPending(DisplayHandle) != 0) {
2563                                         UpdateMessageQueue();
2564                                         pending = true;
2565                                 }
2566                         }
2567                         if (!pending) {
2568                                 return false;
2569                         }
2570                         return GetMessage(ref msg, hWnd, wFilterMin, wFilterMax);
2571                 }
2572
2573                 internal static void PostMessage (IntPtr handle, Msg message, IntPtr wparam, IntPtr lparam) {
2574                         XEvent xevent = new XEvent ();
2575
2576                         xevent.type = XEventName.ClientMessage;
2577                         xevent.ClientMessageEvent.display = DisplayHandle;
2578                         xevent.ClientMessageEvent.window = Hwnd.ObjectFromHandle(handle).whole_window;
2579                         xevent.ClientMessageEvent.message_type = (IntPtr) PostAtom;
2580                         xevent.ClientMessageEvent.format = 32;
2581                         xevent.ClientMessageEvent.ptr1 = handle;
2582                         xevent.ClientMessageEvent.ptr2 = (IntPtr) message;
2583                         xevent.ClientMessageEvent.ptr3 = wparam;
2584                         xevent.ClientMessageEvent.ptr4 = lparam;
2585
2586                         MessageQueue.Enqueue (xevent);
2587                 }
2588
2589                 internal override void ReleaseMenuDC(IntPtr handle, Graphics dc) {
2590                         dc.Dispose();
2591                 }
2592
2593                 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y) {
2594                         int     dest_x_return;
2595                         int     dest_y_return;
2596                         IntPtr  child;
2597                         Hwnd    hwnd;
2598
2599                         hwnd = Hwnd.ObjectFromHandle(handle);
2600
2601                         lock (XlibLock) {
2602                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
2603                         }
2604
2605                         x = dest_x_return;
2606                         y = dest_y_return;
2607                 }
2608
2609                 internal override void ScreenToMenu(IntPtr handle, ref int x, ref int y) {
2610                         int     dest_x_return;
2611                         int     dest_y_return;
2612                         IntPtr  child;
2613                         Hwnd    hwnd;
2614
2615                         hwnd = Hwnd.ObjectFromHandle(handle);
2616
2617                         lock (XlibLock) {
2618                                 XTranslateCoordinates (DisplayHandle, RootWindow, hwnd.client_window, x, y, out dest_x_return, out dest_y_return, out child);
2619                         }
2620
2621                         x = dest_x_return;
2622                         y = dest_y_return;
2623                 }
2624
2625                 internal override void ScrollWindow(IntPtr handle, Rectangle area, int XAmount, int YAmount, bool with_children) {
2626                         Hwnd            hwnd;
2627                         IntPtr          gc;
2628                         XGCValues       gc_values;
2629
2630                         hwnd = Hwnd.ObjectFromHandle(handle);
2631
2632                         if (hwnd.invalid != Rectangle.Empty) {
2633                                 // BIG FAT WARNING. This only works with how we use this function right now
2634                                 // where we basically still scroll the whole window, but work around areas
2635                                 // that are covered by our children
2636
2637                                 hwnd.invalid.X += XAmount;
2638                                 hwnd.invalid.Y += YAmount;
2639
2640                                 if (hwnd.invalid.X < 0) {
2641                                         hwnd.invalid.Width += hwnd.invalid.X;
2642                                         hwnd.invalid.X =0;
2643                                 }
2644
2645                                 if (hwnd.invalid.Y < 0) {
2646                                         hwnd.invalid.Height += hwnd.invalid.Y;
2647                                         hwnd.invalid.Y =0;
2648                                 }
2649                         }
2650
2651                         gc_values = new XGCValues();
2652
2653                         if (with_children) {
2654                                 gc_values.subwindow_mode = GCSubwindowMode.IncludeInferiors;
2655                         }
2656
2657                         gc = XCreateGC(DisplayHandle, hwnd.client_window, 0, ref gc_values);
2658
2659                         XCopyArea(DisplayHandle, hwnd.client_window, hwnd.client_window, gc, area.X - XAmount, area.Y - YAmount, area.Width, area.Height, area.X, area.Y);
2660                         
2661                         // Generate an expose for the area exposed by the horizontal scroll
2662                         if (XAmount > 0) {
2663                                 hwnd.AddInvalidArea (area.X, area.Y, XAmount, area.Height);
2664                         } else if (XAmount < 0) {
2665                                 hwnd.AddInvalidArea (XAmount + area.X + area.Width, area.Y, -XAmount, area.Height);
2666                         }
2667
2668                         // Generate an expose for the area exposed by the vertical scroll
2669                         if (YAmount > 0) {
2670                                 hwnd.AddInvalidArea (area.X, area.Y, area.Width, YAmount);
2671                         } else if (YAmount < 0) {
2672                                 hwnd.AddInvalidArea (area.X, YAmount + area.Y + area.Height, area.Width, -YAmount);
2673                         }
2674                         XFreeGC(DisplayHandle, gc);
2675
2676                         UpdateWindow(handle);
2677                 }
2678
2679                 internal override void ScrollWindow(IntPtr handle, int XAmount, int YAmount, bool with_children) {
2680                         Hwnd    hwnd;
2681
2682                         hwnd = Hwnd.GetObjectFromWindow(handle);
2683         
2684                         ScrollWindow(handle, hwnd.ClientRect, XAmount, YAmount, with_children);
2685                 }
2686
2687                 internal override void SendAsyncMethod (AsyncMethodData method) {
2688                         XEvent xevent = new XEvent ();
2689
2690                         xevent.type = XEventName.ClientMessage;
2691                         xevent.ClientMessageEvent.display = DisplayHandle;
2692                         xevent.ClientMessageEvent.window = IntPtr.Zero;
2693                         xevent.ClientMessageEvent.message_type = (IntPtr)AsyncAtom;
2694                         xevent.ClientMessageEvent.format = 32;
2695                         xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
2696
2697                         MessageQueue.EnqueueLocked (xevent);
2698
2699                         WakeupMain ();
2700                 }
2701
2702                 internal override void SetBorderStyle(IntPtr handle, BorderStyle border_style) {
2703                         Hwnd    hwnd;
2704
2705                         hwnd = Hwnd.ObjectFromHandle(handle);
2706                         hwnd.border_style = border_style;
2707
2708                         // FIXME - do we need to trigger some resize?
2709                 }
2710
2711                 internal override void SetCaretPos(IntPtr handle, int x, int y) {
2712                         if (Caret.Hwnd == handle) {
2713                                 Caret.Timer.Stop();
2714                                 HideCaret();
2715
2716                                 Caret.X = x;
2717                                 Caret.Y = y;
2718
2719                                 if (Caret.Visible == 1) {
2720                                         ShowCaret();
2721                                         Caret.Timer.Start();
2722                                 }
2723                         }
2724                 }
2725
2726                 internal override void SetCursor(IntPtr handle, IntPtr cursor) {
2727                         Hwnd    hwnd;
2728
2729                         if (OverrideCursorHandle == IntPtr.Zero) {
2730                                 if ((LastCursorWindow == handle) && (LastCursorHandle == cursor)) {
2731                                         return;
2732                                 }
2733
2734                                 LastCursorHandle = cursor;
2735                                 LastCursorWindow = handle;
2736
2737                                 hwnd = Hwnd.ObjectFromHandle(handle);
2738                                 lock (XlibLock) {
2739                                         if (cursor != IntPtr.Zero) {
2740                                                 XDefineCursor(DisplayHandle, hwnd.whole_window, cursor);
2741                                         } else {
2742                                                 XUndefineCursor(DisplayHandle, hwnd.whole_window);
2743                                         }
2744                                 }
2745                                 return;
2746                         }
2747
2748                         hwnd = Hwnd.ObjectFromHandle(handle);
2749                         lock (XlibLock) {
2750                                 XDefineCursor(DisplayHandle, hwnd.whole_window, OverrideCursorHandle);
2751                         }
2752                 }
2753
2754                 internal override void SetCursorPos(IntPtr handle, int x, int y) {
2755                         if (handle == IntPtr.Zero) {
2756                                 lock (XlibLock) {
2757                                         XWarpPointer(DisplayHandle, IntPtr.Zero, IntPtr.Zero, 0, 0, 0, 0, x, y);
2758                                 }
2759                                 return;
2760                         } else {
2761                                 Hwnd    hwnd;
2762
2763                                 hwnd = Hwnd.ObjectFromHandle(handle);
2764                                 lock (XlibLock) {
2765                                         XWarpPointer(DisplayHandle, IntPtr.Zero, hwnd.client_window, 0, 0, 0, 0, x, y);
2766                                 }
2767                                 return;
2768                         }
2769                 }
2770
2771                 internal override void SetFocus(IntPtr handle) {
2772                         Hwnd    hwnd;
2773
2774                         hwnd = Hwnd.ObjectFromHandle(handle);
2775
2776                         if (FocusWindow != IntPtr.Zero) {
2777                                 PostMessage(FocusWindow, Msg.WM_KILLFOCUS, hwnd.client_window, IntPtr.Zero);
2778                         }
2779                         PostMessage(hwnd.client_window, Msg.WM_SETFOCUS, FocusWindow, IntPtr.Zero);
2780                         FocusWindow = hwnd.client_window;
2781
2782                         //XSetInputFocus(DisplayHandle, Hwnd.ObjectFromHandle(handle).client_window, RevertTo.None, IntPtr.Zero);
2783                 }
2784
2785                 internal override void SetIcon(IntPtr handle, Icon icon) {
2786                         Hwnd    hwnd;
2787
2788                         hwnd = Hwnd.ObjectFromHandle(handle);
2789                         if (hwnd != null) {
2790                                 SetIcon(hwnd, icon);
2791                         }
2792                 }
2793
2794                 internal override void SetMenu(IntPtr handle, IntPtr menu_handle) {
2795                         Hwnd    hwnd;
2796
2797                         hwnd = Hwnd.ObjectFromHandle(handle);
2798                         hwnd.menu_handle = menu_handle;
2799
2800                         // FIXME - do we need to trigger some resize?
2801                 }
2802
2803                 internal override void SetModal(IntPtr handle, bool Modal) {
2804                         if (Modal) {
2805                                 ModalWindows.Push(handle);
2806                         } else {
2807                                 if (ModalWindows.Contains(handle)) {
2808                                         ModalWindows.Pop();
2809                                 }
2810                                 if (ModalWindows.Count > 0) {
2811                                         Activate((IntPtr)ModalWindows.Peek());
2812                                 }
2813                         }
2814                 }
2815
2816                 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
2817                         Hwnd    hwnd;
2818
2819                         hwnd = Hwnd.ObjectFromHandle(handle);
2820                         hwnd.parent = Hwnd.ObjectFromHandle(parent);
2821
2822                         lock (XlibLock) {
2823                                 #if DriverDebug
2824                                         Console.WriteLine("Parent for window {0:X} / {1:X} = {2:X} (Handle:{3:X})", hwnd.ClientWindow.ToInt32(), hwnd.WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, parent.ToInt32());
2825                                 #endif
2826                                 XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent.client_window, hwnd.x, hwnd.y);
2827                         }
2828
2829                         return IntPtr.Zero;
2830                 }
2831
2832                 internal override void SetTimer (Timer timer) {
2833                         lock (TimerList) {
2834                                 TimerList.Add(timer);
2835                         }
2836                         WakeupMain ();
2837                 }
2838
2839                 internal override bool SetTopmost(IntPtr handle, IntPtr handle_owner, bool enabled) {
2840                         Hwnd    hwnd;
2841                         Hwnd    hwnd_owner;
2842
2843                         hwnd = Hwnd.ObjectFromHandle(handle);
2844
2845                         if (handle_owner != IntPtr.Zero) {
2846                                 hwnd_owner = Hwnd.ObjectFromHandle(handle_owner);
2847                         } else {
2848                                 hwnd_owner = null;
2849                         }
2850
2851                         if (enabled) {
2852                                 lock (XlibLock) {
2853                                         if (hwnd_owner != null) {
2854                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, hwnd_owner.whole_window);
2855                                         } else {
2856                                                 XSetTransientForHint(DisplayHandle, hwnd.whole_window, FosterParent);
2857                                         }
2858                                 }
2859                         } else {
2860                                 lock (XlibLock) {
2861                                         XDeleteProperty(DisplayHandle, hwnd.whole_window, (int)Atom.XA_WM_TRANSIENT_FOR);
2862                                 }
2863                         }
2864                         return true;
2865                 }
2866
2867                 internal override bool SetVisible(IntPtr handle, bool visible) {
2868                         Hwnd    hwnd;
2869
2870                         hwnd = Hwnd.ObjectFromHandle(handle);
2871                         hwnd.visible = visible;
2872
2873                         lock (XlibLock) {
2874                                 if (visible) {
2875                                         XMapWindow(DisplayHandle, hwnd.whole_window);
2876                                         XMapWindow(DisplayHandle, hwnd.client_window);
2877                                 } else {
2878                                         XUnmapWindow(DisplayHandle, hwnd.whole_window);
2879                                 }
2880                         }
2881                         return true;
2882                 }
2883
2884                 internal override void SetWindowBackground(IntPtr handle, Color color) {
2885                         XColor  xcolor;
2886                         Hwnd    hwnd;
2887
2888                         hwnd = Hwnd.ObjectFromHandle(handle);
2889                         xcolor = new XColor();
2890
2891                         xcolor.red = (ushort)(color.R * 257);
2892                         xcolor.green = (ushort)(color.G * 257);
2893                         xcolor.blue = (ushort)(color.B * 257);
2894
2895                         lock (XlibLock) {
2896                                 XAllocColor(DisplayHandle, DefaultColormap, ref xcolor);
2897                                 XSetWindowBackground(DisplayHandle, hwnd.client_window, xcolor.pixel);
2898                                 XClearWindow(DisplayHandle, hwnd.client_window);
2899                         }
2900                 }
2901
2902                 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
2903                         Hwnd            hwnd;
2904                         Rectangle       client_rect;
2905
2906                         hwnd = Hwnd.ObjectFromHandle(handle);
2907                         // Save a server roundtrip (and prevent a feedback loop)
2908                         if ((hwnd.x == x) && (hwnd.y == y) && (hwnd.width == width) && (hwnd.height == height)) {
2909                                 return;
2910                         }
2911
2912                         // X requires a sanity check for width & height; otherwise it dies
2913                         if (width < 1) {
2914                                 width = 1;
2915                         }
2916
2917                         if (height < 1) {
2918                                 height = 1;
2919                         }
2920
2921                         client_rect = Hwnd.GetClientRectangle(hwnd.border_style, hwnd.menu_handle, hwnd.title_style, width, height);
2922
2923                         lock (XlibLock) {
2924                                 XMoveResizeWindow(DisplayHandle, hwnd.whole_window, x, y, width, height);
2925                                 XMoveResizeWindow(DisplayHandle, hwnd.client_window, client_rect.X, client_rect.Y, client_rect.Width, client_rect.Height);
2926                         }
2927
2928                         // Prevent an old queued ConfigureNotify from setting our width with outdated data, set it now
2929                         hwnd.width = width;
2930                         hwnd.height = height;
2931                 }
2932
2933                 internal override void SetWindowState(IntPtr handle, FormWindowState state) {
2934                         FormWindowState current_state;
2935                         Hwnd            hwnd;
2936
2937                         hwnd = Hwnd.ObjectFromHandle(handle);
2938
2939                         current_state = GetWindowState(handle);
2940
2941                         if (current_state == state) {
2942                                 return;
2943                         }
2944
2945                         switch(state) {
2946                                 case FormWindowState.Normal: {
2947                                         lock (XlibLock) {
2948                                                 if (current_state == FormWindowState.Minimized) {
2949                                                         XMapWindow(DisplayHandle, hwnd.whole_window);
2950                                                         XMapWindow(DisplayHandle, hwnd.client_window);
2951                                                 } else if (current_state == FormWindowState.Maximized) {
2952                                                         SendNetWMMessage(hwnd.whole_window, (IntPtr)(uint)NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
2953                                                 }
2954                                         }
2955                                         Activate(handle);
2956                                         return;
2957                                 }
2958
2959                                 case FormWindowState.Minimized: {
2960                                         lock (XlibLock) {
2961                                                 if (current_state == FormWindowState.Maximized) {
2962                                                         SendNetWMMessage(hwnd.whole_window, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)2 /* toggle */, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
2963                                                 }
2964                                                 XIconifyWindow(DisplayHandle, hwnd.whole_window, 0);
2965                                         }
2966                                         return;
2967                                 }
2968
2969                                 case FormWindowState.Maximized: {
2970                                         lock (XlibLock) {
2971                                                 if (current_state == FormWindowState.Minimized) {
2972                                                         XMapWindow(DisplayHandle, hwnd.whole_window);
2973                                                         XMapWindow(DisplayHandle, hwnd.client_window);
2974                                                 }
2975
2976                                                 SendNetWMMessage(hwnd.whole_window, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE], (IntPtr)1 /* Add */, (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_HORZ], (IntPtr)NetAtoms[(int)NA._NET_WM_STATE_MAXIMIZED_VERT]);
2977                                         }
2978                                         Activate(handle);
2979                                         return;
2980                                 }
2981                         }
2982                 }
2983
2984                 internal override void SetWindowStyle(IntPtr handle, CreateParams cp) {
2985                         Hwnd    hwnd;
2986
2987                         hwnd = Hwnd.ObjectFromHandle(handle);
2988                         SetHwndStyles(hwnd, cp);
2989                         SetWMStyles(hwnd, cp);
2990                 }
2991                 internal override bool SetZOrder(IntPtr handle, IntPtr after_handle, bool top, bool bottom) {
2992                         Hwnd    hwnd;
2993                         Hwnd    after_hwnd;
2994
2995                         hwnd = Hwnd.ObjectFromHandle(handle);
2996                         if (after_handle != IntPtr.Zero) {
2997                                 after_hwnd = Hwnd.ObjectFromHandle(after_handle);
2998                         } else {
2999                                 after_hwnd = null;
3000                         }
3001
3002                         if (top) {
3003                                 lock (XlibLock) {
3004                                         XRaiseWindow(DisplayHandle, hwnd.whole_window);
3005                                 }
3006                                 return true;
3007                         } else if (!bottom) {
3008                                 XWindowChanges  values = new XWindowChanges();
3009
3010                                 if (after_hwnd == null) {
3011                                         throw new ArgumentNullException("after_handle", "Need sibling to adjust z-order");
3012                                 }
3013                                 values.sibling = after_hwnd.whole_window;
3014                                 values.stack_mode = StackMode.Below;
3015
3016                                 lock (XlibLock) {
3017                                         XConfigureWindow(DisplayHandle, hwnd.whole_window, ChangeWindowFlags.CWStackMode | ChangeWindowFlags.CWSibling, ref values);
3018                                 }
3019                         } else {
3020                                 // Bottom
3021                                 lock (XlibLock) {
3022                                         XLowerWindow(DisplayHandle, hwnd.whole_window);
3023                                 }
3024                                 return true;
3025                         }
3026                         return false;
3027                 }
3028
3029                 internal override void ShowCursor(bool show) {
3030                         ;       // FIXME - X11 doesn't 'hide' the cursor. we could create an empty cursor
3031                 }
3032
3033                 internal override bool SystrayAdd(IntPtr handle, string tip, Icon icon, out ToolTip tt) {
3034                         GetSystrayManagerWindow();
3035
3036                         if (SystrayMgrWindow != IntPtr.Zero) {
3037                                 uint[]          atoms;
3038                                 XSizeHints      size_hints;
3039                                 Hwnd            hwnd;
3040
3041                                 hwnd = Hwnd.ObjectFromHandle(handle);
3042
3043                                 size_hints = new XSizeHints();
3044
3045                                 size_hints.flags = (IntPtr)(XSizeHintsFlags.PMinSize | XSizeHintsFlags.PMaxSize | XSizeHintsFlags.PBaseSize);
3046                                 size_hints.min_width = icon.Width;
3047                                 size_hints.min_height = icon.Height;
3048
3049                                 size_hints.max_width = icon.Width;
3050                                 size_hints.max_height = icon.Height;
3051
3052                                 size_hints.base_width = icon.Width;
3053                                 size_hints.base_height = icon.Height;
3054                                 XSetWMNormalHints(DisplayHandle, hwnd.whole_window, ref size_hints);
3055
3056                                 atoms = new uint[2];
3057                                 atoms[0] = 1;   // Version 1
3058                                 atoms[1] = 1;   // We're not mapped
3059
3060                                 // This line cost me 3 days...
3061                                 XChangeProperty(DisplayHandle, hwnd.whole_window, NetAtoms[(int)NA._XEMBED_INFO], NetAtoms[(int)NA._XEMBED_INFO], 32, PropertyMode.Replace, atoms, 2);
3062
3063                                 // Need to pick some reasonable defaults
3064                                 tt = new ToolTip();
3065                                 tt.AutomaticDelay = 100;
3066                                 tt.InitialDelay = 250;
3067                                 tt.ReshowDelay = 250;
3068                                 tt.ShowAlways = true;
3069
3070                                 if ((tip != null) && (tip != string.Empty)) {
3071                                         tt.SetToolTip(Control.FromHandle(handle), tip);
3072                                         tt.Active = true;
3073                                 } else {
3074                                         tt.Active = false;
3075                                 }
3076
3077                                 // Make sure the window exists
3078                                 XSync(DisplayHandle, hwnd.whole_window);
3079
3080                                 SendNetClientMessage(SystrayMgrWindow, (IntPtr)NetAtoms[(int)NA._NET_SYSTEM_TRAY_OPCODE], IntPtr.Zero, (IntPtr)SystrayRequest.SYSTEM_TRAY_REQUEST_DOCK, hwnd.whole_window);
3081                                 return true;
3082                         }
3083                         tt = null;
3084                         return false;
3085                 }
3086
3087                 internal override bool SystrayChange(IntPtr handle, string tip, Icon icon, ref ToolTip tt) {
3088                         Control control;
3089
3090                         control = Control.FromHandle(handle);
3091                         if (control != null && tt != null) {
3092                                 tt.SetToolTip(control, tip);
3093                                 tt.Active = true;
3094                                 return true;
3095                         } else {
3096                                 return false;
3097                         }
3098                 }
3099
3100                 internal override void SystrayRemove(IntPtr handle, ref ToolTip tt) {
3101                         Hwnd    hwnd;
3102
3103                         hwnd = Hwnd.ObjectFromHandle(handle);
3104
3105                         XUnmapWindow(DisplayHandle, hwnd.whole_window);
3106                         SetParent(hwnd.whole_window, FosterParent);
3107
3108                         // The caller can now re-dock it later...
3109                         if (tt != null) {
3110                                 tt.Dispose();
3111                                 tt = null;
3112                         }
3113                 }
3114
3115                 internal override bool Text(IntPtr handle, string text) {
3116                         lock (XlibLock) {
3117                                 // FIXME - use _NET properties
3118                                 XStoreName(DisplayHandle, Hwnd.ObjectFromHandle(handle).whole_window, text);
3119                         }
3120                         return true;
3121                 }
3122
3123                 internal override bool TranslateMessage(ref MSG msg) {
3124                         return Keyboard.TranslateMessage (ref msg);
3125                 }
3126
3127                 internal override void UpdateWindow(IntPtr handle) {
3128                         XEvent  xevent;
3129                         Hwnd    hwnd;
3130
3131                         hwnd = Hwnd.ObjectFromHandle(handle);
3132
3133                         if (!hwnd.visible || hwnd.expose_pending) {
3134                                 return;
3135                         }
3136
3137                         xevent = new XEvent();
3138                         xevent.type = XEventName.Expose;
3139                         xevent.ExposeEvent.display = DisplayHandle;
3140                         xevent.ExposeEvent.window = hwnd.client_window;
3141
3142                         MessageQueue.Enqueue(xevent);
3143                         hwnd.expose_pending = true;
3144                 }
3145                 #endregion      // Public Static Methods
3146
3147                 #region Events
3148                 internal override event EventHandler Idle;
3149                 #endregion      // Events
3150
3151                 #region X11 Imports
3152                 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
3153                 internal extern static IntPtr XOpenDisplay(IntPtr display);
3154                 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
3155                 internal extern static int XCloseDisplay(IntPtr display);                                                   
3156                 [DllImport ("libX11", EntryPoint="XSynchronize")]
3157                 internal extern static IntPtr XSynchronize(IntPtr display, bool onoff);
3158
3159                 [DllImport ("libX11", EntryPoint="XCreateWindow")]
3160                 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, SetWindowValuemask valuemask, ref XSetWindowAttributes attributes);
3161                 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
3162                 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int border, int background);
3163                 [DllImport ("libX11", EntryPoint="XMapWindow")]
3164                 internal extern static int XMapWindow(IntPtr display, IntPtr window);
3165                 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
3166                 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
3167                 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
3168                 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
3169                 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
3170                 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
3171                 [DllImport ("libX11", EntryPoint="XRootWindow")]
3172                 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
3173                 [DllImport ("libX11", EntryPoint="XNextEvent")]
3174                 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
3175                 [DllImport ("libX11")]
3176                 internal extern static int XConnectionNumber (IntPtr diplay);
3177                 [DllImport ("libX11")]
3178                 internal extern static int XPending (IntPtr diplay);
3179                 [DllImport ("libX11")]
3180                 internal extern static bool XCheckWindowEvent (IntPtr display, IntPtr window, EventMask mask, ref XEvent xevent);
3181                 [DllImport ("libX11")]
3182                 internal extern static bool XCheckMaskEvent (IntPtr display, EventMask mask, ref XEvent xevent);
3183                 [DllImport ("libX11", EntryPoint="XSelectInput")]
3184                 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, EventMask mask);
3185
3186                 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
3187                 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
3188
3189                 [DllImport ("libX11", EntryPoint="XReparentWindow")]
3190                 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
3191                 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
3192                 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
3193
3194                 [DllImport ("libX11", EntryPoint="XResizeWindow")]
3195                 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
3196
3197                 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
3198                 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
3199
3200                 [DllImport ("libX11", EntryPoint="XFlush")]
3201                 internal extern static int XFlush(IntPtr display);
3202
3203                 [DllImport ("libX11", EntryPoint="XSetWMName")]
3204                 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
3205
3206                 [DllImport ("libX11", EntryPoint="XStoreName")]
3207                 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
3208
3209                 [DllImport ("libX11", EntryPoint="XFetchName")]
3210                 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
3211
3212                 [DllImport ("libX11", EntryPoint="XSendEvent")]
3213                 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event);
3214
3215                 [DllImport ("libX11", EntryPoint="XQueryTree")]
3216                 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);
3217
3218                 [DllImport ("libX11", EntryPoint="XFree")]
3219                 internal extern static int XFree(IntPtr data);
3220
3221                 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
3222                 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
3223
3224                 [DllImport ("libX11", EntryPoint="XLowerWindow")]
3225                 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
3226
3227                 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
3228                 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
3229
3230                 [DllImport ("libX11", EntryPoint="XInternAtom")]
3231                 internal extern static int XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
3232
3233                 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
3234                 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, uint[] protocols, int count);
3235
3236                 [DllImport ("libX11", EntryPoint="XGrabPointer")]
3237                 internal extern static int XGrabPointer(IntPtr display, IntPtr window, bool owner_events, EventMask event_mask, GrabMode pointer_mode, GrabMode keyboard_mode, IntPtr confine_to, uint cursor, uint timestamp);
3238
3239                 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
3240                 internal extern static int XUngrabPointer(IntPtr display, uint timestamp);
3241
3242                 [DllImport ("libX11", EntryPoint="XQueryPointer")]
3243                 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);
3244
3245                 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
3246                 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);
3247
3248                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
3249                 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);
3250
3251                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
3252                 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);
3253
3254                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
3255                 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);
3256
3257                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
3258                 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);
3259
3260                 [DllImport ("libX11", EntryPoint="XWarpPointer")]
3261                 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);
3262
3263                 [DllImport ("libX11", EntryPoint="XClearWindow")]
3264                 internal extern static int XClearWindow(IntPtr display, IntPtr window);
3265
3266                 [DllImport ("libX11", EntryPoint="XClearArea")]
3267                 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, int width, int height, bool exposures);
3268
3269                 // Colormaps
3270                 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
3271                 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
3272
3273                 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
3274                 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
3275
3276                 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
3277                 internal extern static IntPtr XDefaultVisual(IntPtr display, int screen_number);
3278
3279                 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
3280                 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
3281
3282                 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
3283                 internal extern static IntPtr XDefaultColormap(IntPtr display, int screen_number);
3284
3285                 [DllImport ("libX11", EntryPoint="XLookupColor")]
3286                 internal extern static int XLookupColor(IntPtr display, IntPtr Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
3287
3288                 [DllImport ("libX11", EntryPoint="XAllocColor")]
3289                 internal extern static int XAllocColor(IntPtr display, IntPtr Colormap, ref XColor colorcell_def);
3290
3291                 [DllImport ("libX11", EntryPoint="XSetTransientForHint")]
3292                 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
3293
3294                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
3295                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int type, int format, PropertyMode  mode, ref MotifWmHints data, int nelements);
3296
3297                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
3298                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, Atom format, int type, PropertyMode  mode, uint[] atoms, int nelements);
3299
3300                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
3301                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int format, int type, PropertyMode  mode, uint[] atoms, int nelements);
3302
3303                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
3304                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int format, int type, PropertyMode  mode, IntPtr atoms, int nelements);
3305
3306                 [DllImport ("libX11", EntryPoint="XChangeProperty")]
3307                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, Atom format, int type, PropertyMode  mode, IntPtr atoms, int nelements);
3308
3309                 [DllImport ("libX11", EntryPoint="XDeleteProperty")]
3310                 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, int property);
3311
3312                 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
3313                 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
3314
3315                 // Drawing
3316                 [DllImport ("libX11", EntryPoint="XCreateGC")]
3317                 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, GCFunction valuemask, ref XGCValues values);
3318
3319                 [DllImport ("libX11", EntryPoint="XFreeGC")]
3320                 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
3321
3322                 [DllImport ("libX11", EntryPoint="XSetFunction")]
3323                 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
3324
3325                 [DllImport ("libX11", EntryPoint="XDrawLine")]
3326                 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
3327
3328                 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
3329                 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, IntPtr background);
3330
3331                 [DllImport ("libX11", EntryPoint="XCopyArea")]
3332                 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);
3333
3334                 [DllImport ("libX11", EntryPoint="XGetAtomName")]
3335                 internal extern static string XGetAtomName(IntPtr display, int atom);
3336
3337                 [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
3338                 internal extern static int XGetWindowProperty(IntPtr display, IntPtr window, int atom, int long_offset, int long_length, bool delete, Atom req_type, out Atom actual_type, out int actual_format, out int nitems, out int bytes_after, ref IntPtr prop);
3339
3340                 [DllImport ("libX11", EntryPoint="XSetInputFocus")]
3341                 internal extern static int XSetInputFocus(IntPtr display, IntPtr window, RevertTo revert_to, IntPtr time);
3342
3343                 [DllImport ("libX11", EntryPoint="XIconifyWindow")]
3344                 internal extern static int XIconifyWindow(IntPtr display, IntPtr window, int screen_number);
3345
3346                 [DllImport ("libX11", EntryPoint="XDefineCursor")]
3347                 internal extern static int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
3348
3349                 [DllImport ("libX11", EntryPoint="XUndefineCursor")]
3350                 internal extern static int XUndefineCursor(IntPtr display, IntPtr window);
3351
3352                 [DllImport ("libX11", EntryPoint="XFreeCursor")]
3353                 internal extern static int XFreeCursor(IntPtr display, IntPtr cursor);
3354
3355                 [DllImport ("libX11", EntryPoint="XCreateFontCursor")]
3356                 internal extern static IntPtr XCreateFontCursor(IntPtr display, CursorFontShape shape);
3357
3358                 [DllImport ("libX11", EntryPoint="XCreatePixmapCursor")]
3359                 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);
3360
3361                 [DllImport ("libX11", EntryPoint="XCreatePixmapFromBitmapData")]
3362                 internal extern static IntPtr XCreatePixmapFromBitmapData(IntPtr display, IntPtr drawable, byte[] data, int width, int height, IntPtr fg, IntPtr bg, int depth);
3363
3364                 [DllImport ("libX11", EntryPoint="XFreePixmap")]
3365                 internal extern static IntPtr XFreePixmap(IntPtr display, IntPtr pixmap);
3366
3367                 [DllImport ("libX11", EntryPoint="XQueryBestCursor")]
3368                 internal extern static int XQueryBestCursor(IntPtr display, IntPtr drawable, int width, int height, out int best_width, out int best_height);
3369
3370                 [DllImport ("libX11", EntryPoint="XWhitePixel")]
3371                 internal extern static IntPtr XWhitePixel(IntPtr display, int screen_no);
3372
3373                 [DllImport ("libX11", EntryPoint="XBlackPixel")]
3374                 internal extern static IntPtr XBlackPixel(IntPtr display, int screen_no);
3375
3376                 [DllImport ("libX11", EntryPoint="XGrabServer")]
3377                 internal extern static void XGrabServer(IntPtr display);
3378
3379                 [DllImport ("libX11", EntryPoint="XUngrabServer")]
3380                 internal extern static void XUngrabServer(IntPtr display);
3381
3382                 [DllImport ("libX11", EntryPoint="XGetSelectionOwner")]
3383                 internal extern static IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
3384
3385                 [DllImport ("libX11", EntryPoint="XSetWMNormalHints")]
3386                 internal extern static void XSetWMNormalHints(IntPtr display, IntPtr window, ref XSizeHints hints);
3387
3388                 [DllImport ("libX11", EntryPoint="XSetWMHints")]
3389                 internal extern static void XSetWMHints(IntPtr display, IntPtr window, ref XWMHints wmhints);
3390
3391                 [DllImport ("libX11", EntryPoint="XSync")]
3392                 internal extern static void XSync(IntPtr display, IntPtr window);
3393
3394                 [DllImport ("libX11", EntryPoint="XGetIconSizes")]
3395                 internal extern static int XGetIconSizes(IntPtr display, IntPtr window, out IntPtr size_list, out int count);
3396
3397                 [DllImport ("libX11", EntryPoint="XSetErrorHandler")]
3398                 internal extern static IntPtr XSetErrorHandler(XErrorHandler error_handler);
3399
3400                 [DllImport ("libX11", EntryPoint="XGetErrorText")]
3401                 internal extern static IntPtr XGetErrorText(IntPtr display, byte code, StringBuilder buffer, int length);
3402
3403                 [DllImport ("libX11", EntryPoint="XInitThreads")]\r
3404                 internal extern static int XInitThreads();\r
3405                 #endregion
3406         }
3407 }