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