* XplatUIX11.cs: When generating mouse wparams get the modifier
[mono.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / XplatUIX11.cs
1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
8 // 
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 // 
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19 //
20 // Copyright (c) 2004 Novell, Inc.
21 //
22 // Authors:
23 //      Peter Bartok    pbartok@novell.com
24 //
25 //
26
27 // NOT COMPLETE
28
29 using System;
30 using System.Threading;
31 using System.Drawing;
32 using System.ComponentModel;
33 using System.Collections;
34 using System.Diagnostics;
35 using System.Runtime.InteropServices;
36 using System.Net;
37 using System.Net.Sockets;
38
39 // Only do the poll when building with mono for now
40 #if __MonoCS__
41 using Mono.Unix;
42 #endif
43
44 /// X11 Version
45 namespace System.Windows.Forms {
46         internal class XplatUIX11 : XplatUIDriver {
47                 #region Structure Definitions
48                 internal struct Caret {
49                         internal Timer  timer;                          // Blink interval
50                         internal IntPtr hwnd;                           // Window owning the caret
51                         internal int    x;                              // X position of the caret
52                         internal int    y;                              // Y position of the caret
53                         internal int    width;                          // Width of the caret; if no image used
54                         internal int    height;                         // Height of the caret, if no image used
55                         internal int    visible;                        // Counter for visible/hidden
56                         internal bool   on;                             // Caret blink display state: On/Off
57                         internal IntPtr gc;                             // Graphics context
58                         internal bool   paused;                         // Don't update right now
59                 }
60
61                 internal struct Hover {
62                         internal Timer  timer;                          // for hovering
63                         internal IntPtr hwnd;                           // Last window we entered; used to generate WM_MOUSEHOVER
64                         internal int    x;                              // Last MouseMove X coordinate; used to generate WM_MOUSEHOVER
65                         internal int    y;                              // Last MouseMove Y coordinate; used to generate WM_MOUSEHOVER
66                         internal int    interval;                       // in milliseconds, how long to hold before hover is generated
67                         internal int    hevent;                         // X Atom
68                 }
69                 #endregion      // Structure Definitions
70
71                 #region Local Variables
72                 private static XplatUIX11       instance;
73                 private static int              ref_count;
74                 private static bool             themes_enabled;
75
76                 private static IntPtr           DisplayHandle;          // X11 handle to display
77                 private static int              screen_num;             // Screen number used
78                 private static IntPtr           root_window;            // Handle of the root window for the screen/display
79                 private static IntPtr           FosterParent;           // Container to hold child windows until their parent exists
80                 private static int              wm_protocols;           // X Atom
81                 private static int              wm_delete_window;       // X Atom
82                 private static int              mwm_hints;              // X Atom
83                 private static int              wm_no_taskbar;          // X Atom
84                 private static int              wm_state_above;         // X Atom
85                 private static int              atom;                   // X Atom
86                 private static int              net_wm_state;           // X Atom
87                 private static int              async_method;
88                 private static int              post_message;
89                 private static uint             default_colormap;       // X Colormap ID
90                 internal static Keys            key_state;
91                 internal static MouseButtons    mouse_state;
92                 internal static Point           mouse_position;
93                 internal static bool            grab_confined;          // Is the current grab (if any) confined to grab_area?
94                 internal static IntPtr          grab_hwnd;              // The window that is grabbed
95                 internal static Rectangle       grab_area;              // The area the current grab is confined to
96                 internal static IntPtr          click_pending_hwnd;     // 
97                 internal static Msg             click_pending_message;  // 
98                 internal static IntPtr          click_pending_lparam;   // 
99                 internal static IntPtr          click_pending_wparam;   // 
100                 internal static int             click_pending_time;     // Last time we received a mouse click
101                 internal static bool            click_pending;          // True if we haven't sent the last mouse click
102                 internal static int             double_click_interval;  // in milliseconds, how fast one has to click for a double click
103                 internal static Hover           hover;
104
105                 internal static Caret           caret;                  // To display a blinking caret
106
107                 private static Hashtable        handle_data;
108                 private static XEventQueue      message_queue;
109
110                 private X11Keyboard keyboard;
111                 private ArrayList timer_list;
112                 private Thread timer_thread;
113                 private AutoResetEvent timer_wait;
114                 private Socket listen;
115                 private Socket wake;
116
117 #if __MonoCS__
118                 private Pollfd [] pollfds;
119 #endif
120
121                 private object xlib_lock = new object ();
122
123                 private static readonly EventMask  SelectInputMask = EventMask.ButtonPressMask | 
124                                 EventMask.ButtonReleaseMask | 
125                                 EventMask.KeyPressMask | 
126                                 EventMask.KeyReleaseMask | 
127                                 EventMask.EnterWindowMask | 
128                                 EventMask.LeaveWindowMask |
129                                 EventMask.ExposureMask |
130                                 EventMask.PointerMotionMask | 
131                                 EventMask.VisibilityChangeMask |
132                                 EventMask.StructureNotifyMask;
133
134                 #endregion      // Local Variables
135
136                 #region Properties
137                 internal override Keys ModifierKeys {
138                         get {
139                                 return keyboard.ModifierKeys;
140                         }
141                 }
142
143                 internal override MouseButtons MouseButtons {
144                         get {
145                                 return mouse_state;
146                         }
147                 }
148
149                 internal override Point MousePosition {
150                         get {
151                                 return mouse_position;
152                         }
153                 }
154
155                 internal override bool DropTarget {
156                         get {
157                                 return false;
158                         }
159
160                         set {
161                                 if (value) {
162                                         throw new NotImplementedException("Need to figure out D'n'D for X11");
163                                 }
164                         }
165                 }
166                 // Keyboard
167                 internal override int KeyboardSpeed {
168                         get {
169                                 //
170                                 // A lot harder: need to do:
171                                 // XkbQueryExtension(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)       = 1
172                                 // XkbAllocKeyboard(0x08051008, 0xbfffdf4c, 0xbfffdf50, 0xbfffdf54, 0xbfffdf58)        = 0x080517a8
173                                 // XkbGetControls(0x08051008, 1, 0x080517a8, 0xbfffdf54, 0xbfffdf58)                   = 0
174                                 //
175                                 // And from that we can tell the repetition rate
176                                 //
177                                 // Notice, the values must map to:
178                                 //   [0, 31] which maps to 2.5 to 30 repetitions per second.
179                                 //
180                                 return 0;
181                         }
182                 }
183
184                 internal override int KeyboardDelay {
185                         get {
186                                 //
187                                 // Return values must range from 0 to 4, 0 meaning 250ms,
188                                 // and 4 meaning 1000 ms.
189                                 //
190                                 return 1; // ie, 500 ms
191                         }
192                 }
193                 #endregion      // Properties
194
195                 #region Constructor & Destructor
196                 // This is always called from a locked context
197                 private XplatUIX11() {
198                         // Handle singleton stuff first
199                         ref_count=0;
200
201                         message_queue = new XEventQueue ();
202                         timer_list = new ArrayList ();
203
204                         // Now regular initialization
205                         SetDisplay(XOpenDisplay(IntPtr.Zero));
206
207                         keyboard = new X11Keyboard (DisplayHandle);
208                         
209                         listen = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
210                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 0);
211                         listen.Bind (ep);
212                         listen.Listen (1);
213
214                         wake = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
215                         wake.Connect (listen.LocalEndPoint);
216
217                         double_click_interval = 500;
218                         hover.interval = 500;
219
220                         hover.timer = new Timer();
221                         hover.timer.Enabled = false;
222                         hover.timer.Interval = hover.interval;          // FIXME - read this from somewhere
223                         hover.timer.Tick +=new EventHandler(MouseHover);
224                         hover.x = -1;
225                         hover.y = -1;
226
227 #if __MonoCS__
228                         pollfds = new Pollfd [2];
229                         pollfds [0] = new Pollfd ();
230                         pollfds [0].fd = XConnectionNumber (DisplayHandle);
231                         pollfds [0].events = PollEvents.POLLIN;
232
233                         pollfds [1] = new Pollfd ();
234                         pollfds [1].fd = wake.Handle.ToInt32 ();
235                         pollfds [1].events = PollEvents.POLLIN;
236 #endif
237
238                         caret.timer = new Timer();
239                         caret.timer.Interval = 500;             // FIXME - where should this number come from?
240                         caret.timer.Tick += new EventHandler(CaretCallback);
241                 }
242
243                 ~XplatUIX11() {
244                         lock (this) {
245                                 if (DisplayHandle!=IntPtr.Zero) {
246                                         XCloseDisplay(DisplayHandle);
247                                         DisplayHandle=IntPtr.Zero;
248                                 }
249                         }
250                 }
251                 #endregion      // Constructor & Destructor
252
253                 #region Singleton Specific Code
254                 public static XplatUIX11 GetInstance() {
255                         lock (typeof (XplatUIX11)) {
256                                 if (instance==null) {
257                                         instance=new XplatUIX11();
258                                 }
259                                 ref_count++;
260                         }
261                         return instance;
262                 }
263
264                 public int Reference {
265                         get {
266                                 return ref_count;
267                         }
268                 }
269                 #endregion
270
271
272                 #region Events
273                 internal override event EventHandler Idle;
274                 #endregion      // Events
275
276
277                 #region Callbacks
278                 private void MouseHover(object sender, EventArgs e) {\r
279                         if ((hover.x == mouse_position.X) && (hover.y == mouse_position.Y)) {\r
280                                 XEvent xevent;
281
282                                 hover.timer.Enabled = false;\r
283 \r
284                                 if (hover.hwnd != IntPtr.Zero) {\r
285                                         xevent = new XEvent ();
286                                         xevent.type = XEventName.ClientMessage;
287                                         xevent.ClientMessageEvent.display = DisplayHandle;
288                                         xevent.ClientMessageEvent.window = (IntPtr)hover.hwnd;
289                                         xevent.ClientMessageEvent.message_type = (IntPtr)hover.hevent;
290                                         xevent.ClientMessageEvent.format = 32;
291                                         xevent.ClientMessageEvent.ptr1 = (IntPtr) (hover.y << 16 | hover.x);
292
293                                         message_queue.EnqueueLocked (xevent);
294
295                                         WakeupMain ();
296                                 }\r
297                         }\r
298                 }\r
299
300                 private void CaretCallback(object sender, EventArgs e) {\r
301                         if (caret.paused) {
302                                 return;
303                         }
304                         caret.on = !caret.on;
305
306                         XDrawLine(DisplayHandle, caret.hwnd, caret.gc, caret.x, caret.y, caret.x, caret.y + caret.height);
307                 }\r
308                 #endregion      // Callbacks
309
310                 #region Public Static Methods
311                 internal override IntPtr InitializeDriver() {
312                         lock (this) {
313                                 if (DisplayHandle==IntPtr.Zero) {
314                                         DisplayHandle=XOpenDisplay(IntPtr.Zero);
315                                         key_state=Keys.None;
316                                         mouse_state=MouseButtons.None;
317                                         mouse_position=Point.Empty;
318                                 }
319                         }
320                         return IntPtr.Zero;
321                 }
322
323                 internal static void SetDisplay(IntPtr display_handle) {
324                         if (display_handle != IntPtr.Zero) {
325                                 IntPtr  Screen;
326
327                                 if (FosterParent != IntPtr.Zero) {
328                                         XDestroyWindow(DisplayHandle, FosterParent);
329                                 }
330                                 if (DisplayHandle != IntPtr.Zero) {
331                                         XCloseDisplay(DisplayHandle);
332                                 }
333
334                                 DisplayHandle=display_handle;
335
336                                 // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
337                                 // been hacked to do this for us.
338                                 Graphics.FromHdcInternal (DisplayHandle);
339
340                                 // Create a few things
341                                 key_state = Keys.None;
342                                 mouse_state = MouseButtons.None;
343                                 mouse_position = Point.Empty;
344                                 Screen = XDefaultScreenOfDisplay(DisplayHandle);
345                                 //screen_num = XScreenNumberOfScreen(DisplayHandle, Screen);
346                                 screen_num = 0;
347                                 root_window = XRootWindow(display_handle, screen_num);
348                                 default_colormap = XDefaultColormap(display_handle, screen_num);
349
350                                 // Create the foster parent
351                                 FosterParent=XCreateSimpleWindow(display_handle, root_window, 0, 0, 1, 1, 4, 0, 0);
352                                 if (FosterParent==IntPtr.Zero) {
353                                         Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
354                                 }
355
356                                 // Prepare for shutdown
357                                 wm_protocols=XInternAtom(display_handle, "WM_PROTOCOLS", false);
358                                 wm_delete_window=XInternAtom(display_handle, "WM_DELETE_WINDOW", false);
359
360                                 // handling decorations and such
361                                 mwm_hints=XInternAtom(display_handle, "_MOTIF_WM_HINTS", false);
362                                 net_wm_state=XInternAtom(display_handle, "_NET_WM_STATE", false);
363                                 wm_no_taskbar=XInternAtom(display_handle, "_NET_WM_STATE_NO_TASKBAR", false);
364                                 wm_state_above=XInternAtom(display_handle, "_NET_WM_STATE_ABOVE", false);
365                                 atom=XInternAtom(display_handle, "ATOM", false);
366                                 async_method = XInternAtom(display_handle, "_SWF_AsyncAtom", false);
367                                 post_message = XInternAtom (display_handle, "_SWF_PostMessageAtom", false);
368                                 hover.hevent = XInternAtom(display_handle, "_SWF_HoverAtom", false);
369
370                                 handle_data = new Hashtable ();
371                         } else {
372                                 throw new ArgumentNullException("Display", "Could not open display (X-Server required. Check you DISPLAY environment variable)");
373                         }
374                 }
375
376                 internal override void ShutdownDriver(IntPtr token) {
377                         lock (this) {
378                                 if (DisplayHandle!=IntPtr.Zero) {
379                                         XCloseDisplay(DisplayHandle);
380                                         DisplayHandle=IntPtr.Zero;
381                                 }
382                         }
383                 }
384
385
386                 internal void Version() {
387                         Console.WriteLine("Xplat version $revision: $");
388                 }
389
390                 internal override void Exit() {
391                         Console.WriteLine("XplatUIX11.Exit");
392                 }
393
394                 internal override void GetDisplaySize(out Size size) {
395                         XWindowAttributes       attributes=new XWindowAttributes();
396
397                         lock (xlib_lock) {
398                                 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
399                         }
400
401                         size = new Size(attributes.width, attributes.height);
402                 }
403
404                 internal override void EnableThemes() {
405                         themes_enabled=true;
406                 }
407
408                 internal override IntPtr CreateWindow(CreateParams cp) {
409                         IntPtr                  WindowHandle;
410                         IntPtr                  ParentHandle;
411                         int                     X;
412                         int                     Y;
413                         int                     Width;
414                         int                     Height;
415                         MotifWmHints            mwmHints;
416                         uint[]                  atoms;
417                         int                     atom_count;
418                         int                     BorderWidth;
419                         int                     protocols;
420                         XSetWindowAttributes    attr;
421
422                         ParentHandle=cp.Parent;
423
424                         X=cp.X;
425                         Y=cp.Y;
426                         Width=cp.Width;
427                         Height=cp.Height;
428                         BorderWidth=0;
429
430                         if (Width<1) Width=1;
431                         if (Height<1) Height=1;
432
433
434                         lock (xlib_lock) {
435                                 if (ParentHandle==IntPtr.Zero) {
436                                         if ((cp.Style & (int)(WindowStyles.WS_CHILD))!=0) {
437                                                 // We need to use our foster parent window until
438                                                 // this poor child gets it's parent assigned
439                                                 ParentHandle=FosterParent;
440                                         } else if ((cp.Style & (int)(WindowStyles.WS_POPUP))!=0) {
441                                                 BorderWidth=0;
442                                                 ParentHandle=XRootWindow(DisplayHandle, 0);
443                                         } else {
444                                                 if (X<1) X=50;
445                                                 if (Y<1) Y=50;
446                                                 BorderWidth=4;
447                                                 ParentHandle=XRootWindow(DisplayHandle, 0);
448                                         }
449                                 }
450
451                                 attr = new XSetWindowAttributes();
452
453                                 if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
454                                         attr.save_under = true;
455                                 }
456
457                                 attr.override_redirect = false;
458
459                                 if ((cp.Style & ((int)WindowStyles.WS_POPUP)) != 0) {
460                                         attr.override_redirect = true;
461                                 }
462
463                                 attr.bit_gravity = Gravity.NorthWestGravity;
464                                 attr.win_gravity = Gravity.NorthWestGravity;
465
466                                 WindowHandle=XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, BorderWidth, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity | SetWindowValuemask.SaveUnder | SetWindowValuemask.OverrideRedirect, ref attr);
467
468                                 // Set the appropriate window manager hints
469                                 if (((cp.Style & ((int)WindowStyles.WS_POPUP)) != 0)  && (ParentHandle != IntPtr.Zero)) {
470                                         XSetTransientForHint(DisplayHandle, WindowHandle, ParentHandle);
471                                 }
472
473                                 mwmHints = new MotifWmHints();
474                                 mwmHints.flags = MotifFlags.Functions | MotifFlags.Decorations;
475                                 mwmHints.functions = 0;
476                                 mwmHints.decorations = 0;
477                                 
478                                 if ((cp.Style & ((int)WindowStyles.WS_CAPTION)) != 0) {
479                                         mwmHints.functions |= MotifFunctions.Move;
480                                         mwmHints.decorations |= MotifDecorations.Title | MotifDecorations.Menu;
481                                 }
482
483                                 if ((cp.Style & ((int)WindowStyles.WS_THICKFRAME)) != 0) {
484                                         mwmHints.functions |= MotifFunctions.Move | MotifFunctions.Resize;
485                                         mwmHints.decorations |= MotifDecorations.Border | MotifDecorations.ResizeH;
486                                 }
487
488                                 if ((cp.Style & ((int)WindowStyles.WS_MINIMIZEBOX)) != 0) {
489                                         mwmHints.functions |= MotifFunctions.Minimize;
490                                         mwmHints.decorations |= MotifDecorations.Minimize;
491                                 }
492
493                                 if ((cp.Style & ((int)WindowStyles.WS_MAXIMIZEBOX)) != 0) {
494                                         mwmHints.functions |= MotifFunctions.Maximize;
495                                         mwmHints.decorations |= MotifDecorations.Maximize;
496                                 }
497
498                                 if ((cp.Style & ((int)WindowStyles.WS_SYSMENU)) != 0) {
499                                         mwmHints.functions |= MotifFunctions.Close;
500                                 }
501
502                                 if ((cp.ExStyle & ((int)WindowStyles.WS_EX_DLGMODALFRAME)) != 0) {
503                                         mwmHints.decorations |= MotifDecorations.Border;
504                                 }
505
506                                 if ((cp.Style & ((int)WindowStyles.WS_DLGFRAME)) != 0) {
507                                         mwmHints.decorations |= MotifDecorations.Border;
508                                 }
509
510                                 if ((cp.Style & ((int)WindowStyles.WS_BORDER)) != 0) {
511                                         mwmHints.decorations |= MotifDecorations.Border;
512                                 }
513
514
515                                 if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
516                                         mwmHints.functions = 0;
517                                         mwmHints.decorations = 0;
518                                 }
519
520                                 XChangeProperty(DisplayHandle, WindowHandle, mwm_hints, mwm_hints, 32, PropertyMode.Replace, ref mwmHints, 5);
521
522                                 atoms = new uint[8];
523                                 atom_count = 0;
524
525                                 if ((cp.ExStyle & ((int)WindowStyles.WS_EX_TOOLWINDOW)) != 0) {
526                                         atoms[atom_count++] = (uint)wm_state_above;
527                                         atoms[atom_count++] = (uint)wm_no_taskbar;
528                                 }
529                                 XChangeProperty(DisplayHandle, WindowHandle, net_wm_state, atom, 32, PropertyMode.Replace, ref atoms, atom_count);
530
531                                 XMapWindow(DisplayHandle, WindowHandle);
532
533                                 XSelectInput(DisplayHandle, WindowHandle, SelectInputMask);
534
535                                 protocols=wm_delete_window;
536                                 XSetWMProtocols(DisplayHandle, WindowHandle, ref protocols, 1);
537                         }
538                         return(WindowHandle);
539                 }
540
541                 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
542                         CreateParams create_params = new CreateParams();
543
544                         create_params.Caption = "";
545                         create_params.X = X;
546                         create_params.Y = Y;
547                         create_params.Width = Width;
548                         create_params.Height = Height;
549
550                         create_params.ClassName=XplatUI.DefaultClassName;
551                         create_params.ClassStyle = 0;
552                         create_params.ExStyle=0;
553                         create_params.Parent=IntPtr.Zero;
554                         create_params.Param=0;
555
556                         return CreateWindow(create_params);
557                 }
558
559                 internal override void DestroyWindow(IntPtr handle) {
560                         lock (this) {
561                                 HandleData data = (HandleData) handle_data [handle];
562                                 if (data != null) {
563                                         data.Dispose ();
564                                         handle_data [handle] = null;
565                                         XDestroyWindow(DisplayHandle, handle);
566                                 }
567                         }
568                 }
569
570                 internal override void RefreshWindow(IntPtr handle) {
571                         XEvent  xevent = new XEvent();
572                         IntPtr  root;
573                         int     border_width;
574                         int     depth;
575                         int     x;
576                         int     y;
577                         int     width;
578                         int     height;
579
580                         lock (xlib_lock) {
581
582                                 // We need info about our window to generate the expose 
583                                 XGetGeometry(DisplayHandle, handle, out root, out x, out y,
584                                                 out width, out height, out border_width, out depth);
585
586                                 xevent.type=XEventName.Expose;
587                                 xevent.ExposeEvent.display=DisplayHandle;
588                                 xevent.ExposeEvent.window=handle;
589                                 xevent.ExposeEvent.x=0;
590                                 xevent.ExposeEvent.y=0;
591                                 xevent.ExposeEvent.width=width;
592                                 xevent.ExposeEvent.height=height;
593
594                                 XSendEvent(DisplayHandle, handle, false, EventMask.ExposureMask, ref xevent);
595                                 XFlush(DisplayHandle);
596                         }
597                 }
598
599                 internal override void SetWindowBackground(IntPtr handle, Color color) {
600                         XColor  xcolor;
601
602                         xcolor = new XColor();
603
604                         xcolor.red = (ushort)(color.R * 257);
605                         xcolor.green = (ushort)(color.G * 257);
606                         xcolor.blue = (ushort)(color.B * 257);
607                         XAllocColor(DisplayHandle, default_colormap, ref xcolor);
608
609                         lock (xlib_lock) {
610                                 XSetWindowBackground(DisplayHandle, handle, xcolor.pixel);
611                                 XClearWindow(DisplayHandle, handle);
612                         }
613                 }
614
615                 [MonoTODO("Add support for internal table of windows/DCs for looking up paint area and cleanup")]
616                 internal override PaintEventArgs PaintEventStart(IntPtr handle) {
617                         PaintEventArgs  paint_event;
618
619                         HandleData data = (HandleData) handle_data [handle];
620                         if (data == null) {
621                                 throw new Exception ("null data on paint event start: " + handle);
622
623                         }
624
625                         if (caret.visible == 1) {
626                                 caret.paused = true;
627                                 HideCaret();
628                         }
629
630                         data.DeviceContext = Graphics.FromHwnd (handle);
631                         paint_event = new PaintEventArgs((Graphics)data.DeviceContext, data.InvalidArea);
632
633                         return paint_event;
634                 }
635
636                 internal override void PaintEventEnd(IntPtr handle) {
637                         HandleData data = (HandleData) handle_data [handle];
638                         if (data == null)
639                                 throw new Exception ("null data on PaintEventEnd");
640                         data.ClearInvalidArea ();
641                         Graphics g = (Graphics) data.DeviceContext;
642                         g.Flush ();
643                         g.Dispose ();
644
645                         if (caret.visible == 1) {
646                                 ShowCaret();
647                                 caret.paused = false;
648                         }
649                 }
650
651                 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
652                         // X requires a sanity check for width & height; otherwise it dies
653                         if (width < 1) {
654                                 width = 1;
655                         }
656
657                         if (height < 1) {
658                                 height = 1;
659                         }
660
661                         lock (xlib_lock) {
662                                 XMoveResizeWindow(DisplayHandle, handle, x, y, width, height);
663                         }
664                         return;
665                 }
666
667                 internal override void GetWindowPos(IntPtr handle, out int x, out int y, out int width, out int height, out int client_width, out int client_height) {
668                         IntPtr  root;
669                         int     border_width;
670                         int     depth;
671
672                         lock (xlib_lock) {
673                                 
674                                 XGetGeometry(DisplayHandle, handle, out root, out x,
675                                                 out y, out width, out height, out border_width, out depth);
676                         }
677
678                         client_width = width;
679                         client_height = height;
680                         return;
681                 }
682
683                 internal override void Activate(IntPtr handle) {
684
685                         lock (xlib_lock) {
686                                 // Not sure this is the right method, but we don't use ICs either...    
687                                 XRaiseWindow(DisplayHandle, handle);
688                         }
689                         return;
690                 }
691
692                 internal override void EnableWindow(IntPtr handle, bool Enable) {
693                         // We do nothing; On X11 SetModal is used to create modal dialogs, on Win32 this function is used (see comment there)
694                 }
695
696                 internal override void SetModal(IntPtr handle, bool Modal) {
697                         // We need to use the Motif window manager hints to build modal stuff; see freedesktop.org
698                         throw new NotImplementedException("Finish me");
699                 }
700
701                 internal override void Invalidate (IntPtr handle, Rectangle rc, bool clear) {
702                         if (clear) {
703                                 XClearArea (DisplayHandle, handle, rc.Left, rc.Top, (uint)rc.Width, (uint)rc.Height, true);
704                         } else {
705                                 XEvent xevent = new XEvent ();
706                                 xevent.type = XEventName.Expose;
707                                 xevent.ExposeEvent.display = DisplayHandle;
708                                 xevent.ExposeEvent.window = handle;
709                                 xevent.ExposeEvent.x = rc.X;
710                                 xevent.ExposeEvent.y = rc.Y;
711                                 xevent.ExposeEvent.width = rc.Width;
712                                 xevent.ExposeEvent.height = rc.Height;
713
714                                 AddExpose (xevent);
715                         }
716                 }
717
718                 internal override IntPtr DefWndProc(ref Message msg) {
719                         switch((Msg)msg.Msg) {
720                                 case Msg.WM_ERASEBKGND: {
721                                         HandleData data = (HandleData) handle_data [msg.HWnd];
722                                         if (data == null) {
723                                                 throw new Exception ("null data on WM_ERASEBKGND: " + msg.HWnd);
724
725                                         }
726                                         
727                                         XClearArea(DisplayHandle, msg.HWnd, data.InvalidArea.Left, data.InvalidArea.Top, (uint)data.InvalidArea.Width, (uint)data.InvalidArea.Height, false);
728
729                                         return IntPtr.Zero;
730                                 }
731                         }
732                         return IntPtr.Zero;
733                 }
734
735                 internal override void HandleException(Exception e) {
736                         StackTrace st = new StackTrace(e);
737                         Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
738                         Console.WriteLine("{0}{1}", e.Message, st.ToString());
739                 }
740
741                 internal override void DoEvents() {
742                         Console.WriteLine("XplatUIX11.DoEvents");
743                 }
744
745                 internal override bool PeekMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
746                         Console.WriteLine("XplatUIX11.PeekMessage");
747                         return true;
748                 }
749
750                 private void CreateKeyBoardMsg (XEvent xevent, ref MSG msg)
751                 {
752                         IntPtr  buffer = Marshal.AllocHGlobal(24);
753                         XKeySym keysym;
754                         string  keys;
755                         int     len;
756                         msg.wParam = IntPtr.Zero;
757
758                         lock (xlib_lock) {
759                                 len = XLookupString(ref xevent, buffer, 24, out keysym, IntPtr.Zero);
760                         }
761
762                         if ((keysym==XKeySym.XK_Control_L) || (keysym==XKeySym.XK_Control_R)) {
763                                 if (xevent.type==XEventName.KeyPress) {
764                                         key_state |= Keys.Control;
765                                 } else {
766                                         key_state &= ~Keys.Control;
767                                 }
768                         }
769
770                         if ((keysym==XKeySym.XK_Shift_L) || (keysym==XKeySym.XK_Shift_R)) {
771                                 if (xevent.type==XEventName.KeyPress) {
772                                         key_state |= Keys.Shift;
773                                 } else {
774                                         key_state &= ~Keys.Shift;
775                                 }
776                         }
777
778                         if ((keysym==XKeySym.XK_Alt_L) || (keysym==XKeySym.XK_Alt_R)) {
779                                 if (xevent.type==XEventName.KeyPress) {
780                                         key_state |= Keys.Alt;
781                                 } else {
782                                         key_state &= ~Keys.Alt;
783                                 }
784                         }
785
786                         if (len>0) { /* String is not zero terminated*/
787                                 Marshal.WriteByte (buffer, len, 0);
788                         }
789
790                         keys=Marshal.PtrToStringAuto(buffer);
791
792                         for (int i = 0; i < KeyMapping.Length; i++) {
793                                 if (KeyMapping[i].X11Key == keysym) {
794                                         msg.wParam = (IntPtr) KeyMapping[i].Win32Key;
795                                         // Console.WriteLine("Got special key {0} {1:x} ", (VirtualKeys) keysym, keysym);
796                                         break;
797                                 }                                                       
798                         }
799
800                         if ((msg.wParam == IntPtr.Zero) && (keys.Length>0)) {
801                                 char[] keychars;                                
802                                 keychars=keys.ToCharArray(0, 1);
803                                 msg.wParam=(IntPtr)keychars[0];
804                                 // Console.WriteLine("Got key {0} {1:x} ", (VirtualKeys) keysym, keysym);
805                         }
806
807                         Marshal.FreeHGlobal (buffer);
808                         msg.lParam = (IntPtr) 1;
809                 }
810
811                 private IntPtr GetMousewParam(int Delta) {
812                         int     result = 0;
813
814                         if ((mouse_state & MouseButtons.Left) != 0) {
815                                 result |= (int)MsgButtons.MK_LBUTTON;
816                         }
817
818                         if ((mouse_state & MouseButtons.Middle) != 0) {
819                                 result |= (int)MsgButtons.MK_MBUTTON;
820                         }
821
822                         if ((mouse_state & MouseButtons.Right) != 0) {
823                                 result |= (int)MsgButtons.MK_RBUTTON;
824                         }
825
826                         Keys mods = ModifierKeys;
827                         if ((mods & Keys.Control) != 0) {
828                                 result |= (int)MsgButtons.MK_CONTROL;
829                         }
830
831                         if ((mods & Keys.Shift) != 0) {
832                                 result |= (int)MsgButtons.MK_SHIFT;
833                         }
834
835                         result |= Delta << 16;
836
837                         return (IntPtr)result;
838                 }
839
840                 private int NextTimeout (DateTime now)
841                 {
842                         int timeout = Int32.MaxValue; 
843                         lock (timer_list) {
844                                 foreach (Timer timer in timer_list) {
845                                         int next = (int) (timer.Expires - now).TotalMilliseconds;
846                                         if (next < 0)
847                                                 return 0; // Have a timer that has already expired
848                                         if (next < timeout)
849                                                 timeout = next;
850                                 }
851                         }
852                         if (timeout < Timer.Minimum)
853                                 timeout = Timer.Minimum;
854                         return timeout;
855                 }
856
857                 private void CheckTimers (DateTime now)
858                 {
859                         lock (timer_list) {
860                                 int count = timer_list.Count;
861                                 if (count == 0)
862                                         return;
863                                 for (int i = 0; i < timer_list.Count; i++) {
864                                         Timer timer = (Timer) timer_list [i];
865                                         if (timer.Enabled && timer.Expires <= now) {
866                                                 timer.FireTick ();
867                                                 timer.Update (now);
868                                         }
869                                 }
870                         }
871                 }
872
873                 private void AddExpose (XEvent xevent)
874                 {
875                         HandleData data = (HandleData) handle_data [xevent.AnyEvent.window];
876                         if (data == null) {
877                                 data = new HandleData ();
878                                 handle_data [xevent.AnyEvent.window] = data;
879                         }
880
881                         if (!data.IsVisible) {
882                                 return;
883                         }
884
885                         data.AddToInvalidArea (xevent.ExposeEvent.x, xevent.ExposeEvent.y,
886                                         xevent.ExposeEvent.width, xevent.ExposeEvent.height);
887                                    
888                         if (!data.HasExpose) {
889                                 message_queue.Enqueue (xevent);
890                                 data.HasExpose = true;
891                         }
892                 }
893
894                 private void UpdateMessageQueue ()
895                 {
896                         DateTime now = DateTime.Now;
897
898                         int pending;
899                         lock (xlib_lock) {
900                                 pending = XPending (DisplayHandle);
901                         }
902                         if (pending == 0) {
903                                 if (Idle != null) {
904                                         Idle (this, EventArgs.Empty);
905                                 }
906                                 lock (xlib_lock) {
907                                         pending = XPending (DisplayHandle);
908                                 }
909                         }
910
911                         if (pending == 0) {
912                                 int timeout = NextTimeout (now);
913                                 if (timeout > 0) {
914 #if __MonoCS__
915                                         Syscall.poll (pollfds, (uint) pollfds.Length, timeout);
916 #endif
917                                         pending = XPending (DisplayHandle);
918                                 }
919                         }
920
921                         CheckTimers (now);
922
923                         if (pending == 0) {
924                                 lock (xlib_lock) {
925                                         pending = XPending (DisplayHandle);
926                                 }
927                         }
928
929                         while (pending > 0) {
930                                 XEvent xevent = new XEvent ();
931
932                                 lock (xlib_lock) {
933                                         XNextEvent (DisplayHandle, ref xevent);
934                                 }
935                                 
936                                 switch (xevent.type) {
937                                 case XEventName.Expose:
938                                         AddExpose (xevent);
939                                         break;
940                                 case XEventName.KeyPress:
941                                 case XEventName.KeyRelease:
942                                 case XEventName.ButtonPress:
943                                 case XEventName.ButtonRelease:
944                                 case XEventName.MotionNotify:
945                                 case XEventName.EnterNotify:
946                                 case XEventName.LeaveNotify:
947                                 case XEventName.ConfigureNotify:
948                                 case XEventName.DestroyNotify:
949                                 case XEventName.FocusIn:
950                                 case XEventName.FocusOut:
951                                 case XEventName.ClientMessage:
952                                         message_queue.Enqueue (xevent);
953                                         break;
954                                 }
955
956                                 lock (xlib_lock) {
957                                         pending = XPending (DisplayHandle);
958                                 }
959                         }
960                 }
961
962                 internal override bool GetMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax) {
963                         XEvent  xevent;
964
965                         if (message_queue.Count > 0) {
966                                 xevent = (XEvent) message_queue.Dequeue ();
967                         } else {
968                                 UpdateMessageQueue ();
969                                 if (message_queue.Count > 0) {
970                                         xevent = (XEvent) message_queue.Dequeue ();
971                                 } else {
972                                         msg.hwnd= IntPtr.Zero;
973                                         msg.message = Msg.WM_ENTERIDLE;
974                                         return true;
975                                 }
976                         }
977
978                         msg.hwnd=xevent.AnyEvent.window;
979
980                         //
981                         // If you add a new event to this switch make sure to add it in
982                         // UpdateMessage also unless it is not coming through the X event system.
983                         //
984                         switch(xevent.type) {
985                                 case XEventName.KeyPress: {
986                                         keyboard.KeyEvent (xevent.AnyEvent.window, xevent, ref msg);
987                                         break;
988                                 }
989
990                                 case XEventName.KeyRelease: {
991                                         keyboard.KeyEvent (xevent.AnyEvent.window, xevent, ref msg);
992                                         break;
993                                 }
994
995                                 case XEventName.ButtonPress: {
996                                         switch(xevent.ButtonEvent.button) {
997                                                 case 1: {
998                                                         mouse_state |= MouseButtons.Left;
999                                                         msg.message=Msg.WM_LBUTTONDOWN;
1000                                                         msg.wParam=GetMousewParam(0);
1001                                                         break;
1002                                                 }
1003
1004                                                 case 2: {
1005                                                         mouse_state |= MouseButtons.Middle;
1006                                                         msg.message=Msg.WM_MBUTTONDOWN;
1007                                                         msg.wParam=GetMousewParam(0);
1008                                                         break;
1009                                                 }
1010
1011                                                 case 3: {
1012                                                         mouse_state |= MouseButtons.Right;
1013                                                         msg.message=Msg.WM_RBUTTONDOWN;
1014                                                         msg.wParam=GetMousewParam(0);
1015                                                         break;
1016                                                 }
1017
1018                                                 case 4: {
1019                                                         msg.message=Msg.WM_MOUSEWHEEL;
1020                                                         msg.wParam=GetMousewParam(120);
1021                                                         break;
1022                                                 }
1023
1024                                                 case 5: {
1025                                                         msg.message=Msg.WM_MOUSEWHEEL;
1026                                                         msg.wParam=GetMousewParam(-120);
1027                                                         break;
1028                                                 }
1029
1030                                         }
1031
1032                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
1033                                         mouse_position.X=xevent.ButtonEvent.x;
1034                                         mouse_position.Y=xevent.ButtonEvent.y;
1035
1036                                         if (!click_pending) {
1037                                                 click_pending = true;
1038                                                 click_pending_hwnd = msg.hwnd;
1039                                                 click_pending_message = msg.message;
1040                                                 click_pending_wparam = msg.wParam;
1041                                                 click_pending_lparam = msg.lParam;
1042                                                 click_pending_time = xevent.ButtonEvent.time;
1043                                         } else {
1044                                                 if (((xevent.ButtonEvent.time - click_pending_time)<double_click_interval) && (msg.wParam == click_pending_wparam) && (msg.lParam == click_pending_lparam) && (msg.message == click_pending_message)) {
1045                                                         // Looks like a genuine double click, clicked twice on the same spot with the same keys
1046                                                         switch(xevent.ButtonEvent.button) {
1047                                                                 case 1: {
1048                                                                         msg.message=Msg.WM_LBUTTONDBLCLK;
1049                                                                         break;
1050                                                                 }
1051
1052                                                                 case 2: {
1053                                                                         msg.message=Msg.WM_MBUTTONDBLCLK;
1054                                                                         break;
1055                                                                 }
1056
1057                                                                 case 3: {
1058                                                                         msg.message=Msg.WM_RBUTTONDBLCLK;
1059                                                                         break;
1060                                                                 }
1061                                                         }
1062                                                 }
1063                                                 click_pending = false;
1064                                         }
1065
1066                                         break;
1067                                 }
1068
1069                                 case XEventName.ButtonRelease: {
1070                                         switch(xevent.ButtonEvent.button) {
1071                                                 case 1: {
1072                                                         mouse_state &= ~MouseButtons.Left;
1073                                                         msg.message=Msg.WM_LBUTTONUP;
1074                                                         msg.wParam=GetMousewParam(0);
1075                                                         break;
1076                                                 }
1077
1078                                                 case 2: {
1079                                                         mouse_state &= ~MouseButtons.Middle;
1080                                                         msg.message=Msg.WM_MBUTTONUP;
1081                                                         msg.wParam=GetMousewParam(0);
1082                                                         break;
1083                                                 }
1084
1085                                                 case 3: {
1086                                                         mouse_state &= ~MouseButtons.Right;
1087                                                         msg.message=Msg.WM_RBUTTONUP;
1088                                                         msg.wParam=GetMousewParam(0);
1089                                                         break;
1090                                                 }
1091
1092                                                 case 4: {
1093                                                         return true;
1094                                                 }
1095
1096                                                 case 5: {
1097                                                         return true;
1098                                                 }
1099                                         }
1100
1101                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
1102                                         mouse_position.X=xevent.ButtonEvent.x;
1103                                         mouse_position.Y=xevent.ButtonEvent.y;
1104                                         break;
1105                                 }
1106
1107                                 case XEventName.MotionNotify: {
1108                                         msg.message = Msg.WM_MOUSEMOVE;
1109                                         msg.wParam = GetMousewParam(0);
1110                                         msg.lParam = (IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x);
1111                                         mouse_position.X = xevent.MotionEvent.x;
1112                                         mouse_position.Y = xevent.MotionEvent.y;
1113                                         hover.x = mouse_position.X;
1114                                         hover.y = mouse_position.Y;
1115                                         hover.timer.Interval = hover.interval;
1116                                         break;
1117                                 }
1118
1119                                 case XEventName.EnterNotify: {
1120                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
1121                                                 return true;
1122                                         }
1123                                         msg.message=Msg.WM_MOUSE_ENTER;
1124                                         hover.timer.Enabled = true;
1125                                         hover.hwnd = msg.hwnd;
1126                                         break;
1127                                 }
1128
1129                                 case XEventName.LeaveNotify: {
1130                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
1131                                                 return true;
1132                                         }
1133                                         msg.message=Msg.WM_MOUSE_LEAVE;
1134                                         hover.timer.Enabled = false;
1135                                         hover.hwnd = IntPtr.Zero;
1136                                         break;
1137                                 }
1138
1139                                 case XEventName.ConfigureNotify: {
1140                                         msg.message=Msg.WM_WINDOWPOSCHANGED;
1141                                         msg.wParam=IntPtr.Zero;
1142                                         msg.lParam=IntPtr.Zero;
1143
1144                                         break;
1145                                 }
1146
1147                                 case XEventName.FocusIn: {
1148                                         msg.message=Msg.WM_ACTIVATE;
1149                                         msg.wParam=(IntPtr)WindowActiveFlags.WA_ACTIVE;
1150                                         msg.lParam=IntPtr.Zero;
1151                                         break;
1152                                 }
1153
1154                                 case XEventName.FocusOut: {
1155                                         msg.message=Msg.WM_ACTIVATE;
1156                                         msg.wParam=(IntPtr)WindowActiveFlags.WA_INACTIVE;
1157                                         msg.lParam=IntPtr.Zero;
1158                                         break;
1159                                 }
1160
1161                                 case XEventName.Expose: {
1162                                         if (caret.visible == 1) {
1163                                                 caret.paused = true;
1164                                                 HideCaret();
1165                                         }
1166
1167                                         NativeWindow.WndProc(msg.hwnd, Msg.WM_ERASEBKGND, msg.hwnd, IntPtr.Zero);
1168
1169                                         if (caret.visible == 1) {
1170                                                 ShowCaret();
1171                                                 caret.paused = false;
1172                                         }
1173
1174                                         msg.message=Msg.WM_PAINT;
1175                                         msg.wParam=IntPtr.Zero;
1176                                         msg.lParam=IntPtr.Zero;
1177                                         break;
1178                                 }
1179
1180                                 case XEventName.DestroyNotify: {
1181                                         msg.message=Msg.WM_DESTROY;
1182                                         msg.wParam=IntPtr.Zero;
1183                                         msg.lParam=IntPtr.Zero;
1184                                         break;
1185                                 }
1186
1187                                 case XEventName.ClientMessage: {
1188                                         if (xevent.ClientMessageEvent.message_type == (IntPtr)async_method) {
1189                                                 GCHandle handle = (GCHandle)xevent.ClientMessageEvent.ptr1;
1190                                                 AsyncMethodData data = (AsyncMethodData) handle.Target;
1191                                                 AsyncMethodResult result = data.Result.Target as AsyncMethodResult;
1192                                                 object ret = data.Method.DynamicInvoke (data.Args);
1193                                                 if (result != null)
1194                                                         result.Complete (ret);
1195                                                 handle.Free ();
1196                                         } else if (xevent.ClientMessageEvent.message_type == (IntPtr)hover.hevent) {
1197                                                 msg.message = Msg.WM_MOUSEHOVER;
1198                                                 msg.wParam = GetMousewParam(0);
1199                                                 msg.lParam = (IntPtr) (xevent.ClientMessageEvent.ptr1);
1200                                         } else if (xevent.ClientMessageEvent.message_type == (IntPtr) post_message) {
1201                                                 msg.message = (Msg) xevent.ClientMessageEvent.ptr1.ToInt32 ();
1202                                                 msg.hwnd = xevent.ClientMessageEvent.window;
1203                                                 msg.wParam = xevent.ClientMessageEvent.ptr2;
1204                                                 msg.lParam = xevent.ClientMessageEvent.ptr3;
1205                                         } else {
1206                                                 msg.message=Msg.WM_QUIT;
1207                                                 msg.wParam=IntPtr.Zero;
1208                                                 msg.lParam=IntPtr.Zero;
1209                                                 return false;
1210                                         }
1211                                         break;
1212                                 }
1213
1214                                 case XEventName.TimerNotify: {
1215                                         xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
1216                                         break;
1217                                 }
1218                                         
1219                                 default: {
1220                                         msg.message = Msg.WM_NULL;
1221                                         break;
1222                                 }
1223                         }
1224
1225                         return true;
1226                 }
1227
1228                 internal override bool TranslateMessage(ref MSG msg) {
1229                         return keyboard.TranslateMessage (ref msg);
1230                 }
1231
1232                 internal override IntPtr DispatchMessage(ref MSG msg) {
1233                         return NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
1234                 }
1235
1236                 internal override bool SetZOrder(IntPtr hWnd, IntPtr AfterhWnd, bool Top, bool Bottom) {
1237                         if (Top) {
1238                                 XRaiseWindow(DisplayHandle, hWnd);
1239                                 return true;
1240                         } else if (!Bottom) {
1241                                 XWindowChanges  values = new XWindowChanges();
1242
1243                                 values.sibling = AfterhWnd;
1244                                 values.stack_mode = StackMode.Below;
1245                                 XConfigureWindow(DisplayHandle, hWnd, ChangeWindowFlags.CWStackMode, ref values);
1246                         } else {
1247                                 XLowerWindow(DisplayHandle, hWnd);
1248                                 return true;
1249                         }
1250                         return false;
1251                 }
1252
1253                 internal override bool SetTopmost(IntPtr hWnd, IntPtr hWndOwner, bool Enabled) {
1254                         if (Enabled) {
1255                                 if (hWndOwner == IntPtr.Zero) {
1256                                         hWndOwner = FosterParent;
1257                                 }
1258                                 XSetTransientForHint(DisplayHandle, hWnd, hWndOwner);
1259                         } else {
1260                                 int     trans_prop;
1261
1262                                 trans_prop = XInternAtom(DisplayHandle, "WM_TRANSIENT_FOR", false);
1263                                 XDeleteProperty(DisplayHandle, hWnd, trans_prop);
1264                         }
1265                         return true;
1266                 }
1267
1268                 internal override bool Text(IntPtr handle, string text) {
1269 #if notdef
1270                         XTextProperty   property = new XTextProperty();
1271
1272                         property.encoding=
1273                         XSetWMName(DisplayHandle, handle, ref property);
1274 #else
1275                         lock (xlib_lock) {
1276                                 XStoreName(DisplayHandle, handle, text);
1277                         }
1278 #endif
1279                         return true;
1280                 }
1281
1282                 internal override bool GetText(IntPtr handle, out string text) {
1283                         IntPtr  textptr;
1284
1285                         textptr = IntPtr.Zero;
1286
1287                         lock (xlib_lock) {
1288                                 XFetchName(DisplayHandle, handle, ref textptr);
1289                         }
1290                         if (textptr != IntPtr.Zero) {
1291                                 text = Marshal.PtrToStringAnsi(textptr);
1292                                 XFree(textptr);
1293                                 return true;
1294                         } else {
1295                                 text = "";
1296                                 return false;
1297                         }
1298                 }
1299
1300                 internal override bool SetVisible(IntPtr handle, bool visible) {
1301                         HandleData data = (HandleData) handle_data [handle];
1302
1303                         if (data == null) {
1304                                 data = new HandleData ();
1305                                 handle_data [handle] = data;
1306                         }
1307
1308                         data.IsVisible = visible;
1309
1310                         lock (xlib_lock) {
1311                                 if (visible) {
1312                                         XMapWindow(DisplayHandle, handle);
1313                                 } else {
1314                                         XUnmapWindow(DisplayHandle, handle);
1315                                 }
1316                         }
1317                         return true;
1318                 }
1319
1320                 internal override bool IsVisible(IntPtr handle) {
1321                         HandleData data = (HandleData) handle_data [handle];
1322
1323                         if (data == null || data.IsVisible == true) {
1324                                 return true;
1325                         }
1326                         return false;
1327                 }
1328
1329                 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
1330                         XWindowAttributes       attributes=new XWindowAttributes();
1331
1332                         lock (xlib_lock) {
1333                                 XGetWindowAttributes(DisplayHandle, handle, ref attributes);
1334                                 XReparentWindow(DisplayHandle, handle, parent, attributes.x, attributes.y);
1335                         }
1336                         return IntPtr.Zero;
1337                 }
1338
1339                 internal override IntPtr GetParent(IntPtr handle) {
1340                         IntPtr  Root;
1341                         IntPtr  Parent;
1342                         IntPtr  Children;
1343                         int     ChildCount;
1344
1345                         Root=IntPtr.Zero;
1346                         Parent=IntPtr.Zero;
1347                         Children=IntPtr.Zero;
1348                         ChildCount=0;
1349
1350                         lock (xlib_lock) {
1351                                 XQueryTree(DisplayHandle, handle, ref Root, ref Parent, ref Children, ref ChildCount);
1352                         }
1353
1354                         if (Children!=IntPtr.Zero) {
1355                                 lock (xlib_lock) {
1356                                         XFree(Children);
1357                                 }
1358                         }
1359                         return Parent;
1360                 }
1361
1362                 internal override void GrabWindow(IntPtr hWnd, IntPtr confine_hwnd) {
1363                         if (confine_hwnd != IntPtr.Zero) {
1364                                 XWindowAttributes       attributes = new XWindowAttributes();
1365
1366                                 lock (xlib_lock) {
1367                                         XGetWindowAttributes(DisplayHandle, confine_hwnd, ref attributes);
1368                                 }
1369                                 grab_area.X = attributes.x;
1370                                 grab_area.Y = attributes.y;
1371                                 grab_area.Width = attributes.width;
1372                                 grab_area.Height = attributes.height;
1373                                 grab_confined = true;
1374                         }
1375                         grab_hwnd = hWnd;
1376                         lock (xlib_lock) {
1377                                 XGrabPointer(DisplayHandle, hWnd, false,
1378                                         EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
1379                                         EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
1380                                         GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_hwnd, 0, 0);
1381                         }
1382                 }
1383
1384                 internal override void GrabInfo(out IntPtr hWnd, out bool GrabConfined, out Rectangle GrabArea) {
1385                         hWnd = grab_hwnd;
1386                         GrabConfined = grab_confined;
1387                         GrabArea = grab_area;
1388                 }
1389
1390                 internal override void ReleaseWindow(IntPtr hWnd) {
1391                         lock (xlib_lock) {
1392                                 XUngrabPointer(DisplayHandle, 0);
1393                                 grab_hwnd = IntPtr.Zero;
1394                                 grab_confined = false;
1395                         }
1396                 }
1397
1398                 internal override bool CalculateWindowRect(IntPtr hWnd, ref Rectangle ClientRect, int Style, bool HasMenu, out Rectangle WindowRect) {
1399                         WindowRect = new Rectangle(ClientRect.Left, ClientRect.Top, ClientRect.Width, ClientRect.Height);
1400                         return true;
1401                 }
1402
1403                 internal override void SetCursorPos(IntPtr handle, int x, int y) {
1404                         lock (xlib_lock) {
1405                                 XWarpPointer(DisplayHandle, IntPtr.Zero, (handle!=IntPtr.Zero) ? handle : IntPtr.Zero, 0, 0, 0, 0, x, y);
1406                         }
1407                 }
1408
1409                 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
1410                         IntPtr  root;
1411                         IntPtr  child;
1412                         int     root_x;
1413                         int     root_y;
1414                         int     win_x;
1415                         int     win_y;
1416                         int     keys_buttons;
1417
1418                         lock (xlib_lock) {
1419                                 XQueryPointer(DisplayHandle, (handle!=IntPtr.Zero) ? handle : root_window,
1420                                                 out root, out child, out root_x, out root_y,
1421                                                 out win_x, out win_y, out keys_buttons);
1422                         }
1423
1424                         if (handle != IntPtr.Zero) {
1425                                 x = win_x;
1426                                 y = win_y;
1427                         } else {
1428                                 x = root_x;
1429                                 y = root_y;
1430                         }
1431                 }
1432
1433                 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y)
1434                 {
1435                         int     dest_x_return;
1436                         int     dest_y_return;
1437                         IntPtr  child;
1438
1439                         lock (xlib_lock) {
1440                                 XTranslateCoordinates (DisplayHandle, root_window,
1441                                                 handle, x, y, out dest_x_return, out dest_y_return, out child);
1442                         }
1443
1444                         x = dest_x_return;
1445                         y = dest_y_return;
1446                 }
1447
1448                 internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
1449                         int     dest_x_return;
1450                         int     dest_y_return;
1451                         IntPtr  child;
1452
1453                         lock (xlib_lock) {
1454                                 XTranslateCoordinates (DisplayHandle, handle, root_window,
1455                                         x, y, out dest_x_return, out dest_y_return, out child);
1456                         }
1457
1458                         x = dest_x_return;
1459                         y = dest_y_return;
1460                 }
1461
1462                 internal override void SendAsyncMethod (AsyncMethodData method)
1463                 {
1464                         XEvent xevent = new XEvent ();
1465
1466                         xevent.type = XEventName.ClientMessage;
1467                         xevent.ClientMessageEvent.display = DisplayHandle;
1468                         xevent.ClientMessageEvent.window = IntPtr.Zero;
1469                         xevent.ClientMessageEvent.message_type = (IntPtr)async_method;
1470                         xevent.ClientMessageEvent.format = 32;
1471                         xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
1472
1473                         message_queue.EnqueueLocked (xevent);
1474
1475                         WakeupMain ();
1476                 }
1477
1478                 // must be called from main thread
1479                 public static void PostMessage (IntPtr hwnd, Msg message, IntPtr wparam, IntPtr lparam)
1480                 {
1481                         XEvent xevent = new XEvent ();
1482
1483                         xevent.type = XEventName.ClientMessage;
1484                         xevent.ClientMessageEvent.display = DisplayHandle;
1485                         xevent.ClientMessageEvent.window = hwnd;
1486                         xevent.ClientMessageEvent.message_type = (IntPtr) post_message;
1487                         xevent.ClientMessageEvent.format = 32;
1488                         xevent.ClientMessageEvent.ptr1 = (IntPtr) message;
1489                         xevent.ClientMessageEvent.ptr2 = wparam;
1490                         xevent.ClientMessageEvent.ptr3 = lparam;
1491
1492                         message_queue.Enqueue (xevent);
1493                 }
1494
1495                 private void WakeupMain ()
1496                 {
1497                         wake.BeginSend (new byte [] { 0xFF }, 0, 1, SocketFlags.None, null, null);
1498                 }
1499
1500                 internal override void SetTimer (Timer timer)
1501                 {
1502                         lock (timer_list) {
1503                                 timer_list.Add (timer);
1504                         }
1505                         WakeupMain ();
1506                 }
1507
1508                 internal override void KillTimer (Timer timer)
1509                 {
1510                         lock (timer_list) {
1511                                 timer_list.Remove (timer);
1512                         }
1513                 }
1514
1515                 internal static void ShowCaret() {
1516                         if ((caret.gc == IntPtr.Zero) || caret.on) {
1517                                 return;
1518                         }
1519                         caret.on = true;
1520
1521                         XDrawLine(DisplayHandle, caret.hwnd, caret.gc, caret.x, caret.y, caret.x, caret.y + caret.height);
1522                 }
1523
1524                 internal static void HideCaret() {
1525                         if ((caret.gc == IntPtr.Zero) || !caret.on) {
1526                                 return;
1527                         }
1528                         caret.on = false;
1529
1530                         XDrawLine(DisplayHandle, caret.hwnd, caret.gc, caret.x, caret.y, caret.x, caret.y + caret.height);
1531                 }
1532
1533                 // Automatically destroys any previous caret
1534                 internal override void CreateCaret(IntPtr hwnd, int width, int height) {
1535                         XGCValues       gc_values;
1536
1537                         if (caret.hwnd != IntPtr.Zero) {
1538                                 DestroyCaret(caret.hwnd);
1539                         }
1540                         caret.hwnd = hwnd;
1541                         caret.width = width;
1542                         caret.height = height;
1543                         caret.visible = 0;
1544                         caret.on = false;
1545
1546                         gc_values = new XGCValues();
1547
1548                         gc_values.line_width = caret.width;
1549                         caret.gc = XCreateGC(DisplayHandle, hwnd, GCFunction.GCLineWidth, ref gc_values);
1550                         if (caret.gc == IntPtr.Zero) {
1551                                 caret.hwnd = IntPtr.Zero;
1552                                 return;
1553                         }
1554
1555                         XSetFunction(DisplayHandle, caret.gc, GXFunction.GXinvert);
1556                 }
1557
1558                 // Only destroy if the hwnd is the hwnd of the current caret
1559                 internal override void DestroyCaret(IntPtr hwnd) {
1560                         if (caret.hwnd == hwnd) {
1561                                 if (caret.visible == 1) {
1562                                         caret.timer.Stop();
1563                                         HideCaret();
1564                                 }
1565                                 if (caret.gc != IntPtr.Zero) {
1566                                         XFreeGC(DisplayHandle, caret.gc);
1567                                         caret.gc = IntPtr.Zero;
1568                                 }
1569                                 caret.hwnd = IntPtr.Zero;
1570                                 caret.visible = 0;
1571                                 caret.on = false;
1572                         }
1573                 }
1574
1575                 // When setting the position we restart the blink interval
1576                 internal override void SetCaretPos(IntPtr hwnd, int x, int y) {
1577                         if (caret.hwnd == hwnd) {
1578                                 caret.timer.Stop();
1579                                 HideCaret();
1580
1581                                 caret.x = x;
1582                                 caret.y = y;
1583
1584                                 if (caret.visible == 1) {
1585                                         ShowCaret();
1586                                         caret.timer.Start();
1587                                 }
1588                         }
1589                 }
1590
1591                 // Visible is cumulative; two hides require two shows before the caret is visible again
1592                 internal override void CaretVisible(IntPtr hwnd, bool visible) {
1593                         if (caret.hwnd == hwnd) {
1594                                 if (visible) {
1595                                         if (caret.visible < 1) {
1596                                                 caret.visible++;
1597                                                 caret.on = false;
1598                                                 if (caret.visible == 1) {
1599                                                         ShowCaret();
1600                                                         caret.timer.Start();
1601                                                 }
1602                                         }
1603                                 } else {
1604                                         caret.visible--;
1605                                         if (caret.visible == 0) {
1606                                                 caret.timer.Stop();
1607                                                 HideCaret();
1608                                         }
1609                                 }
1610                         }
1611                 }
1612
1613                 internal override bool GetFontMetrics(Graphics g, Font font, out int ascent, out int descent) {\r
1614                         return GetFontMetrics(g.GetHdc(), font.ToHfont(), out ascent, out descent);\r
1615                 }\r
1616
1617
1618                 // Santa's little helper
1619                 static void Where() 
1620                 {
1621                         Console.WriteLine("Here: {0}", new StackTrace().ToString());
1622                 }
1623                 #endregion      // Public Static Methods
1624
1625                 internal struct X11ToWin32KeyMapping {
1626                         internal XKeySym        X11Key;
1627                         internal VirtualKeys    Win32Key;       
1628
1629                         internal X11ToWin32KeyMapping (XKeySym x11, VirtualKeys win32)
1630                         {
1631                                 X11Key = x11;
1632                                 Win32Key = win32;
1633                         } 
1634                 }
1635
1636                 /* X11 to Win32 VK mapping */
1637                 static readonly X11ToWin32KeyMapping[] KeyMapping = new X11ToWin32KeyMapping[] 
1638                 {
1639                         /* Cursor navigation*/
1640                         new X11ToWin32KeyMapping (XKeySym.XK_Left, VirtualKeys.VK_LEFT),
1641                         new X11ToWin32KeyMapping (XKeySym.XK_Right, VirtualKeys.VK_RIGHT),
1642                         new X11ToWin32KeyMapping (XKeySym.XK_Up, VirtualKeys.VK_UP),
1643                         new X11ToWin32KeyMapping (XKeySym.XK_Down, VirtualKeys.VK_DOWN),
1644
1645                         new X11ToWin32KeyMapping (XKeySym.XK_Page_Up, VirtualKeys.VK_PRIOR),
1646                         new X11ToWin32KeyMapping (XKeySym.XK_Page_Down, VirtualKeys.VK_NEXT),
1647                         new X11ToWin32KeyMapping (XKeySym.XK_End, VirtualKeys.VK_END),
1648                         new X11ToWin32KeyMapping (XKeySym.XK_Home, VirtualKeys.VK_HOME),
1649
1650                         /* Modifiers*/
1651                         new X11ToWin32KeyMapping (XKeySym.XK_Shift_R, VirtualKeys.VK_SHIFT),
1652                         new X11ToWin32KeyMapping (XKeySym.XK_Shift_L, VirtualKeys.VK_SHIFT),
1653                         new X11ToWin32KeyMapping (XKeySym.XK_Control_R, VirtualKeys.VK_CONTROL),
1654                         new X11ToWin32KeyMapping (XKeySym.XK_Control_L, VirtualKeys.VK_CONTROL),                        
1655
1656                         /* Others */
1657                         new X11ToWin32KeyMapping (XKeySym.XK_Return, VirtualKeys.VK_RETURN),
1658                         new X11ToWin32KeyMapping (XKeySym.XK_Tab, VirtualKeys.VK_TAB),
1659                         new X11ToWin32KeyMapping (XKeySym.XK_Menu, VirtualKeys.VK_MENU),
1660                         new X11ToWin32KeyMapping (XKeySym.XK_BackSpace, VirtualKeys.VK_BACK),
1661                         new X11ToWin32KeyMapping (XKeySym.XK_Clear, VirtualKeys.VK_CLEAR),
1662                         
1663                 };
1664
1665                 
1666
1667                 #region X11 Imports
1668                 [DllImport ("libX11", EntryPoint="XOpenDisplay")]
1669                 internal extern static IntPtr XOpenDisplay(IntPtr display);
1670                 [DllImport ("libX11", EntryPoint="XCloseDisplay")]
1671                 internal extern static void XCloseDisplay(IntPtr display);                                                  
1672
1673                 [DllImport ("libX11", EntryPoint="XCreateWindow")]
1674                 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);
1675                 [DllImport ("libX11", EntryPoint="XCreateSimpleWindow")]
1676                 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int border, int background);
1677                 [DllImport ("libX11", EntryPoint="XMapWindow")]
1678                 internal extern static int XMapWindow(IntPtr display, IntPtr window);
1679                 [DllImport ("libX11", EntryPoint="XUnmapWindow")]
1680                 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
1681                 [DllImport ("libX11", EntryPoint="XMapSubwindows")]
1682                 internal extern static int XMapSubindows(IntPtr display, IntPtr window);
1683                 [DllImport ("libX11", EntryPoint="XUnmapSubwindows")]
1684                 internal extern static int XUnmapSubwindows(IntPtr display, IntPtr window);
1685                 [DllImport ("libX11", EntryPoint="XRootWindow")]
1686                 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
1687                 [DllImport ("libX11", EntryPoint="XNextEvent")]
1688                 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
1689                 [DllImport ("libX11")]
1690                 internal extern static int XConnectionNumber (IntPtr diplay);
1691                 [DllImport ("libX11")]
1692                 internal extern static int XPending (IntPtr diplay);
1693                 [DllImport ("libX11")]
1694                 internal extern static bool XCheckWindowEvent (IntPtr display, IntPtr window, EventMask mask, ref XEvent xevent);
1695                 [DllImport ("libX11")]
1696                 internal extern static bool XCheckMaskEvent (IntPtr display, EventMask mask, ref XEvent xevent);
1697                 [DllImport ("libX11", EntryPoint="XSelectInput")]
1698                 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, EventMask mask);
1699                 [DllImport ("libX11", EntryPoint="XLookupString")]
1700                 internal extern static int XLookupString(ref XEvent xevent, IntPtr buffer, int num_bytes, out XKeySym keysym, IntPtr status);
1701
1702                 [DllImport ("libX11", EntryPoint="XDestroyWindow")]
1703                 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
1704
1705                 [DllImport ("libX11", EntryPoint="XReparentWindow")]
1706                 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
1707                 [DllImport ("libX11", EntryPoint="XMoveResizeWindow")]
1708                 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
1709
1710                 [DllImport ("libX11", EntryPoint="XResizeWindow")]
1711                 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
1712
1713                 [DllImport ("libX11", EntryPoint="XGetWindowAttributes")]
1714                 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
1715
1716                 [DllImport ("libX11", EntryPoint="XFlush")]
1717                 internal extern static int XFlush(IntPtr display);
1718
1719                 [DllImport ("libX11", EntryPoint="XSetWMName")]
1720                 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
1721
1722                 [DllImport ("libX11", EntryPoint="XStoreName")]
1723                 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
1724
1725                 [DllImport ("libX11", EntryPoint="XFetchName")]
1726                 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
1727
1728                 [DllImport ("libX11", EntryPoint="XSendEvent")]
1729                 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event);
1730
1731                 [DllImport ("libX11", EntryPoint="XQueryTree")]
1732                 internal extern static int XQueryTree(IntPtr display, IntPtr window, ref IntPtr root_return, ref IntPtr parent_return, ref IntPtr children_return, ref int nchildren_return);
1733
1734                 [DllImport ("libX11", EntryPoint="XFree")]
1735                 internal extern static int XFree(IntPtr data);
1736
1737                 [DllImport ("libX11", EntryPoint="XRaiseWindow")]
1738                 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
1739
1740                 [DllImport ("libX11", EntryPoint="XLowerWindow")]
1741                 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
1742
1743                 [DllImport ("libX11", EntryPoint="XConfigureWindow")]
1744                 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
1745
1746                 [DllImport ("libX11", EntryPoint="XInternAtom")]
1747                 internal extern static int XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
1748
1749                 [DllImport ("libX11", EntryPoint="XSetWMProtocols")]
1750                 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, ref int protocols, int count);
1751
1752                 [DllImport ("libX11", EntryPoint="XGrabPointer")]
1753                 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);
1754
1755                 [DllImport ("libX11", EntryPoint="XUngrabPointer")]
1756                 internal extern static int XUngrabPointer(IntPtr display, uint timestamp);
1757
1758                 [DllImport ("libX11", EntryPoint="XQueryPointer")]
1759                 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);
1760
1761                 [DllImport ("libX11", EntryPoint="XTranslateCoordinates")]
1762                 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);
1763
1764                 [DllImport ("libX11", EntryPoint="XGetGeometry")]
1765                 internal extern static bool XGetGeometry(IntPtr display, IntPtr window, out IntPtr root, out int x, out int y, out int width, out int height, out int border_width, out int depth);
1766
1767                 [DllImport ("libX11", EntryPoint="XWarpPointer")]
1768                 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);
1769
1770                 [DllImport ("libX11", EntryPoint="XClearWindow")]
1771                 internal extern static int XClearWindow(IntPtr display, IntPtr window);
1772
1773                 [DllImport ("libX11", EntryPoint="XClearArea")]
1774                 internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, uint width, uint height, bool exposures);
1775
1776                 // Colormaps
1777                 [DllImport ("libX11", EntryPoint="XDefaultScreenOfDisplay")]
1778                 internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
1779
1780                 [DllImport ("libX11", EntryPoint="XScreenNumberOfScreen")]
1781                 internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
1782
1783                 [DllImport ("libX11", EntryPoint="XDefaultVisual")]
1784                 internal extern static uint XDefaultVisual(IntPtr display, int screen_number);
1785
1786                 [DllImport ("libX11", EntryPoint="XDefaultDepth")]
1787                 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
1788
1789                 [DllImport ("libX11", EntryPoint="XDefaultColormap")]
1790                 internal extern static uint XDefaultColormap(IntPtr display, int screen_number);
1791
1792                 [DllImport ("libX11", EntryPoint="XLookupColor")]
1793                 internal extern static int XLookupColor(IntPtr display, uint Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
1794
1795                 [DllImport ("libX11", EntryPoint="XAllocColor")]
1796                 internal extern static int XAllocColor(IntPtr display, uint Colormap, ref XColor colorcell_def);
1797
1798                 [DllImport ("libX11.so", EntryPoint="XSetTransientForHint")]
1799                 internal extern static int XSetTransientForHint(IntPtr display, IntPtr window, IntPtr prop_window);
1800
1801                 [DllImport ("libX11.so", EntryPoint="XChangeProperty")]
1802                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int type, int format, PropertyMode  mode, ref MotifWmHints data, int nelements);
1803
1804                 [DllImport ("libX11.so", EntryPoint="XChangeProperty")]
1805                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int format, int type, PropertyMode  mode, ref uint[] atoms, int nelements);
1806
1807                 [DllImport ("libX11.so", EntryPoint="XChangeProperty")]
1808                 internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int format, int type, PropertyMode  mode, IntPtr data, int nelements);
1809
1810                 [DllImport ("libX11.so", EntryPoint="XDeleteProperty")]
1811                 internal extern static int XDeleteProperty(IntPtr display, IntPtr window, int property);
1812
1813                 [DllImport ("libX11", EntryPoint="XGetKeyboardControl")]
1814                 internal extern static int XGetKeyboardControl (IntPtr display, out XKeyBoardState state);
1815
1816                 [DllImport ("gdiplus", EntryPoint="GetFontMetrics")]
1817                 internal extern static bool GetFontMetrics(IntPtr graphicsObject, IntPtr nativeObject, out int ascent, out int descent);
1818
1819                 // Drawing
1820                 [DllImport ("libX11", EntryPoint="XCreateGC")]
1821                 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, GCFunction valuemask, ref XGCValues values);
1822
1823                 [DllImport ("libX11", EntryPoint="XFreeGC")]
1824                 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
1825
1826                 [DllImport ("libX11", EntryPoint="XSetFunction")]
1827                 internal extern static int XSetFunction(IntPtr display, IntPtr gc, GXFunction function);
1828
1829                 [DllImport ("libX11", EntryPoint="XDrawLine")]
1830                 internal extern static int XDrawLine(IntPtr display, IntPtr drawable, IntPtr gc, int x1, int y1, int x2, int y2);
1831
1832                 [DllImport ("libX11", EntryPoint="XSetWindowBackground")]
1833                 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, uint background);
1834                 #endregion\r
1835         }
1836 }