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:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
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.
20 // Copyright (c) 2004 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
30 using System.Threading;
32 using System.ComponentModel;
33 using System.Collections;
34 using System.Diagnostics;
35 using System.Runtime.InteropServices;
37 using System.Net.Sockets;
39 // Only do the poll when building with mono for now
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;
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;
67 private static Hashtable handle_data;
68 private Queue message_queue;
70 private ArrayList timer_list;
71 private Thread timer_thread;
72 private AutoResetEvent timer_wait;
73 private Socket listen;
77 private pollfd [] pollfds;
80 private object xlib_lock = new object ();
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;
93 #endregion // Local Variables
95 internal override Keys ModifierKeys {
101 internal override MouseButtons MouseButtons {
107 internal override Point MousePosition {
109 return mouse_position;
113 internal override bool DropTarget {
120 throw new NotImplementedException("Need to figure out D'n'D for X11");
125 #region Constructor & Destructor
126 // This is always called from a locked context
127 private XplatUIX11() {
128 // Handle singleton stuff first
131 message_queue = new Queue ();
132 timer_list = new ArrayList ();
134 // Now regular initialization
135 SetDisplay(XOpenDisplay(IntPtr.Zero));
137 listen = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
138 IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 0);
142 wake = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
143 wake.Connect (listen.LocalEndPoint);
146 pollfds = new pollfd [2];
147 pollfds [0] = new pollfd ();
148 pollfds [0].fd = XConnectionNumber (DisplayHandle);
149 pollfds [0].events = PollEvents.POLLIN;
151 pollfds [1] = new pollfd ();
152 pollfds [1].fd = wake.Handle.ToInt32 ();
153 pollfds [1].events = PollEvents.POLLIN;
159 if (DisplayHandle!=IntPtr.Zero) {
160 XCloseDisplay(DisplayHandle);
161 DisplayHandle=IntPtr.Zero;
165 #endregion // Constructor & Destructor
167 #region Singleton Specific Code
168 public static XplatUIX11 GetInstance() {
169 lock (typeof (XplatUIX11)) {
170 if (instance==null) {
171 instance=new XplatUIX11();
178 public int Reference {
185 internal override event EventHandler Idle;
187 #region Public Static Methods
188 internal override IntPtr InitializeDriver() {
190 if (DisplayHandle==IntPtr.Zero) {
191 DisplayHandle=XOpenDisplay(IntPtr.Zero);
193 mouse_state=MouseButtons.None;
194 mouse_position=Point.Empty;
200 internal static void SetDisplay(IntPtr display_handle) {
201 if (display_handle != IntPtr.Zero) {
202 if (FosterParent != IntPtr.Zero) {
203 XDestroyWindow(DisplayHandle, FosterParent);
205 if (DisplayHandle != IntPtr.Zero) {
206 XCloseDisplay(DisplayHandle);
209 DisplayHandle=display_handle;
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);
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");
224 // Prepare for shutdown
225 wm_protocols=XInternAtom(display_handle, "WM_PROTOCOLS", false);
226 wm_delete_window=XInternAtom(display_handle, "WM_DELETE_WINDOW", false);
228 handle_data = new Hashtable ();
232 internal override void ShutdownDriver(IntPtr token) {
234 if (DisplayHandle!=IntPtr.Zero) {
235 XCloseDisplay(DisplayHandle);
236 DisplayHandle=IntPtr.Zero;
242 internal void Version() {
243 Console.WriteLine("Xplat version $revision: $");
246 internal override void Exit() {
247 Console.WriteLine("XplatUIX11.Exit");
250 internal override void GetDisplaySize(out Size size) {
251 XWindowAttributes attributes=new XWindowAttributes();
254 XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
257 size = new Size(attributes.width, attributes.height);
260 internal override void EnableThemes() {
264 internal override IntPtr CreateWindow(CreateParams cp) {
274 ParentHandle=cp.Parent;
282 if (Width<1) Width=1;
283 if (Height<1) Height=1;
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;
296 ParentHandle=XRootWindow(DisplayHandle, 0);
300 WindowHandle=XCreateSimpleWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, BorderWidth, 0, 0);
301 XMapWindow(DisplayHandle, WindowHandle);
303 XSelectInput(DisplayHandle, WindowHandle, SelectInputMask);
306 protocols=wm_delete_window;
307 XSetWMProtocols(DisplayHandle, WindowHandle, ref protocols, 1);
309 return(WindowHandle);
312 internal override IntPtr CreateWindow(IntPtr Parent, int X, int Y, int Width, int Height) {
313 CreateParams create_params = new CreateParams();
315 create_params.Caption = "";
318 create_params.Width = Width;
319 create_params.Height = Height;
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;
327 return CreateWindow(create_params);
330 internal override void DestroyWindow(IntPtr handle) {
332 HandleData data = (HandleData) handle_data [handle];
335 handle_data [handle] = null;
340 internal override void RefreshWindow(IntPtr handle) {
341 XEvent xevent = new XEvent();
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);
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;
364 XSendEvent(DisplayHandle, handle, false, EventMask.ExposureMask, ref xevent);
365 XFlush(DisplayHandle);
369 internal override void SetWindowBackground(IntPtr handle, Color color) {
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) );
375 XSetWindowBackground(DisplayHandle, handle, backcolor);
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;
383 HandleData data = (HandleData) handle_data [handle];
385 throw new Exception ("null data on paint event start: " + handle);
389 data.DeviceContext = Graphics.FromHwnd (handle);
390 paint_event = new PaintEventArgs((Graphics)data.DeviceContext, data.InvalidArea);
395 internal override void PaintEventEnd(IntPtr handle) {
396 HandleData data = (HandleData) handle_data [handle];
398 throw new Exception ("null data on PaintEventEnd");
399 data.ClearInvalidArea ();
400 Graphics g = (Graphics) data.DeviceContext;
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
415 XMoveResizeWindow(DisplayHandle, handle, x, y, width, height);
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) {
427 XGetGeometry(DisplayHandle, handle, out root, out x,
428 out y, out width, out height, out border_width, out depth);
431 client_width = width;
432 client_height = height;
436 internal override void Activate(IntPtr handle) {
439 // Not sure this is the right method, but we don't use ICs either...
440 XRaiseWindow(DisplayHandle, handle);
445 internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
446 XEvent xevent = new XEvent();
448 xevent.type=XEventName.Expose;
449 xevent.ExposeEvent.display=DisplayHandle;
450 xevent.ExposeEvent.window=handle;
451 xevent.ExposeEvent.count=0;
456 // Need to clear the whole window, so we force a redraw for the whole window
457 XWindowAttributes attributes=new XWindowAttributes();
459 // We need info about our window to generate the expose
460 XGetWindowAttributes(DisplayHandle, handle, ref attributes);
462 xevent.ExposeEvent.x=0;
463 xevent.ExposeEvent.y=0;
464 xevent.ExposeEvent.width=attributes.width;
465 xevent.ExposeEvent.height=attributes.height;
467 xevent.ExposeEvent.x=rc.Left;
468 xevent.ExposeEvent.y=rc.Top;
469 xevent.ExposeEvent.width=rc.Width;
470 xevent.ExposeEvent.height=rc.Height;
473 XSendEvent(DisplayHandle, handle, false, EventMask.ExposureMask, ref xevent);
474 // Flush is not needed, invalidate does not guarantee an immediate effect
478 internal override IntPtr DefWndProc(ref Message msg) {
481 case (int)Msg.WM_PAINT: {
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);
495 Console.WriteLine("XplatUIX11.DefWndProc");
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());
506 internal override void DoEvents() {
507 Console.WriteLine("XplatUIX11.DoEvents");
510 internal override bool PeekMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax, uint flags) {
511 Console.WriteLine("XplatUIX11.PeekMessage");
515 private void CreateKeyBoardMsg (XEvent xevent, ref MSG msg)
517 IntPtr buffer = Marshal.AllocHGlobal(24);
521 msg.wParam = IntPtr.Zero;
524 len = XLookupString(ref xevent, buffer, 24, out keysym, IntPtr.Zero);
527 if ((keysym==XKeySym.XK_Control_L) || (keysym==XKeySym.XK_Control_R)) {
528 if (xevent.type==XEventName.KeyPress) {
529 key_state |= Keys.Control;
531 key_state &= ~Keys.Control;
535 if ((keysym==XKeySym.XK_Shift_L) || (keysym==XKeySym.XK_Shift_R)) {
536 if (xevent.type==XEventName.KeyPress) {
537 key_state |= Keys.Shift;
539 key_state &= ~Keys.Shift;
543 if (len>0) /* String is not zero terminated*/
544 Marshal.WriteByte (buffer, len, 0);
546 keys=Marshal.PtrToStringAuto(buffer);
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);
556 if ((msg.wParam == IntPtr.Zero) && (keys.Length>0)) {
558 keychars=keys.ToCharArray(0, 1);
559 msg.wParam=(IntPtr)keychars[0];
560 Console.WriteLine("Got key {0} {1:x} ", keysym, keysym);
563 Marshal.FreeHGlobal (buffer);
564 msg.lParam = (IntPtr) 1;
567 private IntPtr GetMousewParam(int Delta) {
570 if ((mouse_state & MouseButtons.Left) != 0) {
571 result |= (int)MsgButtons.MK_LBUTTON;
574 if ((mouse_state & MouseButtons.Middle) != 0) {
575 result |= (int)MsgButtons.MK_MBUTTON;
578 if ((mouse_state & MouseButtons.Right) != 0) {
579 result |= (int)MsgButtons.MK_RBUTTON;
582 if ((key_state & Keys.Control) != 0) {
583 result |= (int)MsgButtons.MK_CONTROL;
586 if ((key_state & Keys.Shift) != 0) {
587 result |= (int)MsgButtons.MK_SHIFT;
590 result |= Delta << 16;
592 return (IntPtr)result;
595 private int NextTimeout (DateTime now)
597 int timeout = Int32.MaxValue;
599 foreach (Timer timer in timer_list) {
600 int next = (int) (timer.Expires - now).TotalMilliseconds;
602 return 0; // Have a timer that has already expired
607 if (timeout < Timer.Minimum)
608 timeout = Timer.Minimum;
612 private void CheckTimers (DateTime now)
615 int count = timer_list.Count;
618 for (int i = 0; i < count; i++) {
619 Timer timer = (Timer) timer_list [i];
620 if (timer.Enabled && timer.Expires <= now) {
628 private void UpdateMessageQueue ()
630 DateTime now = DateTime.Now;
634 pending = XPending (DisplayHandle);
638 Idle (this, EventArgs.Empty);
641 pending = XPending (DisplayHandle);
646 int timeout = NextTimeout (now);
649 Syscall.poll (pollfds, pollfds.Length, timeout);
651 pending = XPending (DisplayHandle);
659 pending = XPending (DisplayHandle);
663 while (pending > 0) {
664 XEvent xevent = new XEvent ();
667 XNextEvent (DisplayHandle, ref xevent);
670 switch (xevent.type) {
671 case XEventName.Expose:
672 HandleData data = (HandleData) handle_data [xevent.AnyEvent.window];
674 data = new HandleData ();
675 handle_data [xevent.AnyEvent.window] = data;
678 data.AddToInvalidArea (xevent.ExposeEvent.x, xevent.ExposeEvent.y,
679 xevent.ExposeEvent.width, xevent.ExposeEvent.height);
681 if (!data.HasExpose) {
682 lock (message_queue) {
683 message_queue.Enqueue (xevent);
685 data.HasExpose = true;
689 lock (message_queue) {
690 message_queue.Enqueue (xevent);
696 pending = XPending (DisplayHandle);
701 internal override bool GetMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax) {
704 if (message_queue.Count > 0) {
705 xevent = (XEvent) message_queue.Dequeue ();
707 UpdateMessageQueue ();
708 if (message_queue.Count > 0) {
709 xevent = (XEvent) message_queue.Dequeue ();
711 msg.hwnd= IntPtr.Zero;
712 msg.message = Msg.WM_ENTERIDLE;
717 msg.hwnd=xevent.AnyEvent.window;
719 switch(xevent.type) {
720 case XEventName.KeyPress: {
721 msg.message = Msg.WM_KEYDOWN;
722 CreateKeyBoardMsg (xevent, ref msg);
726 case XEventName.KeyRelease: {
727 msg.message=Msg.WM_KEYUP;
728 CreateKeyBoardMsg (xevent, ref msg);
732 case XEventName.ButtonPress: {
733 switch(xevent.ButtonEvent.button) {
735 mouse_state |= MouseButtons.Left;
736 msg.message=Msg.WM_LBUTTONDOWN;
737 msg.wParam=GetMousewParam(0);
742 mouse_state |= MouseButtons.Middle;
743 msg.message=Msg.WM_MBUTTONDOWN;
744 msg.wParam=GetMousewParam(0);
749 mouse_state |= MouseButtons.Right;
750 msg.message=Msg.WM_RBUTTONDOWN;
751 msg.wParam=GetMousewParam(0);
756 msg.message=Msg.WM_MOUSEWHEEL;
757 msg.wParam=GetMousewParam(120);
762 msg.message=Msg.WM_MOUSEWHEEL;
763 msg.wParam=GetMousewParam(-120);
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;
775 case XEventName.ButtonRelease: {
776 switch(xevent.ButtonEvent.button) {
778 mouse_state &= ~MouseButtons.Left;
779 msg.message=Msg.WM_LBUTTONUP;
780 msg.wParam=GetMousewParam(0);
785 mouse_state &= ~MouseButtons.Middle;
786 msg.message=Msg.WM_MBUTTONUP;
787 msg.wParam=GetMousewParam(0);
792 mouse_state &= ~MouseButtons.Right;
793 msg.message=Msg.WM_RBUTTONUP;
794 msg.wParam=GetMousewParam(0);
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;
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;
822 case XEventName.EnterNotify: {
823 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
826 msg.message=Msg.WM_MOUSE_ENTER;
830 case XEventName.LeaveNotify: {
831 if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
834 msg.message=Msg.WM_MOUSE_LEAVE;
838 case XEventName.ConfigureNotify: {
839 msg.message=Msg.WM_WINDOWPOSCHANGED;
840 msg.wParam=IntPtr.Zero;
841 msg.lParam=IntPtr.Zero;
846 case XEventName.Expose: {
847 msg.message=Msg.WM_PAINT;
848 msg.wParam=IntPtr.Zero;
849 msg.lParam=IntPtr.Zero;
853 case XEventName.DestroyNotify: {
854 msg.message=Msg.WM_DESTROY;
855 msg.wParam=IntPtr.Zero;
856 msg.lParam=IntPtr.Zero;
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);
867 result.Complete (ret);
870 msg.message=Msg.WM_QUIT;
871 msg.wParam=IntPtr.Zero;
872 msg.lParam=IntPtr.Zero;
878 case XEventName.TimerNotify: {
879 xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
884 msg.message = Msg.WM_NULL;
889 NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
894 internal override bool TranslateMessage(ref MSG msg) {
898 internal override bool DispatchMessage(ref MSG msg) {
902 internal override bool SetZOrder(IntPtr hWnd, IntPtr AfterhWnd, bool Top, bool Bottom) {
904 XRaiseWindow(DisplayHandle, hWnd);
906 } else if (!Bottom) {
907 XWindowChanges values = new XWindowChanges();
909 values.sibling = AfterhWnd;
910 values.stack_mode = StackMode.Below;
911 XConfigureWindow(DisplayHandle, hWnd, ChangeWindowFlags.CWStackMode, ref values);
913 XLowerWindow(DisplayHandle, hWnd);
920 internal override bool Text(IntPtr handle, string text) {
922 XTextProperty property = new XTextProperty();
925 XSetWMName(DisplayHandle, handle, ref property);
928 XStoreName(DisplayHandle, handle, text);
934 internal override bool GetText(IntPtr handle, out string text) {
937 textptr = IntPtr.Zero;
940 XFetchName(DisplayHandle, handle, ref textptr);
942 if (textptr != IntPtr.Zero) {
943 text = Marshal.PtrToStringAnsi(textptr);
952 internal override bool SetVisible(IntPtr handle, bool visible) {
955 XMapWindow(DisplayHandle, handle);
958 XUnmapWindow(DisplayHandle, handle);
965 internal override bool IsVisible(IntPtr handle) {
969 internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
970 XWindowAttributes attributes=new XWindowAttributes();
973 XGetWindowAttributes(DisplayHandle, handle, ref attributes);
974 XReparentWindow(DisplayHandle, handle, parent, attributes.x, attributes.y);
979 internal override IntPtr GetParent(IntPtr handle) {
987 Children=IntPtr.Zero;
991 XQueryTree(DisplayHandle, handle, ref Root, ref Parent, ref Children, ref ChildCount);
994 if (Children!=IntPtr.Zero) {
1002 internal override void GrabWindow(IntPtr hWnd, IntPtr confine_hwnd) {
1003 if (confine_hwnd != IntPtr.Zero) {
1004 XWindowAttributes attributes = new XWindowAttributes();
1007 XGetWindowAttributes(DisplayHandle, confine_hwnd, ref attributes);
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;
1017 XGrabPointer(DisplayHandle, hWnd, false,
1018 EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
1019 EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
1020 GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_hwnd, 0, 0);
1024 internal override void GrabInfo(out IntPtr hWnd, out bool GrabConfined, out Rectangle GrabArea) {
1026 GrabConfined = grab_confined;
1027 GrabArea = grab_area;
1030 internal override void ReleaseWindow(IntPtr hWnd) {
1032 XUngrabPointer(DisplayHandle, 0);
1033 grab_hwnd = IntPtr.Zero;
1034 grab_confined = false;
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);
1043 internal override void SetCursorPos(IntPtr handle, int x, int y) {
1045 XWarpPointer(DisplayHandle, IntPtr.Zero, (handle!=IntPtr.Zero) ? handle : IntPtr.Zero, 0, 0, 0, 0, x, y);
1049 internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
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);
1064 if (handle != IntPtr.Zero) {
1073 internal override void ScreenToClient(IntPtr handle, ref int x, ref int y)
1080 XTranslateCoordinates (DisplayHandle, root_window,
1081 handle, x, y, out dest_x_return, out dest_y_return, out child);
1088 internal override void SendAsyncMethod (AsyncMethodData method)
1090 XEvent xevent = new XEvent ();
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);
1099 lock (message_queue) {
1100 message_queue.Enqueue (xevent);
1106 private void WakeupMain ()
1108 wake.BeginSend (new byte [] { 0xFF }, 0, 1, SocketFlags.None, null, null);
1111 internal override void SetTimer (Timer timer)
1114 timer_list.Add (timer);
1119 internal override void KillTimer (Timer timer)
1122 timer_list.Remove (timer);
1126 // Santa's little helper
1129 Console.WriteLine("Here: {0}", new StackTrace().ToString());
1131 #endregion // Public Static Methods
1133 internal struct X11ToWin32KeyMapping {
1134 internal XKeySym X11Key;
1135 internal XplatUIWin32.VirtualKeys Win32Key;
1137 internal X11ToWin32KeyMapping (XKeySym x11, XplatUIWin32.VirtualKeys win32)
1144 /* X11 to Win32 VK mapping */
1145 static readonly X11ToWin32KeyMapping[] KeyMapping = new X11ToWin32KeyMapping[]
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),
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),
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),
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),
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);
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);
1206 [DllImport ("libX11.so", EntryPoint="XDestroyWindow")]
1207 internal extern static int XDestroyWindow(IntPtr display, IntPtr window);
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);
1214 [DllImport ("libX11.so", EntryPoint="XResizeWindow")]
1215 internal extern static int XResizeWindow(IntPtr display, IntPtr window, int width, int height);
1217 [DllImport ("libX11.so", EntryPoint="XGetWindowAttributes")]
1218 internal extern static int XGetWindowAttributes(IntPtr display, IntPtr window, ref XWindowAttributes attributes);
1220 [DllImport ("libX11.so", EntryPoint="XFlush")]
1221 internal extern static int XFlush(IntPtr display);
1223 [DllImport ("libX11.so", EntryPoint="XSetWMName")]
1224 internal extern static int XSetWMName(IntPtr display, IntPtr window, ref XTextProperty text_prop);
1226 [DllImport ("libX11.so", EntryPoint="XStoreName")]
1227 internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
1229 [DllImport ("libX11.so", EntryPoint="XFetchName")]
1230 internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
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);
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);
1238 [DllImport ("libX11.so", EntryPoint="XFree")]
1239 internal extern static int XFree(IntPtr data);
1241 [DllImport ("libX11.so", EntryPoint="XRaiseWindow")]
1242 internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
1244 [DllImport ("libX11.so", EntryPoint="XLowerWindow")]
1245 internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
1247 [DllImport ("libX11.so", EntryPoint="XConfigureWindow")]
1248 internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
1250 [DllImport ("libX11.so", EntryPoint="XInternAtom")]
1251 internal extern static int XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
1253 [DllImport ("libX11.so", EntryPoint="XSetWMProtocols")]
1254 internal extern static int XSetWMProtocols(IntPtr display, IntPtr window, ref int protocols, int count);
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);
1259 [DllImport ("libX11.so", EntryPoint="XUngrabPointer")]
1260 internal extern static int XUngrabPointer(IntPtr display, uint timestamp);
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);
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);
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);
1271 [DllImport ("libX11.so", EntryPoint="XAllocColor")]
1272 internal extern static int XAllocColor(IntPtr display, uint Colormap, ref XColor colorcell_def);
1274 [DllImport ("libX11.so", EntryPoint="XGetStandardColormap")]
1275 internal extern static int XGetStandardColormap(IntPtr display, IntPtr window, ref XStandardColormap cmap_info, Atom property);
1277 [DllImport ("libX11.so", EntryPoint="XSetRGBColormaps")]
1278 internal extern static int XSetRGBColormaps(IntPtr display, IntPtr window, ref XStandardColormap cmap_info, int count, Atom property);
1280 [DllImport ("libX11.so", EntryPoint="XInstallColormap")]
1281 internal extern static int XInstallColormap(IntPtr display, uint cmap);
1283 [DllImport ("libX11.so", EntryPoint="XDefaultColormap")]
1284 internal extern static uint XDefaultColormap(IntPtr display, int screen_number);
1286 [DllImport ("libX11.so", EntryPoint="XDefaultDepth")]
1287 internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
1289 [DllImport ("libX11.so", EntryPoint="XDefaultVisual")]
1290 internal extern static uint XDefaultVisual(IntPtr display, int screen_number);
1292 [DllImport ("libX11.so", EntryPoint="XSetWindowColormap")]
1293 internal extern static uint XSetWindowColormap(IntPtr display, IntPtr window, uint cmap);
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);
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);