// NOT COMPLETE
using System;
+using System.Threading;
using System.Drawing;
using System.ComponentModel;
using System.Collections;
using System.Diagnostics;
using System.Runtime.InteropServices;
+using System.Net;
+using System.Net.Sockets;
+
+// Only do the poll when building with mono for now
+#if __MonoCS__
+using Mono.Posix;
+#endif
/// X11 Version
namespace System.Windows.Forms {
private static bool themes_enabled;
private static IntPtr DisplayHandle; // X11 handle to display
+ private static int screen_num; // Screen number used
private static IntPtr root_window; // Handle of the root window for the screen/display
private static IntPtr FosterParent; // Container to hold child windows until their parent exists
private static int wm_protocols; // X Atom
private static int wm_delete_window; // X Atom
+ private static IntPtr async_method;
private static uint default_colormap; // X Colormap ID
internal static Keys key_state;
internal static MouseButtons mouse_state;
internal static Point mouse_position;
+ internal static bool grab_confined; // Is the current grab (if any) confined to grab_area?
+ internal static IntPtr grab_hwnd; // The window that is grabbed
+ internal static Rectangle grab_area; // The area the current grab is confined to
internal static bool is_visible;
private static Hashtable handle_data;
+ private Queue message_queue;
+
+ private ArrayList timer_list;
+ private Thread timer_thread;
+ private AutoResetEvent timer_wait;
+ private Socket listen;
+ private Socket wake;
+
+#if __MonoCS__
+ private pollfd [] pollfds;
+#endif
+
+ private object xlib_lock = new object ();
+
+ private static readonly EventMask SelectInputMask = EventMask.ButtonPressMask |
+ EventMask.ButtonReleaseMask |
+ EventMask.KeyPressMask |
+ EventMask.KeyReleaseMask |
+ EventMask.EnterWindowMask |
+ EventMask.LeaveWindowMask |
+ EventMask.ExposureMask |
+ EventMask.PointerMotionMask |
+ EventMask.VisibilityChangeMask |
+ EventMask.StructureNotifyMask;
#endregion // Local Variables
}
#region Constructor & Destructor
-
-
+ // This is always called from a locked context
private XplatUIX11() {
// Handle singleton stuff first
ref_count=0;
+ message_queue = new Queue ();
+ timer_list = new ArrayList ();
+
// Now regular initialization
SetDisplay(XOpenDisplay(IntPtr.Zero));
+
+ listen = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
+ IPEndPoint ep = new IPEndPoint (IPAddress.Loopback, 0);
+ listen.Bind (ep);
+ listen.Listen (1);
+
+ wake = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
+ wake.Connect (listen.LocalEndPoint);
+
+#if __MonoCS__
+ pollfds = new pollfd [2];
+ pollfds [0] = new pollfd ();
+ pollfds [0].fd = XConnectionNumber (DisplayHandle);
+ pollfds [0].events = PollEvents.POLLIN;
+
+ pollfds [1] = new pollfd ();
+ pollfds [1].fd = wake.Handle.ToInt32 ();
+ pollfds [1].events = PollEvents.POLLIN;
+#endif
}
~XplatUIX11() {
- if (DisplayHandle!=IntPtr.Zero) {
- XCloseDisplay(DisplayHandle);
- DisplayHandle=IntPtr.Zero;
+ lock (this) {
+ if (DisplayHandle!=IntPtr.Zero) {
+ XCloseDisplay(DisplayHandle);
+ DisplayHandle=IntPtr.Zero;
+ }
}
}
#endregion // Constructor & Destructor
#region Singleton Specific Code
public static XplatUIX11 GetInstance() {
- if (instance==null) {
- instance=new XplatUIX11();
+ lock (typeof (XplatUIX11)) {
+ if (instance==null) {
+ instance=new XplatUIX11();
+ }
+ ref_count++;
}
- ref_count++;
return instance;
}
}
#endregion
+ internal override event EventHandler Idle;
+
#region Public Static Methods
- internal override IntPtr InitializeDriver() {\r
- if (DisplayHandle==IntPtr.Zero) {
- DisplayHandle=XOpenDisplay(IntPtr.Zero);
- key_state=Keys.None;
- mouse_state=MouseButtons.None;
- mouse_position=Point.Empty;
- }
-
- return IntPtr.Zero;\r
- }\r
-\r
- internal static void SetDisplay(IntPtr display_handle) {\r
- if (display_handle != IntPtr.Zero) {\r
+ internal override IntPtr InitializeDriver() {
+ lock (this) {
+ if (DisplayHandle==IntPtr.Zero) {
+ DisplayHandle=XOpenDisplay(IntPtr.Zero);
+ key_state=Keys.None;
+ mouse_state=MouseButtons.None;
+ mouse_position=Point.Empty;
+ }
+ }
+ return IntPtr.Zero;
+ }
+
+ internal static void SetDisplay(IntPtr display_handle) {
+ if (display_handle != IntPtr.Zero) {
+ IntPtr Screen;
+
if (FosterParent != IntPtr.Zero) {
XDestroyWindow(DisplayHandle, FosterParent);
}
- if (DisplayHandle != IntPtr.Zero) {\r
- XCloseDisplay(DisplayHandle);\r
- }\r
-\r
- DisplayHandle=display_handle;\r
-\r
- // Create a few things\r
+ if (DisplayHandle != IntPtr.Zero) {
+ XCloseDisplay(DisplayHandle);
+ }
+
+ DisplayHandle=display_handle;
+
+ // We need to tell System.Drawing our DisplayHandle. FromHdcInternal has
+ // been hacked to do this for us.
+ Graphics.FromHdcInternal (DisplayHandle);
+
+ // Create a few things
key_state = Keys.None;
mouse_state = MouseButtons.None;
mouse_position = Point.Empty;
- root_window = XRootWindow(display_handle, 0);
- default_colormap = XDefaultColormap(display_handle, 0);
+ Screen = XDefaultScreenOfDisplay(DisplayHandle);
+ //screen_num = XScreenNumberOfScreen(DisplayHandle, Screen);
+ screen_num = 0;
+ root_window = XRootWindow(display_handle, screen_num);
+ default_colormap = XDefaultColormap(display_handle, screen_num);
// Create the foster parent
FosterParent=XCreateSimpleWindow(display_handle, root_window, 0, 0, 1, 1, 4, 0, 0);
if (FosterParent==IntPtr.Zero) {
Console.WriteLine("XplatUIX11 Constructor failed to create FosterParent");
}
-
// Prepare for shutdown
wm_protocols=XInternAtom(display_handle, "WM_PROTOCOLS", false);
wm_delete_window=XInternAtom(display_handle, "WM_DELETE_WINDOW", false);
handle_data = new Hashtable ();
- }\r
- }\r
+ }
+ }
- internal override void ShutdownDriver(IntPtr token) {\r
- if (DisplayHandle!=IntPtr.Zero) {
- XCloseDisplay(DisplayHandle);
- DisplayHandle=IntPtr.Zero;
+ internal override void ShutdownDriver(IntPtr token) {
+ lock (this) {
+ if (DisplayHandle!=IntPtr.Zero) {
+ XCloseDisplay(DisplayHandle);
+ DisplayHandle=IntPtr.Zero;
+ }
}
- }\r
+ }
internal void Version() {
Console.WriteLine("XplatUIX11.Exit");
}
+ internal override void GetDisplaySize(out Size size) {
+ XWindowAttributes attributes=new XWindowAttributes();
+
+ lock (xlib_lock) {
+ XGetWindowAttributes(DisplayHandle, XRootWindow(DisplayHandle, 0), ref attributes);
+ }
+
+ size = new Size(attributes.width, attributes.height);
+ }
+
internal override void EnableThemes() {
themes_enabled=true;
}
if (Width<1) Width=1;
if (Height<1) Height=1;
- if (ParentHandle==IntPtr.Zero) {
- if ((cp.Style & (int)WindowStyles.WS_CHILD)!=0) {
- // We need to use our foster parent window until this poor child gets it's parent assigned
- ParentHandle=FosterParent;
- } else {
- if (X<1) X=50;
- if (Y<1) Y=50;
- BorderWidth=4;
- ParentHandle=XRootWindow(DisplayHandle, 0);
- }
- }
- WindowHandle=XCreateSimpleWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, BorderWidth, 0, (this.BackColor.ToArgb() & 0x00ffffff));
- XMapWindow(DisplayHandle, WindowHandle);
-
- XSelectInput(DisplayHandle, WindowHandle,
- EventMask.ButtonPressMask |
- EventMask.ButtonReleaseMask |
- EventMask.KeyPressMask |
- EventMask.KeyReleaseMask |
- EventMask.EnterWindowMask |
- EventMask.LeaveWindowMask |
- EventMask.ExposureMask |
- EventMask.PointerMotionMask |
- EventMask.VisibilityChangeMask |
- EventMask.StructureNotifyMask);
+ lock (xlib_lock) {
+ if (ParentHandle==IntPtr.Zero) {
+ if ((cp.Style & (int)WindowStyles.WS_CHILD)!=0) {
+ // We need to use our foster parent window until
+ // this poor child gets it's parent assigned
+ ParentHandle=FosterParent;
+ } else {
+ if (X<1) X=50;
+ if (Y<1) Y=50;
+ BorderWidth=4;
+ ParentHandle=XRootWindow(DisplayHandle, 0);
+ }
+ }
- is_visible=true;
+ WindowHandle=XCreateSimpleWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, BorderWidth, 0, 0);
+ XMapWindow(DisplayHandle, WindowHandle);
- protocols=wm_delete_window;
- XSetWMProtocols(DisplayHandle, WindowHandle, ref protocols, 1);
+ XSelectInput(DisplayHandle, WindowHandle, SelectInputMask);
+ is_visible=true;
+ protocols=wm_delete_window;
+ XSetWMProtocols(DisplayHandle, WindowHandle, ref protocols, 1);
+ }
return(WindowHandle);
}
}
internal override void DestroyWindow(IntPtr handle) {
- XDestroyWindow(DisplayHandle, handle);
- HandleData data = (HandleData) handle_data [handle];
- if (data != null) {
- data.Dispose ();
- handle_data[handle] = null;
+ lock (this) {
+ HandleData data = (HandleData) handle_data [handle];
+ if (data != null) {
+ data.Dispose ();
+ handle_data [handle] = null;
+ }
+ XDestroyWindow(DisplayHandle, handle);
}
- return;
}
internal override void RefreshWindow(IntPtr handle) {
int width;
int height;
- // We need info about our window to generate the expose
- XGetGeometry(DisplayHandle, handle, out root, out x, out y, out width, out height, out border_width, out depth);
+ lock (xlib_lock) {
+
+ // We need info about our window to generate the expose
+ XGetGeometry(DisplayHandle, handle, out root, out x, out y,
+ out width, out height, out border_width, out depth);
+
+ xevent.type=XEventName.Expose;
+ xevent.ExposeEvent.display=DisplayHandle;
+ xevent.ExposeEvent.window=handle;
+ xevent.ExposeEvent.x=0;
+ xevent.ExposeEvent.y=0;
+ xevent.ExposeEvent.width=width;
+ xevent.ExposeEvent.height=height;
+
+ XSendEvent(DisplayHandle, handle, false, EventMask.ExposureMask, ref xevent);
+ XFlush(DisplayHandle);
+ }
+ }
+
+ internal override void SetWindowBackground(IntPtr handle, Color color) {
+ XColor xcolor;
+
+ xcolor = new XColor();
- xevent.type=XEventName.Expose;
- xevent.ExposeEvent.display=DisplayHandle;
- xevent.ExposeEvent.window=handle;
- xevent.ExposeEvent.x=0;
- xevent.ExposeEvent.y=0;
- xevent.ExposeEvent.width=width;
- xevent.ExposeEvent.height=height;
+ xcolor.red = (ushort)(color.R * 257);
+ xcolor.green = (ushort)(color.G * 257);
+ xcolor.blue = (ushort)(color.B * 257);
+ XAllocColor(DisplayHandle, default_colormap, ref xcolor);
- XSendEvent(DisplayHandle, handle, false, EventMask.ExposureMask, ref xevent);
- XFlush(DisplayHandle);
+ lock (xlib_lock) {
+ XSetWindowBackground(DisplayHandle, handle, xcolor.pixel);
+ XClearWindow(DisplayHandle, handle);
+ }
}
[MonoTODO("Add support for internal table of windows/DCs for looking up paint area and cleanup")]
return paint_event;
}
- internal override void PaintEventEnd(IntPtr handle) {\r
+ internal override void PaintEventEnd(IntPtr handle) {
HandleData data = (HandleData) handle_data [handle];
if (data == null)
throw new Exception ("null data on PaintEventEnd");
data.ClearInvalidArea ();
- }\r
+ Graphics g = (Graphics) data.DeviceContext;
+ g.Flush ();
+ g.Dispose ();
+ }
internal override void SetWindowPos(IntPtr handle, int x, int y, int width, int height) {
// X requires a sanity check for width & height; otherwise it dies
if (height < 1) {
height = 1;
}
- XMoveResizeWindow(DisplayHandle, handle, x, y, width, height);
+ lock (xlib_lock) {
+ XMoveResizeWindow(DisplayHandle, handle, x, y, width, height);
+ }
return;
}
int border_width;
int depth;
- XGetGeometry(DisplayHandle, handle, out root, out x, out y, out width, out height, out border_width, out depth);
+ lock (xlib_lock) {
+
+ XGetGeometry(DisplayHandle, handle, out root, out x,
+ out y, out width, out height, out border_width, out depth);
+ }
client_width = width;
client_height = height;
}
internal override void Activate(IntPtr handle) {
- // Not sure this is the right method, but we don't use ICs either...
- XRaiseWindow(DisplayHandle, handle);
+
+ lock (xlib_lock) {
+ // Not sure this is the right method, but we don't use ICs either...
+ XRaiseWindow(DisplayHandle, handle);
+ }
return;
}
internal override void Invalidate(IntPtr handle, Rectangle rc, bool clear) {
- XEvent xevent = new XEvent();
-
- xevent.type=XEventName.Expose;
- xevent.ExposeEvent.display=DisplayHandle;
- xevent.ExposeEvent.window=handle;
- xevent.ExposeEvent.count=0;
-
- if (clear) {
- // Need to clear the whole window, so we force a redraw for the whole window
- XWindowAttributes attributes=new XWindowAttributes();
-
- // We need info about our window to generate the expose
- XGetWindowAttributes(DisplayHandle, handle, ref attributes);
-
- xevent.ExposeEvent.x=0;
- xevent.ExposeEvent.y=0;
- xevent.ExposeEvent.width=attributes.width;
- xevent.ExposeEvent.height=attributes.height;
- } else {
- xevent.ExposeEvent.x=rc.Left;
- xevent.ExposeEvent.y=rc.Top;
- xevent.ExposeEvent.width=rc.Width;
- xevent.ExposeEvent.height=rc.Height;
+ // FIXME - we're not properly interpreting the clear flag, we're assuming it's always true
+ lock (xlib_lock) {
+ XClearArea(DisplayHandle, handle, rc.Left, rc.Top, (uint)rc.Width, (uint)rc.Height, true);
}
-
- XSendEvent(DisplayHandle, handle, false, EventMask.ExposureMask, ref xevent);
- // Flush is not needed, invalidate does not guarantee an immediate effect
- //XFlush(DisplayHandle);
- return;
}
internal override IntPtr DefWndProc(ref Message msg) {
int len;
msg.wParam = IntPtr.Zero;
- len = XLookupString(ref xevent, buffer, 24, out keysym, IntPtr.Zero);
+ lock (xlib_lock) {
+ len = XLookupString(ref xevent, buffer, 24, out keysym, IntPtr.Zero);
+ }
if ((keysym==XKeySym.XK_Control_L) || (keysym==XKeySym.XK_Control_R)) {
if (xevent.type==XEventName.KeyPress) {
return (IntPtr)result;
}
+ private int NextTimeout (DateTime now)
+ {
+ int timeout = Int32.MaxValue;
+ lock (timer_list) {
+ foreach (Timer timer in timer_list) {
+ int next = (int) (timer.Expires - now).TotalMilliseconds;
+ if (next < 0)
+ return 0; // Have a timer that has already expired
+ if (next < timeout)
+ timeout = next;
+ }
+ }
+ if (timeout < Timer.Minimum)
+ timeout = Timer.Minimum;
+ return timeout;
+ }
+
+ private void CheckTimers (DateTime now)
+ {
+ lock (timer_list) {
+ int count = timer_list.Count;
+ if (count == 0)
+ return;
+ for (int i = 0; i < count; i++) {
+ Timer timer = (Timer) timer_list [i];
+ if (timer.Enabled && timer.Expires <= now) {
+ timer.FireTick ();
+ timer.Update (now);
+ }
+ }
+ }
+ }
+
+ private void UpdateMessageQueue ()
+ {
+ DateTime now = DateTime.Now;
+
+ int pending;
+ lock (xlib_lock) {
+ pending = XPending (DisplayHandle);
+ }
+ if (pending == 0) {
+ if (Idle != null) {
+ Idle (this, EventArgs.Empty);
+ }
+ lock (xlib_lock) {
+ pending = XPending (DisplayHandle);
+ }
+ }
+
+ if (pending == 0) {
+ int timeout = NextTimeout (now);
+ if (timeout > 0) {
+#if __MonoCS__
+ Syscall.poll (pollfds, pollfds.Length, timeout);
+#endif
+ pending = XPending (DisplayHandle);
+ }
+ }
+
+ CheckTimers (now);
+
+ if (pending == 0) {
+ lock (xlib_lock) {
+ pending = XPending (DisplayHandle);
+ }
+ }
+
+ while (pending > 0) {
+ XEvent xevent = new XEvent ();
+
+ lock (xlib_lock) {
+ XNextEvent (DisplayHandle, ref xevent);
+ }
+
+ switch (xevent.type) {
+ case XEventName.Expose:
+ HandleData data = (HandleData) handle_data [xevent.AnyEvent.window];
+ if (data == null) {
+ data = new HandleData ();
+ handle_data [xevent.AnyEvent.window] = data;
+ }
+
+ data.AddToInvalidArea (xevent.ExposeEvent.x, xevent.ExposeEvent.y,
+ xevent.ExposeEvent.width, xevent.ExposeEvent.height);
+
+ if (!data.HasExpose) {
+ lock (message_queue) {
+ message_queue.Enqueue (xevent);
+ }
+ data.HasExpose = true;
+ }
+ break;
+ case XEventName.KeyPress:
+ case XEventName.KeyRelease:
+ case XEventName.ButtonPress:
+ case XEventName.ButtonRelease:
+ case XEventName.MotionNotify:
+ case XEventName.EnterNotify:
+ case XEventName.LeaveNotify:
+ case XEventName.ConfigureNotify:
+ case XEventName.DestroyNotify:
+ case XEventName.ClientMessage:
+ lock (message_queue) {
+ message_queue.Enqueue (xevent);
+ }
+ break;
+ }
+
+ lock (xlib_lock) {
+ pending = XPending (DisplayHandle);
+ }
+ }
+ }
+
internal override bool GetMessage(ref MSG msg, IntPtr hWnd, int wFilterMin, int wFilterMax) {
- XEvent xevent = new XEvent();
+ XEvent xevent;
+
+ if (message_queue.Count > 0) {
+ xevent = (XEvent) message_queue.Dequeue ();
+ } else {
+ UpdateMessageQueue ();
+ if (message_queue.Count > 0) {
+ xevent = (XEvent) message_queue.Dequeue ();
+ } else {
+ msg.hwnd= IntPtr.Zero;
+ msg.message = Msg.WM_ENTERIDLE;
+ return true;
+ }
+ }
- begin:
- XNextEvent(DisplayHandle, ref xevent);
msg.hwnd=xevent.AnyEvent.window;
+ //
+ // If you add a new event to this switch make sure to add it in
+ // UpdateMessage also unless it is not coming through the X event system.
+ //
switch(xevent.type) {
case XEventName.KeyPress: {
msg.message = Msg.WM_KEYDOWN;
case XEventName.ButtonPress: {
switch(xevent.ButtonEvent.button) {
case 1: {
- mouse_state=MouseButtons.Left;
+ mouse_state |= MouseButtons.Left;
msg.message=Msg.WM_LBUTTONDOWN;
msg.wParam=GetMousewParam(0);
break;
}
case 2: {
- mouse_state=MouseButtons.Middle;
+ mouse_state |= MouseButtons.Middle;
msg.message=Msg.WM_MBUTTONDOWN;
msg.wParam=GetMousewParam(0);
break;
}
case 3: {
- mouse_state=MouseButtons.Right;
+ mouse_state |= MouseButtons.Right;
msg.message=Msg.WM_RBUTTONDOWN;
msg.wParam=GetMousewParam(0);
break;
case XEventName.ButtonRelease: {
switch(xevent.ButtonEvent.button) {
case 1: {
- mouse_state=MouseButtons.Left;
+ mouse_state &= ~MouseButtons.Left;
msg.message=Msg.WM_LBUTTONUP;
msg.wParam=GetMousewParam(0);
break;
}
case 2: {
- mouse_state=MouseButtons.Middle;
+ mouse_state &= ~MouseButtons.Middle;
msg.message=Msg.WM_MBUTTONUP;
msg.wParam=GetMousewParam(0);
break;
}
case 3: {
- mouse_state=MouseButtons.Right;
+ mouse_state &= ~MouseButtons.Right;
msg.message=Msg.WM_RBUTTONUP;
msg.wParam=GetMousewParam(0);
break;
}
case XEventName.EnterNotify: {
+ if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
+ return true;
+ }
msg.message=Msg.WM_MOUSE_ENTER;
break;
}
case XEventName.LeaveNotify: {
+ if (xevent.CrossingEvent.mode != NotifyMode.NotifyNormal) {
+ return true;
+ }
msg.message=Msg.WM_MOUSE_LEAVE;
break;
}
}
case XEventName.Expose: {
- HandleData data = (HandleData) handle_data [xevent.AnyEvent.window];
- if (data == null) {
- data = new HandleData ();
- handle_data [xevent.AnyEvent.window] = data;
- }
-
- data.AddToInvalidArea (xevent.ExposeEvent.x, xevent.ExposeEvent.y,
- xevent.ExposeEvent.width, xevent.ExposeEvent.height);
-
- // Only paint on the last of a series of expose events
- if (xevent.ExposeEvent.count > 0) {
- goto begin;
- }
-
- // Try combining expose events to reduce drawing
- while (XCheckWindowEvent (DisplayHandle, xevent.AnyEvent.window,
- EventMask.ExposureMask, ref xevent)) {
- data.AddToInvalidArea (xevent.ExposeEvent.x, xevent.ExposeEvent.y,
- xevent.ExposeEvent.width, xevent.ExposeEvent.height);
- }
-
msg.message=Msg.WM_PAINT;
+ msg.wParam=IntPtr.Zero;
+ msg.lParam=IntPtr.Zero;
break;
}
}
case XEventName.ClientMessage: {
- if (xevent.ClientMessageEvent.l0==wm_delete_window) {
+ if (xevent.ClientMessageEvent.message_type == async_method) {
+ GCHandle handle = (GCHandle)xevent.ClientMessageEvent.ptr1;
+ AsyncMethodData data = (AsyncMethodData) handle.Target;
+ AsyncMethodResult result = data.Result.Target as AsyncMethodResult;
+ object ret = data.Method.DynamicInvoke (data.Args);
+ if (result != null)
+ result.Complete (ret);
+ handle.Free ();
+ } else {
msg.message=Msg.WM_QUIT;
msg.wParam=IntPtr.Zero;
msg.lParam=IntPtr.Zero;
return false;
}
- return true;
- break;
- }
- default: {
- msg.message = Msg.WM_NULL;
break;
}
+
+ case XEventName.TimerNotify: {
+ xevent.TimerNotifyEvent.handler (this, EventArgs.Empty);
+ break;
+ }
+
+ default: {
+ msg.message = Msg.WM_NULL;
+ break;
+ }
}
NativeWindow.WndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
return true;
}
+ internal override bool SetZOrder(IntPtr hWnd, IntPtr AfterhWnd, bool Top, bool Bottom) {
+ if (Top) {
+ XRaiseWindow(DisplayHandle, hWnd);
+ return true;
+ } else if (!Bottom) {
+ XWindowChanges values = new XWindowChanges();
+
+ values.sibling = AfterhWnd;
+ values.stack_mode = StackMode.Below;
+ XConfigureWindow(DisplayHandle, hWnd, ChangeWindowFlags.CWStackMode, ref values);
+ } else {
+ XLowerWindow(DisplayHandle, hWnd);
+ return true;
+ }
+ return false;
+ }
+
+
internal override bool Text(IntPtr handle, string text) {
#if notdef
XTextProperty property = new XTextProperty();
property.encoding=
XSetWMName(DisplayHandle, handle, ref property);
#else
- XStoreName(DisplayHandle, handle, text);
+ lock (xlib_lock) {
+ XStoreName(DisplayHandle, handle, text);
+ }
#endif
return true;
}
- internal override bool SetVisible(IntPtr handle, bool visible) {
- if (visible) {
- XMapWindow(DisplayHandle, handle);
- is_visible=true;
+ internal override bool GetText(IntPtr handle, out string text) {
+ IntPtr textptr;
+
+ textptr = IntPtr.Zero;
+
+ lock (xlib_lock) {
+ XFetchName(DisplayHandle, handle, ref textptr);
+ }
+ if (textptr != IntPtr.Zero) {
+ text = Marshal.PtrToStringAnsi(textptr);
+ XFree(textptr);
+ return true;
} else {
- XUnmapWindow(DisplayHandle, handle);
- is_visible=false;
+ text = "";
+ return false;
+ }
+ }
+
+ internal override bool SetVisible(IntPtr handle, bool visible) {
+ lock (xlib_lock) {
+ if (visible) {
+ XMapWindow(DisplayHandle, handle);
+ is_visible=true;
+ } else {
+ XUnmapWindow(DisplayHandle, handle);
+ is_visible=false;
+ }
}
return true;
}
internal override IntPtr SetParent(IntPtr handle, IntPtr parent) {
XWindowAttributes attributes=new XWindowAttributes();
- XGetWindowAttributes(DisplayHandle, handle, ref attributes);
- XReparentWindow(DisplayHandle, handle, parent, attributes.x, attributes.y);
+ lock (xlib_lock) {
+ XGetWindowAttributes(DisplayHandle, handle, ref attributes);
+ XReparentWindow(DisplayHandle, handle, parent, attributes.x, attributes.y);
+ }
return IntPtr.Zero;
}
Children=IntPtr.Zero;
ChildCount=0;
- XQueryTree(DisplayHandle, handle, ref Root, ref Parent, ref Children, ref ChildCount);
+ lock (xlib_lock) {
+ XQueryTree(DisplayHandle, handle, ref Root, ref Parent, ref Children, ref ChildCount);
+ }
if (Children!=IntPtr.Zero) {
- XFree(Children);
+ lock (xlib_lock) {
+ XFree(Children);
+ }
}
return Parent;
}
-\r
- internal override void GrabWindow(IntPtr hWnd) {
- XGrabPointer(DisplayHandle, hWnd, false, EventMask.ButtonPressMask | EventMask.ButtonMotionMask | EventMask.ButtonReleaseMask | EventMask.PointerMotionMask, GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, IntPtr.Zero, 0, 0);
+
+ internal override void GrabWindow(IntPtr hWnd, IntPtr confine_hwnd) {
+ if (confine_hwnd != IntPtr.Zero) {
+ XWindowAttributes attributes = new XWindowAttributes();
+
+ lock (xlib_lock) {
+ XGetWindowAttributes(DisplayHandle, confine_hwnd, ref attributes);
+ }
+ grab_area.X = attributes.x;
+ grab_area.Y = attributes.y;
+ grab_area.Width = attributes.width;
+ grab_area.Height = attributes.height;
+ grab_confined = true;
+ }
+ grab_hwnd = hWnd;
+ lock (xlib_lock) {
+ XGrabPointer(DisplayHandle, hWnd, false,
+ EventMask.ButtonPressMask | EventMask.ButtonMotionMask |
+ EventMask.ButtonReleaseMask | EventMask.PointerMotionMask,
+ GrabMode.GrabModeAsync, GrabMode.GrabModeAsync, confine_hwnd, 0, 0);
+ }
+ }
+
+ internal override void GrabInfo(out IntPtr hWnd, out bool GrabConfined, out Rectangle GrabArea) {
+ hWnd = grab_hwnd;
+ GrabConfined = grab_confined;
+ GrabArea = grab_area;
}
internal override void ReleaseWindow(IntPtr hWnd) {
- XUngrabPointer(DisplayHandle, 0);
+ lock (xlib_lock) {
+ XUngrabPointer(DisplayHandle, 0);
+ grab_hwnd = IntPtr.Zero;
+ grab_confined = false;
+ }
}
internal override bool CalculateWindowRect(IntPtr hWnd, ref Rectangle ClientRect, int Style, bool HasMenu, out Rectangle WindowRect) {
return true;
}
+ internal override void SetCursorPos(IntPtr handle, int x, int y) {
+ lock (xlib_lock) {
+ XWarpPointer(DisplayHandle, IntPtr.Zero, (handle!=IntPtr.Zero) ? handle : IntPtr.Zero, 0, 0, 0, 0, x, y);
+ }
+ }
+
internal override void GetCursorPos(IntPtr handle, out int x, out int y) {
IntPtr root;
IntPtr child;
int win_y;
int keys_buttons;
- XQueryPointer(DisplayHandle, (handle!=IntPtr.Zero) ? handle : root_window, out root, out child, out root_x, out root_y, out win_x, out win_y, out keys_buttons);
+ lock (xlib_lock) {
+ XQueryPointer(DisplayHandle, (handle!=IntPtr.Zero) ? handle : root_window,
+ out root, out child, out root_x, out root_y,
+ out win_x, out win_y, out keys_buttons);
+ }
+
if (handle != IntPtr.Zero) {
x = win_x;
y = win_y;
int dest_y_return;
IntPtr child;
- XTranslateCoordinates (DisplayHandle, root_window, handle, x, y, out dest_x_return, out dest_y_return, out child);
+ lock (xlib_lock) {
+ XTranslateCoordinates (DisplayHandle, root_window,
+ handle, x, y, out dest_x_return, out dest_y_return, out child);
+ }
x = dest_x_return;
y = dest_y_return;
}
+ internal override void ClientToScreen(IntPtr handle, ref int x, ref int y) {
+ int dest_x_return;
+ int dest_y_return;
+ IntPtr child;
+
+ lock (xlib_lock) {
+ XTranslateCoordinates (DisplayHandle, handle, root_window,
+ x, y, out dest_x_return, out dest_y_return, out child);
+ }
+
+ x = dest_x_return;
+ y = dest_y_return;
+ }
+
+ internal override void SendAsyncMethod (AsyncMethodData method)
+ {
+ XEvent xevent = new XEvent ();
+
+ xevent.type = XEventName.ClientMessage;
+ xevent.ClientMessageEvent.display = DisplayHandle;
+ xevent.ClientMessageEvent.window = IntPtr.Zero;
+ xevent.ClientMessageEvent.message_type = async_method;
+ xevent.ClientMessageEvent.format = 32;
+ xevent.ClientMessageEvent.ptr1 = (IntPtr) GCHandle.Alloc (method);
+
+ lock (message_queue) {
+ message_queue.Enqueue (xevent);
+ }
+
+ WakeupMain ();
+ }
+
+ private void WakeupMain ()
+ {
+ wake.BeginSend (new byte [] { 0xFF }, 0, 1, SocketFlags.None, null, null);
+ }
+
+ internal override void SetTimer (Timer timer)
+ {
+ lock (timer_list) {
+ timer_list.Add (timer);
+ }
+ WakeupMain ();
+ }
+
+ internal override void KillTimer (Timer timer)
+ {
+ lock (timer_list) {
+ timer_list.Remove (timer);
+ }
+ }
+
// Santa's little helper
- static void Where() \r
+ static void Where()
{
Console.WriteLine("Here: {0}", new StackTrace().ToString());
}
[DllImport ("libX11.so", EntryPoint="XNextEvent")]
internal extern static IntPtr XNextEvent(IntPtr display, ref XEvent xevent);
[DllImport ("libX11.so")]
+ internal extern static int XConnectionNumber (IntPtr diplay);
+ [DllImport ("libX11.so")]
+ internal extern static int XPending (IntPtr diplay);
+ [DllImport ("libX11.so")]
internal extern static bool XCheckWindowEvent (IntPtr display, IntPtr window, EventMask mask, ref XEvent xevent);
+ [DllImport ("libX11.so")]
+ internal extern static bool XCheckMaskEvent (IntPtr display, EventMask mask, ref XEvent xevent);
[DllImport ("libX11.so", EntryPoint="XSelectInput")]
internal extern static IntPtr XSelectInput(IntPtr display, IntPtr window, EventMask mask);
[DllImport ("libX11.so", EntryPoint="XLookupString")]
[DllImport ("libX11.so", EntryPoint="XStoreName")]
internal extern static int XStoreName(IntPtr display, IntPtr window, string window_name);
+ [DllImport ("libX11.so", EntryPoint="XFetchName")]
+ internal extern static int XFetchName(IntPtr display, IntPtr window, ref IntPtr window_name);
+
[DllImport ("libX11.so", EntryPoint="XSendEvent")]
internal extern static int XSendEvent(IntPtr display, IntPtr window, bool propagate, EventMask event_mask, ref XEvent send_event);
[DllImport ("libX11.so", EntryPoint="XRaiseWindow")]
internal extern static int XRaiseWindow(IntPtr display, IntPtr window);
+ [DllImport ("libX11.so", EntryPoint="XLowerWindow")]
+ internal extern static uint XLowerWindow(IntPtr display, IntPtr window);
+
+ [DllImport ("libX11.so", EntryPoint="XConfigureWindow")]
+ internal extern static uint XConfigureWindow(IntPtr display, IntPtr window, ChangeWindowFlags value_mask, ref XWindowChanges values);
+
[DllImport ("libX11.so", EntryPoint="XInternAtom")]
internal extern static int XInternAtom(IntPtr display, string atom_name, bool only_if_exists);
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);
[DllImport ("libX11.so", EntryPoint="XTranslateCoordinates")]
- 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);
+ 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);
[DllImport ("libX11.so", EntryPoint="XGetGeometry")]
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);
- [DllImport ("libX11.so", EntryPoint="XAllocColor")]
- internal extern static int XAllocColor(IntPtr display, uint Colormap, ref XColor colorcell_def);
+ [DllImport ("libX11.so", EntryPoint="XWarpPointer")]
+ 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);
- [DllImport ("libX11.so", EntryPoint="XGetStandardColormap")]
- internal extern static int XGetStandardColormap(IntPtr display, IntPtr window, ref XStandardColormap cmap_info, Atom property);
+ [DllImport ("libX11.so", EntryPoint="XClearWindow")]
+ internal extern static int XClearWindow(IntPtr display, IntPtr window);
- [DllImport ("libX11.so", EntryPoint="XSetRGBColormaps")]
- internal extern static int XSetRGBColormaps(IntPtr display, IntPtr window, ref XStandardColormap cmap_info, int count, Atom property);
+ [DllImport ("libX11.so", EntryPoint="XClearArea")]
+ internal extern static int XClearArea(IntPtr display, IntPtr window, int x, int y, uint width, uint height, bool exposures);
- [DllImport ("libX11.so", EntryPoint="XInstallColormap")]
- internal extern static int XInstallColormap(IntPtr display, uint cmap);
+ // Colormaps
+ [DllImport ("libX11.so", EntryPoint="XDefaultScreenOfDisplay")]
+ internal extern static IntPtr XDefaultScreenOfDisplay(IntPtr display);
- [DllImport ("libX11.so", EntryPoint="XDefaultColormap")]
- internal extern static uint XDefaultColormap(IntPtr display, int screen_number);
+ [DllImport ("libX11.so", EntryPoint="XScreenNumberOfScreen")]
+ internal extern static int XScreenNumberOfScreen(IntPtr display, IntPtr Screen);
+
+ [DllImport ("libX11.so", EntryPoint="XDefaultVisual")]
+ internal extern static uint XDefaultVisual(IntPtr display, int screen_number);
[DllImport ("libX11.so", EntryPoint="XDefaultDepth")]
internal extern static uint XDefaultDepth(IntPtr display, int screen_number);
- [DllImport ("libX11.so", EntryPoint="XDefaultVisual")]
- internal extern static uint XDefaultVisual(IntPtr display, int screen_number);
+ [DllImport ("libX11.so", EntryPoint="XDefaultColormap")]
+ internal extern static uint XDefaultColormap(IntPtr display, int screen_number);
+
+ [DllImport ("libX11.so", EntryPoint="XLookupColor")]
+ internal extern static int XLookupColor(IntPtr display, uint Colormap, string Coloranem, ref XColor exact_def_color, ref XColor screen_def_color);
+
+ [DllImport ("libX11.so", EntryPoint="XAllocColor")]
+ internal extern static int XAllocColor(IntPtr display, uint Colormap, ref XColor colorcell_def);
- [DllImport ("libX11.so", EntryPoint="XSetWindowColormap")]
- internal extern static uint XSetWindowColormap(IntPtr display, IntPtr window, uint cmap);
// Drawing
[DllImport ("libX11.so", EntryPoint="XCreateGC")]