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