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