private static int atom; // X Atom
private static int wm_state_modal; // X Atom
private static int net_wm_state; // X Atom
+ private static int net_active_window; // X Atom
private static int async_method;
- private static int post_message;
+ private static int post_message; // X Atom send to generate a PostMessage event
private static uint default_colormap; // X Colormap ID
internal static MouseButtons mouse_state;
internal static Point mouse_position;
internal static int click_pending_time; // Last time we received a mouse click
internal static bool click_pending; // True if we haven't sent the last mouse click
internal static int double_click_interval; // in milliseconds, how fast one has to click for a double click
+ internal static Stack modal_window; // Stack of modal window handles
internal static Hover hover;
+ internal static bool getmessage_ret; // Return value for GetMessage function; 0 to terminate app
internal static Caret caret; // To display a blinking caret
// Handle singleton stuff first
ref_count=0;
+ getmessage_ret = true;
+
message_queue = new XEventQueue ();
timer_list = new ArrayList ();
hover.x = -1;
hover.y = -1;
+ modal_window = new Stack(3);
+
#if __MonoCS__
pollfds = new Pollfd [2];
pollfds [0] = new Pollfd ();
wm_no_taskbar=XInternAtom(display_handle, "_NET_WM_STATE_NO_TASKBAR", false);
wm_state_above=XInternAtom(display_handle, "_NET_WM_STATE_ABOVE", false);
wm_state_modal = XInternAtom(display_handle, "_NET_WM_STATE_MODAL", false);
+ net_active_window = XInternAtom(display_handle, "_NET_ACTIVE_WINDOW", false);
atom=XInternAtom(display_handle, "ATOM", false);
async_method = XInternAtom(display_handle, "_SWF_AsyncAtom", false);
}
internal override void Exit() {
- Console.WriteLine("XplatUIX11.Exit");
+ getmessage_ret = false;\r
}
internal override void GetDisplaySize(out Size size) {
attr.bit_gravity = Gravity.NorthWestGravity;
attr.win_gravity = Gravity.NorthWestGravity;
+ if (attr.override_redirect) {
+ if ((cp.Style & ((int)WindowStyles.WS_CAPTION)) != 0) {
+ attr.override_redirect = false;
+ }
+ }
+
WindowHandle=XCreateWindow(DisplayHandle, ParentHandle, X, Y, Width, Height, BorderWidth, (int)CreateWindowArgs.CopyFromParent, (int)CreateWindowArgs.InputOutput, IntPtr.Zero, SetWindowValuemask.BitGravity | SetWindowValuemask.WinGravity | SetWindowValuemask.SaveUnder | SetWindowValuemask.OverrideRedirect, ref attr);
// Set the appropriate window manager hints
}
XChangeProperty(DisplayHandle, WindowHandle, net_wm_state, atom, 32, PropertyMode.Replace, ref atoms, atom_count);
- XMapWindow(DisplayHandle, WindowHandle);
-
XSelectInput(DisplayHandle, WindowHandle, SelectInputMask);
+ if ((cp.Style & ((int)WindowStyles.WS_VISIBLE)) != 0) {
+ XMapWindow(DisplayHandle, WindowHandle);
+ }
+
protocols=wm_delete_window;
XSetWMProtocols(DisplayHandle, WindowHandle, ref protocols, 1);
}
internal override void Activate(IntPtr handle) {
lock (xlib_lock) {
- // Not sure this is the right method, but we don't use ICs either...
- XRaiseWindow(DisplayHandle, handle);
+ XEvent xev = new XEvent();\r
+\r
+ xev.ClientMessageEvent.type = XEventName.ClientMessage;\r
+ xev.ClientMessageEvent.send_event = true;\r
+ xev.ClientMessageEvent.window = handle;\r
+ xev.ClientMessageEvent.message_type = (IntPtr) net_active_window;\r
+ xev.ClientMessageEvent.format = 32;\r
+ XSendEvent(DisplayHandle, root_window, false, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xev);\r
+
+ //XRaiseWindow(DisplayHandle, handle);
}
return;
}
}
internal override void SetModal(IntPtr handle, bool Modal) {
- XEvent xevent = new XEvent();\r
-\r
- xevent.ClientMessageEvent.type = XEventName.ClientMessage;\r
- xevent.ClientMessageEvent.serial = 0;\r
- xevent.ClientMessageEvent.send_event = true;\r
- xevent.ClientMessageEvent.window = handle;\r
- xevent.ClientMessageEvent.message_type = (IntPtr) net_wm_state;\r
- xevent.ClientMessageEvent.format = 32;\r
- xevent.ClientMessageEvent.ptr1 = (IntPtr) (Modal ? NetWindowManagerState.Add : NetWindowManagerState.Remove);\r
- xevent.ClientMessageEvent.ptr2 = (IntPtr) wm_state_modal;\r
-\r
- XSendEvent(DisplayHandle, root_window, false, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xevent);\r
+ if (Modal) {\r
+ modal_window.Push(handle);\r
+ XSelectInput(DisplayHandle, root_window, EventMask.PropertyChangeMask);
+ } else {\r
+ if (modal_window.Contains(handle)) {\r
+ modal_window.Pop();\r
+ }\r
+ if (modal_window.Count > 0) {
+ Activate((IntPtr)modal_window.Peek());
+ } else {
+ XSelectInput(DisplayHandle, root_window, EventMask.NoEventMask);
+ }
+ }\r
}
internal override void Invalidate (IntPtr handle, Rectangle rc, bool clear) {
case XEventName.ClientMessage:
message_queue.Enqueue (xevent);
break;
+
+ case XEventName.PropertyNotify:
+ if (xevent.PropertyEvent.atom == (IntPtr)net_active_window) {
+ if (modal_window.Count > 0) {
+ Atom actual_atom;
+ int actual_format;
+ int nitems;
+ int bytes_after;
+ IntPtr prop = IntPtr.Zero;
+ IntPtr active_window = (IntPtr)modal_window.Peek(); // if GetWindowProperty fails this prevents the reset trigger below
+
+ XGetWindowProperty(DisplayHandle, root_window, net_active_window, 0, 1, false, Atom.XA_WINDOW, out actual_atom, out actual_format, out nitems, out bytes_after, ref prop);
+ if ((nitems > 0) && (prop != IntPtr.Zero)) {
+ active_window = (IntPtr)Marshal.ReadInt32(prop);
+ XFree(prop);
+ }
+
+ if (active_window != (IntPtr)modal_window.Peek()) {
+ if (NativeWindow.FindWindow(active_window) != null) {
+ Activate((IntPtr)modal_window.Peek());
+ }
+ }
+ }
+ }
+ break;
+
}
lock (xlib_lock) {
msg.hwnd = xevent.ClientMessageEvent.window;
msg.wParam = xevent.ClientMessageEvent.ptr2;
msg.lParam = xevent.ClientMessageEvent.ptr3;
- } else {
- msg.message=Msg.WM_QUIT;
- msg.wParam=IntPtr.Zero;
- msg.lParam=IntPtr.Zero;
- return false;
}
break;
}
}
}
- return true;
+ return getmessage_ret;
}
internal override bool TranslateMessage(ref MSG msg) {
[DllImport ("libX11", EntryPoint="XChangeProperty")]
internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int type, int format, PropertyMode mode, ref MotifWmHints data, int nelements);
+ [DllImport ("libX11", EntryPoint="XChangeProperty")]
+ internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, Atom format, int type, PropertyMode mode, ref uint[] atoms, int nelements);
+
[DllImport ("libX11", EntryPoint="XChangeProperty")]
internal extern static int XChangeProperty(IntPtr display, IntPtr window, int property, int format, int type, PropertyMode mode, ref uint[] atoms, int nelements);
[DllImport ("libX11", EntryPoint="XCopyArea")]
internal extern static int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int src_x, int src_y, int width, int height, int dest_x, int dest_y);
+\r
+ [DllImport ("libX11", EntryPoint="XGetAtomName")]
+ internal extern static string XGetAtomName(IntPtr display, int atom);
+\r
+ [DllImport ("libX11", EntryPoint="XGetWindowProperty")]
+ internal extern static int XGetWindowProperty(IntPtr display, IntPtr window, int atom, int long_offset, int long_length, bool delete, Atom req_type, out Atom actual_type, out int actual_format, out int nitems, out int bytes_after, ref IntPtr prop);
#endregion\r
}
}