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