New message loop that uses poll so we don't get a busy loop
[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.Posix;
42 #endif
43
44 /// X11 Version
45 namespace System.Windows.Forms {
46         internal class XplatUIX11 : XplatUIDriver {
47                 #region Local Variables
48                 private static XplatUIX11       instance;
49                 private static int              ref_count;
50                 private static bool             themes_enabled;
51
52                 private static IntPtr           DisplayHandle;          // X11 handle to display
53                 private static IntPtr           root_window;            // Handle of the root window for the screen/display
54                 private static IntPtr           FosterParent;           // Container to hold child windows until their parent exists
55                 private static int              wm_protocols;           // X Atom
56                 private static int              wm_delete_window;       // X Atom
57                 private static IntPtr           async_method;
58                 private static uint             default_colormap;       // X Colormap ID
59                 internal static Keys            key_state;
60                 internal static MouseButtons    mouse_state;
61                 internal static Point           mouse_position;
62                 internal static bool            grab_confined;          // Is the current grab (if any) confined to grab_area?
63                 internal static IntPtr          grab_hwnd;              // The window that is grabbed
64                 internal static Rectangle       grab_area;              // The area the current grab is confined to
65                 internal static bool            is_visible;
66
67                 private static Hashtable        handle_data;
68                 private Queue message_queue;
69
70                 private ArrayList timer_list;
71                 private Thread timer_thread;
72                 private AutoResetEvent timer_wait;
73                 private Socket listen;
74                 private Socket wake;
75
76 #if __MonoCS__
77                 private pollfd [] pollfds;
78 #endif
79
80                 private object xlib_lock = new object ();
81
82                 private static readonly EventMask  SelectInputMask = EventMask.ButtonPressMask | 
83                                 EventMask.ButtonReleaseMask | 
84                                 EventMask.KeyPressMask | 
85                                 EventMask.KeyReleaseMask | 
86                                 EventMask.EnterWindowMask | 
87                                 EventMask.LeaveWindowMask |
88                                 EventMask.ExposureMask |
89                                 EventMask.PointerMotionMask | 
90                                 EventMask.VisibilityChangeMask |
91                                 EventMask.StructureNotifyMask;
92
93                 #endregion      // Local Variables
94
95                 internal override Keys ModifierKeys {
96                         get {
97                                 return key_state;
98                         }
99                 }
100
101                 internal override MouseButtons MouseButtons {
102                         get {
103                                 return mouse_state;
104                         }
105                 }
106
107                 internal override Point MousePosition {
108                         get {
109                                 return mouse_position;
110                         }
111                 }
112
113                 internal override bool DropTarget {
114                         get {
115                                 return false;
116                         }
117
118                         set {
119                                 if (value) {
120                                         throw new NotImplementedException("Need to figure out D'n'D for X11");
121                                 }
122                         }
123                 }
124
125                 #region Constructor & Destructor
126                 // This is always called from a locked context
127                 private XplatUIX11() {
128                         // Handle singleton stuff first
129                         ref_count=0;
130
131                         message_queue = new Queue ();
132                         timer_list = new ArrayList ();
133
134                         // Now regular initialization
135                         SetDisplay(XOpenDisplay(IntPtr.Zero));
136
137                         listen = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
138                         IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 0);
139                         listen.Bind (ep);
140                         listen.Listen (1);
141
142                         wake = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
143                         wake.Connect (listen.LocalEndPoint);
144
145 #if __MonoCS__
146                         pollfds = new pollfd [2];
147                         pollfds [0] = new pollfd ();
148                         pollfds [0].fd = XConnectionNumber (DisplayHandle);
149                         pollfds [0].events = PollEvents.POLLIN;
150
151                         pollfds [1] = new pollfd ();
152                         pollfds [1].fd = wake.Handle.ToInt32 ();
153                         pollfds [1].events = PollEvents.POLLIN;
154 #endif
155                 }
156
157                 ~XplatUIX11() {
158                         lock (this) {
159                                 if (DisplayHandle!=IntPtr.Zero) {
160                                         XCloseDisplay(DisplayHandle);
161                                         DisplayHandle=IntPtr.Zero;
162                                 }
163                         }
164                 }
165                 #endregion      // Constructor & Destructor
166
167                 #region Singleton Specific Code
168                 public static XplatUIX11 GetInstance() {
169                         lock (typeof (XplatUIX11)) {
170                                 if (instance==null) {
171                                         instance=new XplatUIX11();
172                                 }
173                                 ref_count++;
174                         }
175                         return instance;
176                 }
177
178                 public int Reference {
179                         get {
180                                 return ref_count;
181                         }
182                 }
183                 #endregion
184
185                 internal override event EventHandler Idle;
186                 
187                 #region Public Static Methods
188                 internal override IntPtr InitializeDriver() {
189                         lock (this) {
190                                 if (DisplayHandle==IntPtr.Zero) {
191                                         DisplayHandle=XOpenDisplay(IntPtr.Zero);
192                                         key_state=Keys.None;
193                                         mouse_state=MouseButtons.None;
194                                         mouse_position=Point.Empty;
195                                 }
196                         }
197                         return IntPtr.Zero;
198                 }
199
200                 internal static void SetDisplay(IntPtr display_handle) {
201                         if (display_handle != IntPtr.Zero) {
202                                 if (FosterParent != IntPtr.Zero) {
203                                         XDestroyWindow(DisplayHandle, FosterParent);
204                                 }
205                                 if (DisplayHandle != IntPtr.Zero) {
206                                         XCloseDisplay(DisplayHandle);
207                                 }
208
209                                 DisplayHandle=display_handle;
210
211                                 // Create a few things
212                                 key_state = Keys.None;
213                                 mouse_state = MouseButtons.None;
214                                 mouse_position = Point.Empty;
215                                 root_window = XRootWindow(display_handle, 0);
216                                 default_colormap = XDefaultColormap(display_handle, 0);
217
218                                 // Create the foster parent
219                                 FosterParent=XCreateSimpleWindow(display_handle, root_window, 0, 0, 1, 1, 4, 0, 0);
220                                 if (FosterParent==IntPtr.Zero) {
221                                         Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
222                                 }
223
224                                 // Prepare for shutdown
225                                 wm_protocols=XInternAtom(display_handle, "WM_PROTOCOLS", false);
226                                 wm_delete_window=XInternAtom(display_handle, "WM_DELETE_WINDOW", false);
227
228                                 handle_data = new Hashtable ();
229                         }
230                 }
231
232                 internal override void ShutdownDriver(IntPtr token) {
233                         lock (this) {
234                                 if (DisplayHandle!=IntPtr.Zero) {
235                                         XCloseDisplay(DisplayHandle);
236                                         DisplayHandle=IntPtr.Zero;
237                                 }
238                         }
239                 }
240
241
242                 internal void Version() {
243                         Console.WriteLine("Xplat version $revision: $");
244                 }
245
246                 internal override void Exit() {
247                         Console.WriteLine("XplatUIX11.Exit");
248                 }
249
250                 internal override void GetDisplaySize(out Size size) {
251                         XWindowAttributes       attributes=new XWindowAttributes();
252
253                         lock (xlib_lock) {
254                                 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
255                         }
256
257                         size = new Size(attributes.width, attributes.height);
258                 }
259
260                 internal override void EnableThemes() {
261                         themes_enabled=true;
262                 }
263
264                 internal override IntPtr CreateWindow(CreateParams cp) {
265                         IntPtr                  WindowHandle;
266                         IntPtr                  ParentHandle;
267                         int                     X;
268                         int                     Y;
269                         int                     Width;
270                         int                     Height;
271                         int                     BorderWidth;
272                         int                     protocols;
273
274                         ParentHandle=cp.Parent;
275
276                         X=cp.X;
277                         Y=cp.Y;
278                         Width=cp.Width;
279                         Height=cp.Height;
280                         BorderWidth=0;
281
282                         if (Width<1) Width=1;
283                         if (Height<1) Height=1;
284
285
286                         lock (xlib_lock) {
287                                 if (ParentHandle==IntPtr.Zero) {
288                                         if ((cp.Style & (int)WindowStyles.WS_CHILD)!=0) {
289                                                 // We need to use our foster parent window until
290                                                 // this poor child gets it's parent assigned
291                                                 ParentHandle=FosterParent;
292                                         } else {
293                                                 if (X<1) X=50;
294                                                 if (Y<1) Y=50;
295                                                 BorderWidth=4;
296                                                 ParentHandle=XRootWindow(DisplayHandle, 0);
297                                         }
298                                 }
299
300                                 WindowHandle=XCreateSimpleWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, BorderWidth, 0, 0);
301                                 XMapWindow(DisplayHandle, WindowHandle);
302
303                                 XSelectInput(DisplayHandle, WindowHandle, SelectInputMask);
304                                 is_visible=true;
305
306                                 protocols=wm_delete_window;
307                                 XSetWMProtocols(DisplayHandle, WindowHandle, ref protocols, 1);
308                         }
309                         return(WindowHandle);
310                 }
311
312                 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
313                         CreateParams create_params = new CreateParams();
314
315                         create_params.Caption = "";
316                         create_params.X = X;
317                         create_params.Y = Y;
318                         create_params.Width = Width;
319                         create_params.Height = Height;
320
321                         create_params.ClassName=XplatUI.DefaultClassName;
322                         create_params.ClassStyle = 0;
323                         create_params.ExStyle=0;
324                         create_params.Parent=IntPtr.Zero;
325                         create_params.Param=0;
326
327                         return CreateWindow(create_params);
328                 }
329
330                 internal override void DestroyWindow(IntPtr handle) {
331                         lock (this) {
332                                 HandleData data = (HandleData) handle_data [handle];
333                                 if (data != null) {
334                                         data.Dispose ();
335                                         handle_data [handle] = null;
336                                 }
337                         }
338                 }
339
340                 internal override void RefreshWindow(IntPtr handle) {
341                         XEvent  xevent = new XEvent();
342                         IntPtr  root;
343                         int     border_width;
344                         int     depth;
345                         int     x;
346                         int     y;
347                         int     width;
348                         int     height;
349
350                         lock (xlib_lock) {
351
352                                 // We need info about our window to generate the expose 
353                                 XGetGeometry(DisplayHandle, handle, out root, out x, out y,
354                                                 out width, out height, out border_width, out depth);
355
356                                 xevent.type=XEventName.Expose;
357                                 xevent.ExposeEvent.display=DisplayHandle;
358                                 xevent.ExposeEvent.window=handle;
359                                 xevent.ExposeEvent.x=0;
360                                 xevent.ExposeEvent.y=0;
361                                 xevent.ExposeEvent.width=width;
362                                 xevent.ExposeEvent.height=height;
363
364                                 XSendEvent(DisplayHandle, handle, false, EventMask.ExposureMask, ref xevent);
365                                 XFlush(DisplayHandle);
366                         }
367                 }
368
369                 internal override void SetWindowBackground(IntPtr handle, Color color) {
370                         uint    backcolor;
371
372 //                      backcolor = ((uint)(color.ToArgb() & 0xff0000)>>16) | (uint)(color.ToArgb() & 0xff00) | (uint)((color.ToArgb() & 0xff) << 16);
373                         backcolor = ((uint)(color.ToArgb() & 0xff0000)) | (uint)(color.ToArgb() & 0xff00) | (uint)((color.ToArgb() & 0xff) );
374                         lock (xlib_lock) {
375                                 XSetWindowBackground(DisplayHandle, handle, backcolor);
376                         }
377                 }
378
379                 [MonoTODO("Add support for internal table of windows/DCs for looking up paint area and cleanup")]
380                 internal override PaintEventArgs PaintEventStart(IntPtr handle) {
381                         PaintEventArgs  paint_event;
382
383                         HandleData data = (HandleData) handle_data [handle];
384                         if (data == null) {
385                                 throw new Exception ("null data on paint event start: " + handle);
386
387                         }
388
389                         data.DeviceContext = Graphics.FromHwnd (handle);
390                         paint_event = new PaintEventArgs((Graphics)data.DeviceContext, data.InvalidArea);
391
392                         return paint_event;
393                 }
394
395                 internal override void PaintEventEnd(IntPtr handle) {
396                         HandleData data = (HandleData) handle_data [handle];
397                         if (data == null)
398                                 throw new Exception ("null data on PaintEventEnd");
399                         data.ClearInvalidArea ();
400                         Graphics g = (Graphics) data.DeviceContext;
401                         g.Flush ();
402                         g.Dispose ();
403                 }
404
405                 internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
406                         // X requires a sanity check for width & height; otherwise it dies
407                         if (width < 1) {
408                                 width = 1;
409                         }
410
411                         if (height < 1) {
412                                 height = 1;
413                         }
414                         lock (xlib_lock) {
415                                 XMoveResizeWindow(DisplayHandle, handle, x, y, width, height);
416                         }
417                         return;
418                 }
419
420                 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) {
421                         IntPtr  root;
422                         int     border_width;
423                         int     depth;
424
425                         lock (xlib_lock) {
426                                 
427                                 XGetGeometry(DisplayHandle, handle, out root, out x,
428                                                 out y, out width, out height, out border_width, out depth);
429                         }
430
431                         client_width = width;
432                         client_height = height;
433                         return;
434                 }
435
436                 internal override void Activate(IntPtr handle) {
437
438                         lock (xlib_lock) {
439                                 // Not sure this is the right method, but we don't use ICs either...    
440                                 XRaiseWindow(DisplayHandle, handle);
441                         }
442                         return;
443                 }
444
445                 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
446                         XEvent                  xevent = new XEvent();
447
448                         xevent.type=XEventName.Expose;
449                         xevent.ExposeEvent.display=DisplayHandle;
450                         xevent.ExposeEvent.window=handle;
451                         xevent.ExposeEvent.count=0;
452
453                         lock (xlib_lock) {
454
455                                 if (clear) {
456                                         // Need to clear the whole window, so we force a redraw for the whole window
457                                         XWindowAttributes       attributes=new XWindowAttributes();
458
459                                         // We need info about our window to generate the expose 
460                                         XGetWindowAttributes(DisplayHandle, handle, ref attributes);
461
462                                         xevent.ExposeEvent.x=0;
463                                         xevent.ExposeEvent.y=0;
464                                         xevent.ExposeEvent.width=attributes.width;
465                                         xevent.ExposeEvent.height=attributes.height;
466                                 } else {
467                                         xevent.ExposeEvent.x=rc.Left;
468                                         xevent.ExposeEvent.y=rc.Top;
469                                         xevent.ExposeEvent.width=rc.Width;
470                                         xevent.ExposeEvent.height=rc.Height;
471                                 }
472
473                                 XSendEvent(DisplayHandle, handle, false, EventMask.ExposureMask, ref xevent);
474                                 // Flush is not needed, invalidate does not guarantee an immediate effect
475                         }
476                 }
477
478                 internal override IntPtr DefWndProc(ref Message msg) {
479 #if not
480                         switch (msg.Msg) {
481                                 case (int)Msg.WM_PAINT: {
482                                         IntPtr  gc;
483
484                                         if (msg.Hwnd!=IntPtr.Zero) {
485                                                 gc=XCreateGC(DisplayHandle, msg.Hwnd, 0, IntPtr.Zero);
486                                                 XSetBackground(DisplayHandle, gc, this.BackColor.ToArgb());
487                                                 XFreeGC(DisplayHandle, gc);
488                                         }
489                                         break;
490                                 }
491                         }
492 #endif
493
494 #if debug
495                         Console.WriteLine("XplatUIX11.DefWndProc");
496 #endif
497                         return IntPtr.Zero;
498                 }
499
500                 internal override void HandleException(Exception e) {
501                         StackTrace st = new StackTrace(e);
502                         Console.WriteLine("Exception '{0}'", e.Message+st.ToString());
503                         Console.WriteLine("{0}{1}", e.Message, st.ToString());
504                 }
505
506                 internal override void DoEvents() {
507                         Console.WriteLine("XplatUIX11.DoEvents");
508                 }
509
510                 internal override bool PeekMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
511                         Console.WriteLine("XplatUIX11.PeekMessage");
512                         return true;
513                 }
514
515                 private void CreateKeyBoardMsg (XEvent xevent, ref MSG msg)
516                 {
517                         IntPtr  buffer = Marshal.AllocHGlobal(24);
518                         XKeySym keysym;
519                         string  keys;
520                         int     len;
521                         msg.wParam = IntPtr.Zero;
522
523                         lock (xlib_lock) {
524                                 len = XLookupString(ref xevent, buffer, 24, out keysym, IntPtr.Zero);
525                         }
526
527                         if ((keysym==XKeySym.XK_Control_L) || (keysym==XKeySym.XK_Control_R)) {
528                                 if (xevent.type==XEventName.KeyPress) {
529                                         key_state |= Keys.Control;
530                                 } else {
531                                         key_state &= ~Keys.Control;
532                                 }
533                         }
534
535                         if ((keysym==XKeySym.XK_Shift_L) || (keysym==XKeySym.XK_Shift_R)) {
536                                 if (xevent.type==XEventName.KeyPress) {
537                                         key_state |= Keys.Shift;
538                                 } else {
539                                         key_state &= ~Keys.Shift;
540                                 }
541                         }
542
543                         if (len>0) /* String is not zero terminated*/
544                                 Marshal.WriteByte (buffer, len, 0);
545
546                         keys=Marshal.PtrToStringAuto(buffer);
547
548                         for (int i = 0; i < KeyMapping.Length; i++) {
549                                 if (KeyMapping[i].X11Key == keysym) {
550                                         msg.wParam = (IntPtr) KeyMapping[i].Win32Key;
551                                         Console.WriteLine("Got special key {0} {1:x} ", keysym, keysym);
552                                         break;
553                                 }                                                       
554                         }
555
556                         if ((msg.wParam == IntPtr.Zero) && (keys.Length>0)) {
557                                 char[] keychars;                                
558                                 keychars=keys.ToCharArray(0, 1);
559                                 msg.wParam=(IntPtr)keychars[0];
560                                 Console.WriteLine("Got key {0} {1:x} ", keysym, keysym);
561                         }
562
563                         Marshal.FreeHGlobal (buffer);
564                         msg.lParam = (IntPtr) 1;
565                 }
566
567                 private IntPtr GetMousewParam(int Delta) {
568                         int     result = 0;
569
570                         if ((mouse_state & MouseButtons.Left) != 0) {
571                                 result |= (int)MsgButtons.MK_LBUTTON;
572                         }
573
574                         if ((mouse_state & MouseButtons.Middle) != 0) {
575                                 result |= (int)MsgButtons.MK_MBUTTON;
576                         }
577
578                         if ((mouse_state & MouseButtons.Right) != 0) {
579                                 result |= (int)MsgButtons.MK_RBUTTON;
580                         }
581
582                         if ((key_state & Keys.Control) != 0) {
583                                 result |= (int)MsgButtons.MK_CONTROL;
584                         }
585
586                         if ((key_state & Keys.Shift) != 0) {
587                                 result |= (int)MsgButtons.MK_SHIFT;
588                         }
589
590                         result |= Delta << 16;
591
592                         return (IntPtr)result;
593                 }
594
595                 private int NextTimeout (DateTime now)
596                 {
597                         int timeout = Int32.MaxValue; 
598                         lock (timer_list) {
599                                 foreach (Timer timer in timer_list) {
600                                         int next = (int) (timer.Expires - now).TotalMilliseconds;
601                                         if (next < 0)
602                                                 return 0; // Have a timer that has already expired
603                                         if (next < timeout)
604                                                 timeout = next;
605                                 }
606                         }
607                         if (timeout < Timer.Minimum)
608                                 timeout = Timer.Minimum;
609                         return timeout;
610                 }
611
612                 private void CheckTimers (DateTime now)
613                 {
614                         lock (timer_list) {
615                                 int count = timer_list.Count;
616                                 if (count == 0)
617                                         return;
618                                 for (int i = 0; i < count; i++) {
619                                         Timer timer = (Timer) timer_list [i];
620                                         if (timer.Enabled && timer.Expires <= now) {
621                                                 timer.FireTick ();
622                                                 timer.Update (now);
623                                         }
624                                 }
625                         }
626                 }
627
628                 private void UpdateMessageQueue ()
629                 {
630                         DateTime now = DateTime.Now;
631
632                         int pending;
633                         lock (xlib_lock) {
634                                 pending = XPending (DisplayHandle);
635                         }
636                         if (pending == 0) {
637                                 if (Idle != null) {
638                                         Idle (this, EventArgs.Empty);
639                                 }
640                                 lock (xlib_lock) {
641                                         pending = XPending (DisplayHandle);
642                                 }
643                         }
644
645                         if (pending == 0) {
646                                 int timeout = NextTimeout (now);
647                                 if (timeout > 0) {
648 #if __MonoCS__
649                                         Syscall.poll (pollfds, pollfds.Length, timeout);
650 #endif
651                                         pending = XPending (DisplayHandle);
652                                 }
653                         }
654
655                         CheckTimers (now);
656
657                         if (pending == 0) {
658                                 lock (xlib_lock) {
659                                         pending = XPending (DisplayHandle);
660                                 }
661                         }
662
663                         while (pending > 0) {
664                                 XEvent xevent = new XEvent ();
665
666                                 lock (xlib_lock) {
667                                         XNextEvent (DisplayHandle, ref xevent);
668                                 }
669                                 
670                                 switch (xevent.type) {
671                                 case XEventName.Expose:
672                                         HandleData data = (HandleData) handle_data [xevent.AnyEvent.window];
673                                         if (data == null) {
674                                                 data = new HandleData ();
675                                                 handle_data [xevent.AnyEvent.window] = data;
676                                         }
677                                    
678                                         data.AddToInvalidArea (xevent.ExposeEvent.x, xevent.ExposeEvent.y,
679                                                         xevent.ExposeEvent.width, xevent.ExposeEvent.height);
680                                    
681                                         if (!data.HasExpose) {
682                                                 lock (message_queue) {
683                                                         message_queue.Enqueue (xevent);
684                                                 }
685                                                 data.HasExpose = true;
686                                         }
687                                         break;
688                                 default:
689                                         lock (message_queue) {
690                                                 message_queue.Enqueue (xevent);
691                                         }
692                                         break;
693                                 }
694
695                                 lock (xlib_lock) {
696                                         pending = XPending (DisplayHandle);
697                                 }
698                         }
699                 }
700
701                 internal override bool GetMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax) {
702                         XEvent  xevent;
703
704                         if (message_queue.Count > 0) {
705                                 xevent = (XEvent) message_queue.Dequeue ();
706                         } else {
707                                 UpdateMessageQueue ();
708                                 if (message_queue.Count > 0) {
709                                         xevent = (XEvent) message_queue.Dequeue ();
710                                 } else {
711                                         msg.hwnd= IntPtr.Zero;
712                                         msg.message = Msg.WM_ENTERIDLE;
713                                         return true;
714                                 }
715                         }
716
717                         msg.hwnd=xevent.AnyEvent.window;
718
719                         switch(xevent.type) {
720                                 case XEventName.KeyPress: {
721                                         msg.message = Msg.WM_KEYDOWN;
722                                         CreateKeyBoardMsg (xevent, ref msg);
723                                         break;
724                                 }
725
726                                 case XEventName.KeyRelease: {
727                                         msg.message=Msg.WM_KEYUP;
728                                         CreateKeyBoardMsg (xevent, ref msg);
729                                         break;
730                                 }
731
732                                 case XEventName.ButtonPress: {
733                                         switch(xevent.ButtonEvent.button) {
734                                                 case 1: {
735                                                         mouse_state |= MouseButtons.Left;
736                                                         msg.message=Msg.WM_LBUTTONDOWN;
737                                                         msg.wParam=GetMousewParam(0);
738                                                         break;
739                                                 }
740
741                                                 case 2: {
742                                                         mouse_state |= MouseButtons.Middle;
743                                                         msg.message=Msg.WM_MBUTTONDOWN;
744                                                         msg.wParam=GetMousewParam(0);
745                                                         break;
746                                                 }
747
748                                                 case 3: {
749                                                         mouse_state |= MouseButtons.Right;
750                                                         msg.message=Msg.WM_RBUTTONDOWN;
751                                                         msg.wParam=GetMousewParam(0);
752                                                         break;
753                                                 }
754
755                                                 case 4: {
756                                                         msg.message=Msg.WM_MOUSEWHEEL;
757                                                         msg.wParam=GetMousewParam(120);
758                                                         break;
759                                                 }
760
761                                                 case 5: {
762                                                         msg.message=Msg.WM_MOUSEWHEEL;
763                                                         msg.wParam=GetMousewParam(-120);
764                                                         break;
765                                                 }
766
767                                         }
768
769                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
770                                         mouse_position.X=xevent.ButtonEvent.x;
771                                         mouse_position.Y=xevent.ButtonEvent.y;
772                                         break;
773                                 }
774
775                                 case XEventName.ButtonRelease: {
776                                         switch(xevent.ButtonEvent.button) {
777                                                 case 1: {
778                                                         mouse_state &= ~MouseButtons.Left;
779                                                         msg.message=Msg.WM_LBUTTONUP;
780                                                         msg.wParam=GetMousewParam(0);
781                                                         break;
782                                                 }
783
784                                                 case 2: {
785                                                         mouse_state &= ~MouseButtons.Middle;
786                                                         msg.message=Msg.WM_MBUTTONUP;
787                                                         msg.wParam=GetMousewParam(0);
788                                                         break;
789                                                 }
790
791                                                 case 3: {
792                                                         mouse_state &= ~MouseButtons.Right;
793                                                         msg.message=Msg.WM_RBUTTONUP;
794                                                         msg.wParam=GetMousewParam(0);
795                                                         break;
796                                                 }
797
798                                                 case 4: {
799                                                         return true;
800                                                 }
801
802                                                 case 5: {
803                                                         return true;
804                                                 }
805                                         }
806
807                                         msg.lParam=(IntPtr) (xevent.ButtonEvent.y << 16 | xevent.ButtonEvent.x);
808                                         mouse_position.X=xevent.ButtonEvent.x;
809                                         mouse_position.Y=xevent.ButtonEvent.y;
810                                         break;
811                                 }
812
813                                 case XEventName.MotionNotify: {
814                                         msg.message=Msg.WM_MOUSEMOVE;
815                                         msg.wParam=GetMousewParam(0);
816                                         msg.lParam=(IntPtr) (xevent.MotionEvent.y << 16 | xevent.MotionEvent.x);
817                                         mouse_position.X=xevent.MotionEvent.x;
818                                         mouse_position.Y=xevent.MotionEvent.y;
819                                         break;
820                                 }
821
822                                 case XEventName.EnterNotify: {
823                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
824                                                 return true;
825                                         }
826                                         msg.message=Msg.WM_MOUSE_ENTER;
827                                         break;
828                                 }
829
830                                 case XEventName.LeaveNotify: {
831                                         if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
832                                                 return true;
833                                         }
834                                         msg.message=Msg.WM_MOUSE_LEAVE;
835                                         break;
836                                 }
837
838                                 case XEventName.ConfigureNotify: {
839                                         msg.message=Msg.WM_WINDOWPOSCHANGED;
840                                         msg.wParam=IntPtr.Zero;
841                                         msg.lParam=IntPtr.Zero;
842
843                                         break;
844                                 }
845
846                                 case XEventName.Expose: {
847                                         msg.message=Msg.WM_PAINT;
848                                         msg.wParam=IntPtr.Zero;
849                                         msg.lParam=IntPtr.Zero;
850                                         break;
851                                 }
852
853                                 case XEventName.DestroyNotify: {
854                                         msg.message=Msg.WM_DESTROY;
855                                         msg.wParam=IntPtr.Zero;
856                                         msg.lParam=IntPtr.Zero;
857                                         break;
858                                 }
859
860                                 case XEventName.ClientMessage: {
861                                         if (xevent.ClientMessageEvent.message_type == async_method) {
862                                                 GCHandle handle = (GCHandle)xevent.ClientMessageEvent.ptr1;
863                                                 AsyncMethodData data = (AsyncMethodData) handle.Target;
864                                                 AsyncMethodResult result = data.Result.Target as AsyncMethodResult;
865                                                 object ret = data.Method.DynamicInvoke (data.Args);
866                                                 if (result != null)
867                                                         result.Complete (ret);
868                                                 handle.Free ();
869                                         } else {
870                                                 msg.message=Msg.WM_QUIT;
871                                                 msg.wParam=IntPtr.Zero;
872                                                 msg.lParam=IntPtr.Zero;
873                                                 return false;
874                                         }
875                                         break;
876                                 }
877
878                         case XEventName.TimerNotify: {
879                                 xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
880                                 break;
881                         }
882                                 
883                         default: {
884                                         msg.message = Msg.WM_NULL;
885                                         break;
886                                 }
887                         }
888
889                         NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
890
891                         return true;
892                 }
893
894                 internal override bool TranslateMessage(ref MSG msg) {
895                         return true;
896                 }
897
898                 internal override bool DispatchMessage(ref MSG msg) {
899                         return true;
900                 }
901
902                 internal override bool SetZOrder(IntPtr hWnd, IntPtr AfterhWnd, bool Top, bool Bottom) {
903                         if (Top) {
904                                 XRaiseWindow(DisplayHandle, hWnd);
905                                 return true;
906                         } else if (!Bottom) {
907                                 XWindowChanges  values = new XWindowChanges();
908
909                                 values.sibling = AfterhWnd;
910                                 values.stack_mode = StackMode.Below;
911                                 XConfigureWindow(DisplayHandle, hWnd, ChangeWindowFlags.CWStackMode, ref values);
912                         } else {
913                                 XLowerWindow(DisplayHandle, hWnd);
914                                 return true;
915                         }
916                         return false;
917                 }
918
919
920                 internal override bool Text(IntPtr handle, string text) {
921 #if notdef
922                         XTextProperty   property = new XTextProperty();
923
924                         property.encoding=
925                         XSetWMName(DisplayHandle, handle, ref property);
926 #else
927                         lock (xlib_lock) {
928                                 XStoreName(DisplayHandle, handle, text);
929                         }
930 #endif
931                         return true;
932                 }
933
934                 internal override bool GetText(IntPtr handle, out string text) {
935                         IntPtr  textptr;
936
937                         textptr = IntPtr.Zero;
938
939                         lock (xlib_lock) {
940                                 XFetchName(DisplayHandle, handle, ref textptr);
941                         }
942                         if (textptr != IntPtr.Zero) {
943                                 text = Marshal.PtrToStringAnsi(textptr);
944                                 XFree(textptr);
945                                 return true;
946                         } else {
947                                 text = "";
948                                 return false;
949                         }
950                 }
951
952                 internal override bool SetVisible(IntPtr handle, bool visible) {
953                         lock (xlib_lock) {
954                                 if (visible) {
955                                         XMapWindow(DisplayHandle, handle);
956                                         is_visible=true;
957                                 } else {
958                                         XUnmapWindow(DisplayHandle, handle);
959                                         is_visible=false;
960                                 }
961                         }
962                         return true;
963                 }
964
965                 internal override bool IsVisible(IntPtr handle) {
966                         return is_visible;
967                 }
968
969                 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
970                         XWindowAttributes       attributes=new XWindowAttributes();
971
972                         lock (xlib_lock) {
973                                 XGetWindowAttributes(DisplayHandle, handle, ref attributes);
974                                 XReparentWindow(DisplayHandle, handle, parent, attributes.x, attributes.y);
975                         }
976                         return IntPtr.Zero;
977                 }
978
979                 internal override IntPtr GetParent(IntPtr handle) {
980                         IntPtr  Root;
981                         IntPtr  Parent;
982                         IntPtr  Children;
983                         int     ChildCount;
984
985                         Root=IntPtr.Zero;
986                         Parent=IntPtr.Zero;
987                         Children=IntPtr.Zero;
988                         ChildCount=0;
989
990                         lock (xlib_lock) {
991                                 XQueryTree(DisplayHandle, handle, ref Root, ref Parent, ref Children, ref ChildCount);
992                         }
993
994                         if (Children!=IntPtr.Zero) {
995                                 lock (xlib_lock) {
996                                         XFree(Children);
997                                 }
998                         }
999                         return Parent;
1000                 }
1001
1002                 internal override void GrabWindow(IntPtr hWnd, IntPtr confine_hwnd) {
1003                         if (confine_hwnd != IntPtr.Zero) {
1004                                 XWindowAttributes       attributes = new XWindowAttributes();
1005
1006                                 lock (xlib_lock) {
1007                                         XGetWindowAttributes(DisplayHandle, confine_hwnd, ref attributes);
1008                                 }
1009                                 grab_area.X = attributes.x;
1010                                 grab_area.Y = attributes.y;
1011                                 grab_area.Width = attributes.width;
1012                                 grab_area.Height = attributes.height;
1013                                 grab_confined = true;
1014                         }
1015                         grab_hwnd = hWnd;
1016                         lock (xlib_lock) {
1017                                 XGrabPointer(DisplayHandle, hWnd, false,
1018                                         EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
1019                                         EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
1020                                         GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_hwnd, 0, 0);
1021                         }
1022                 }
1023
1024                 internal override void GrabInfo(out IntPtr hWnd, out bool GrabConfined, out Rectangle GrabArea) {
1025                         hWnd = grab_hwnd;
1026                         GrabConfined = grab_confined;
1027                         GrabArea = grab_area;
1028                 }
1029
1030                 internal override void ReleaseWindow(IntPtr hWnd) {
1031                         lock (xlib_lock) {
1032                                 XUngrabPointer(DisplayHandle, 0);
1033                                 grab_hwnd = IntPtr.Zero;
1034                                 grab_confined = false;
1035                         }
1036                 }
1037
1038                 internal override bool CalculateWindowRect(IntPtr hWnd, ref Rectangle ClientRect, int Style, bool HasMenu, out Rectangle WindowRect) {
1039                         WindowRect = new Rectangle(ClientRect.Left, ClientRect.Top, ClientRect.Width, ClientRect.Height);
1040                         return true;
1041                 }
1042
1043                 internal override void SetCursorPos(IntPtr handle, int x, int y) {
1044                         lock (xlib_lock) {
1045                                 XWarpPointer(DisplayHandle, IntPtr.Zero, (handle!=IntPtr.Zero) ? handle : IntPtr.Zero, 0, 0, 0, 0, x, y);
1046                         }
1047                 }
1048
1049                 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
1050                         IntPtr  root;
1051                         IntPtr  child;
1052                         int     root_x;
1053                         int     root_y;
1054                         int     win_x;
1055                         int     win_y;
1056                         int     keys_buttons;
1057
1058                         lock (xlib_lock) {
1059                                 XQueryPointer(DisplayHandle, (handle!=IntPtr.Zero) ? handle : root_window,
1060                                                 out root, out child, out root_x, out root_y,
1061                                                 out win_x, out win_y, out keys_buttons);
1062                         }
1063
1064                         if (handle != IntPtr.Zero) {
1065                                 x = win_x;
1066                                 y = win_y;
1067                         } else {
1068                                 x = root_x;
1069                                 y = root_y;
1070                         }
1071                 }
1072
1073                 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y)
1074                 {
1075                         int     dest_x_return;
1076                         int     dest_y_return;
1077                         IntPtr  child;
1078
1079                         lock (xlib_lock) {
1080                                 XTranslateCoordinates (DisplayHandle, root_window,
1081                                                 handle, x, y, out dest_x_return, out dest_y_return, out child);
1082                         }
1083
1084                         x = dest_x_return;
1085                         y = dest_y_return;
1086                 }
1087
1088                 internal override void SendAsyncMethod (AsyncMethodData method)
1089                 {
1090                         XEvent xevent = new XEvent ();
1091                         
1092                         xevent.type = XEventName.ClientMessage;
1093                         xevent.ClientMessageEvent.display = DisplayHandle;
1094                         xevent.ClientMessageEvent.window = IntPtr.Zero;
1095                         xevent.ClientMessageEvent.message_type = async_method;
1096                         xevent.ClientMessageEvent.format = 32;
1097                         xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
1098
1099                         lock (message_queue) {
1100                                 message_queue.Enqueue (xevent);
1101                         }
1102
1103                         WakeupMain ();
1104                 }
1105
1106                 private void WakeupMain ()
1107                 {
1108                         wake.BeginSend (new byte [] { 0xFF }, 0, 1, SocketFlags.None, null, null);
1109                 }
1110
1111                 internal override void SetTimer (Timer timer)
1112                 {
1113                         lock (timer_list) {
1114                                 timer_list.Add (timer);
1115                         }
1116                         WakeupMain ();
1117                 }
1118
1119                 internal override void KillTimer (Timer timer)
1120                 {
1121                         lock (timer_list) {
1122                                 timer_list.Remove (timer);
1123                         }
1124                 }
1125
1126                 // Santa's little helper
1127                 static void Where() 
1128                 {
1129                         Console.WriteLine("Here: {0}", new StackTrace().ToString());
1130                 }
1131                 #endregion      // Public Static Methods
1132
1133                 internal struct X11ToWin32KeyMapping {
1134                         internal XKeySym                        X11Key;
1135                         internal XplatUIWin32.VirtualKeys       Win32Key;       
1136
1137                         internal X11ToWin32KeyMapping (XKeySym x11, XplatUIWin32.VirtualKeys win32)
1138                         {
1139                                 X11Key = x11;
1140                                 Win32Key = win32;
1141                         } 
1142                 }
1143
1144                 /* X11 to Win32 VK mapping */
1145                 static readonly X11ToWin32KeyMapping[] KeyMapping = new X11ToWin32KeyMapping[] 
1146                 {
1147                         /* Cursor navigation*/
1148                         new X11ToWin32KeyMapping (XKeySym.XK_Left, XplatUIWin32.VirtualKeys.VK_LEFT),
1149                         new X11ToWin32KeyMapping (XKeySym.XK_Right, XplatUIWin32.VirtualKeys.VK_RIGHT),
1150                         new X11ToWin32KeyMapping (XKeySym.XK_Up, XplatUIWin32.VirtualKeys.VK_UP),
1151                         new X11ToWin32KeyMapping (XKeySym.XK_Down, XplatUIWin32.VirtualKeys.VK_DOWN),
1152
1153                         new X11ToWin32KeyMapping (XKeySym.XK_Page_Up, XplatUIWin32.VirtualKeys.VK_PRIOR),
1154                         new X11ToWin32KeyMapping (XKeySym.XK_Page_Down, XplatUIWin32.VirtualKeys.VK_NEXT),
1155                         new X11ToWin32KeyMapping (XKeySym.XK_End, XplatUIWin32.VirtualKeys.VK_END),
1156                         new X11ToWin32KeyMapping (XKeySym.XK_Home, XplatUIWin32.VirtualKeys.VK_HOME),
1157
1158                         /* Modifiers*/
1159                         new X11ToWin32KeyMapping (XKeySym.XK_Shift_R, XplatUIWin32.VirtualKeys.VK_SHIFT),
1160                         new X11ToWin32KeyMapping (XKeySym.XK_Shift_L, XplatUIWin32.VirtualKeys.VK_SHIFT),
1161                         new X11ToWin32KeyMapping (XKeySym.XK_Control_R, XplatUIWin32.VirtualKeys.VK_CONTROL),
1162                         new X11ToWin32KeyMapping (XKeySym.XK_Control_L, XplatUIWin32.VirtualKeys.VK_CONTROL),                   
1163
1164                         /* Others */
1165                         new X11ToWin32KeyMapping (XKeySym.XK_Return, XplatUIWin32.VirtualKeys.VK_RETURN),
1166                         new X11ToWin32KeyMapping (XKeySym.XK_Tab, XplatUIWin32.VirtualKeys.VK_TAB),
1167                         new X11ToWin32KeyMapping (XKeySym.XK_Menu, XplatUIWin32.VirtualKeys.VK_MENU),
1168                         new X11ToWin32KeyMapping (XKeySym.XK_BackSpace, XplatUIWin32.VirtualKeys.VK_BACK),
1169                         new X11ToWin32KeyMapping (XKeySym.XK_Clear, XplatUIWin32.VirtualKeys.VK_CLEAR),
1170                         
1171                 };
1172
1173                 
1174
1175                 #region X11 Imports
1176                 [DllImport ("libX11.so", EntryPoint="XOpenDisplay")]
1177                 internal extern static IntPtr XOpenDisplay(IntPtr display);
1178                 [DllImport ("libX11.so", EntryPoint="XCloseDisplay")]
1179                 internal extern static void XCloseDisplay(IntPtr display);                                                  
1180
1181                 [DllImport ("libX11.so", EntryPoint="XCreateWindow")]
1182                 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, IntPtr attributes);
1183                 [DllImport ("libX11.so", EntryPoint="XCreateSimpleWindow")]
1184                 internal extern static IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, int width, int height, int border_width, int border, int background);
1185                 [DllImport ("libX11.so", EntryPoint="XMapWindow")]
1186                 internal extern static int XMapWindow(IntPtr display, IntPtr window);
1187                 [DllImport ("libX11.so", EntryPoint="XUnmapWindow")]
1188                 internal extern static int XUnmapWindow(IntPtr display, IntPtr window);
1189                 [DllImport ("libX11.so", EntryPoint="XRootWindow")]
1190                 internal extern static IntPtr XRootWindow(IntPtr display, int screen_number);
1191                 [DllImport ("libX11.so", EntryPoint="XNextEvent")]
1192                 internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
1193                 [DllImport ("libX11.so")]
1194                 internal extern static int XConnectionNumber (IntPtr diplay);
1195                 [DllImport ("libX11.so")]
1196                 internal extern static int XPending (IntPtr diplay);
1197                 [DllImport ("libX11.so")]
1198                 internal extern static bool XCheckWindowEvent (IntPtr display, IntPtr window, EventMask mask, ref XEvent xevent);
1199                 [DllImport ("libX11.so")]
1200                 internal extern static bool XCheckMaskEvent (IntPtr display, EventMask mask, ref XEvent xevent);
1201                 [DllImport ("libX11.so", EntryPoint="XSelectInput")]
1202                 internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, EventMask mask);
1203                 [DllImport ("libX11.so", EntryPoint="XLookupString")]
1204                 internal extern static int XLookupString(ref XEvent xevent, IntPtr buffer, int num_bytes, out XKeySym keysym, IntPtr status);
1205
1206                 [DllImport ("libX11.so", EntryPoint="XDestroyWindow")]
1207                 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
1208
1209                 [DllImport ("libX11.so", EntryPoint="XReparentWindow")]
1210                 internal extern static int XReparentWindow(IntPtr display, IntPtr window, IntPtr parent, int x, int y);
1211                 [DllImport ("libX11.so", EntryPoint="XMoveResizeWindow")]
1212                 internal extern static int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, int width, int height);
1213
1214                 [DllImport ("libX11.so", EntryPoint="XResizeWindow")]
1215                 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
1216
1217                 [DllImport ("libX11.so", EntryPoint="XGetWindowAttributes")]
1218                 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
1219
1220                 [DllImport ("libX11.so", EntryPoint="XFlush")]
1221                 internal extern static int XFlush(IntPtr display);
1222
1223                 [DllImport ("libX11.so", EntryPoint="XSetWMName")]
1224                 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
1225
1226                 [DllImport ("libX11.so", EntryPoint="XStoreName")]
1227                 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
1228
1229                 [DllImport ("libX11.so", EntryPoint="XFetchName")]
1230                 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
1231
1232                 [DllImport ("libX11.so", EntryPoint="XSendEvent")]
1233                 internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event);
1234
1235                 [DllImport ("libX11.so", EntryPoint="XQueryTree")]
1236                 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);
1237
1238                 [DllImport ("libX11.so", EntryPoint="XFree")]
1239                 internal extern static int XFree(IntPtr data);
1240
1241                 [DllImport ("libX11.so", EntryPoint="XRaiseWindow")]
1242                 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
1243
1244                 [DllImport ("libX11.so", EntryPoint="XLowerWindow")]
1245                 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
1246
1247                 [DllImport ("libX11.so", EntryPoint="XConfigureWindow")]
1248                 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
1249
1250                 [DllImport ("libX11.so", EntryPoint="XInternAtom")]
1251                 internal extern static int XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
1252
1253                 [DllImport ("libX11.so", EntryPoint="XSetWMProtocols")]
1254                 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, ref int protocols, int count);
1255
1256                 [DllImport ("libX11.so", EntryPoint="XGrabPointer")]
1257                 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);
1258
1259                 [DllImport ("libX11.so", EntryPoint="XUngrabPointer")]
1260                 internal extern static int XUngrabPointer(IntPtr display, uint timestamp);
1261
1262                 [DllImport ("libX11.so", EntryPoint="XQueryPointer")]
1263                 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);
1264
1265                 [DllImport ("libX11.so", EntryPoint="XTranslateCoordinates")]
1266                 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);
1267
1268                 [DllImport ("libX11.so", EntryPoint="XGetGeometry")]
1269                 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);
1270
1271                 [DllImport ("libX11.so", EntryPoint="XAllocColor")]
1272                 internal extern static int XAllocColor(IntPtr display, uint Colormap, ref XColor colorcell_def);
1273
1274                 [DllImport ("libX11.so", EntryPoint="XGetStandardColormap")]
1275                 internal extern static int XGetStandardColormap(IntPtr display, IntPtr window, ref XStandardColormap cmap_info, Atom property);
1276
1277                 [DllImport ("libX11.so", EntryPoint="XSetRGBColormaps")]
1278                 internal extern static int XSetRGBColormaps(IntPtr display, IntPtr window, ref XStandardColormap cmap_info, int count, Atom property);
1279
1280                 [DllImport ("libX11.so", EntryPoint="XInstallColormap")]
1281                 internal extern static int XInstallColormap(IntPtr display, uint cmap);
1282
1283                 [DllImport ("libX11.so", EntryPoint="XDefaultColormap")]
1284                 internal extern static uint XDefaultColormap(IntPtr display, int screen_number);
1285
1286                 [DllImport ("libX11.so", EntryPoint="XDefaultDepth")]
1287                 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
1288
1289                 [DllImport ("libX11.so", EntryPoint="XDefaultVisual")]
1290                 internal extern static uint XDefaultVisual(IntPtr display, int screen_number);
1291
1292                 [DllImport ("libX11.so", EntryPoint="XSetWindowColormap")]
1293                 internal extern static uint XSetWindowColormap(IntPtr display, IntPtr window, uint cmap);
1294
1295                 [DllImport ("libX11.so", EntryPoint="XWarpPointer")]
1296                 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);
1297
1298                 // Drawing
1299                 [DllImport ("libX11.so", EntryPoint="XCreateGC")]
1300                 internal extern static IntPtr XCreateGC(IntPtr display, IntPtr window, int valuemask, IntPtr values);
1301                 [DllImport ("libX11.so", EntryPoint="XFreeGC")]
1302                 internal extern static int XFreeGC(IntPtr display, IntPtr gc);
1303                 [DllImport ("libX11.so", EntryPoint="XSetWindowBackground")]
1304                 internal extern static int XSetWindowBackground(IntPtr display, IntPtr window, uint background);
1305                 #endregion
1306
1307         }
1308 }