From ec4d30681a1a90808c7713cb33183e17132cd3bc Mon Sep 17 00:00:00 2001 From: Peter Dennis Bartok Date: Mon, 20 Dec 2004 11:06:09 +0000 Subject: [PATCH] - Added NativeWindow.FindWindow() method to have a method to check for existence of a window handle - Removed r37929 (SetModal patch from Ashwin Bharambe), was not working - Implemented modal_window stack and checking for _WM_ACTIVE_WINDOW property to allow switching back to the modal window if focus is given to another one of our windows (Application Modal) - Now only sets override_redirect if we create a window without WS_CAPTION - Moved EventMask selection before mapping of newly created window so we can catch the map event as well - Implemented Activate() method via the _WM_ACTIVE_WINDOW property - Added various Atom related DllImports - Implemented Exit() method - .ctor() : No longer shows window if WS_VISIBLE is not defined in CreateParams svn path=/trunk/mcs/; revision=37959 --- .../System.Windows.Forms/NativeWindow.cs | 23 +++- .../System.Windows.Forms/XplatUIX11.cs | 103 ++++++++++++++---- 2 files changed, 96 insertions(+), 30 deletions(-) diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/NativeWindow.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/NativeWindow.cs index 38a7bd38f0b..075a9373cbb 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/NativeWindow.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/NativeWindow.cs @@ -26,6 +26,8 @@ // COMPLETE +#undef ExternalExceptionHandler + using System.Runtime.Remoting; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; @@ -61,6 +63,13 @@ namespace System.Windows.Forms } #endregion // Public Static Methods + #region Private and Internal Static Methods + internal static NativeWindow FindWindow(IntPtr handle) { + return (NativeWindow)window_collection[handle]; + + } + #endregion + #region Public Instance Methods public void AssignHandle(IntPtr handle) { if (window_handle != IntPtr.Zero) { @@ -113,16 +122,16 @@ namespace System.Windows.Forms } protected virtual void WndProc(ref Message m) { -#if debug - Console.WriteLine("NativeWindow.cs: WndProc(ref Message m) called"); -#endif DefWndProc(ref m); } internal static IntPtr WndProc(IntPtr hWnd, Msg msg, IntPtr wParam, IntPtr lParam) { Message m = new Message(); NativeWindow window = null; + + #if !ExternalExceptionHandler try { + #endif window = (NativeWindow)window_collection[hWnd]; m.HWnd=hWnd; m.Msg=(int)msg; @@ -135,6 +144,7 @@ namespace System.Windows.Forms } else { m.Result=XplatUI.DefWndProc(ref m); } + #if !ExternalExceptionHandler } catch(System.Exception ex) { @@ -142,10 +152,11 @@ namespace System.Windows.Forms window.OnThreadException(ex); } } + #endif -#if debug - Console.WriteLine("NativeWindow.cs: Message {0}, result {1}", msg, m.Result); -#endif + #if debug + Console.WriteLine("NativeWindow.cs: Message {0}, result {1}", msg, m.Result); + #endif return m.Result; } diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs index 42c46fce1f4..238eab7879f 100644 --- a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs @@ -85,8 +85,9 @@ namespace System.Windows.Forms { 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; @@ -100,7 +101,9 @@ namespace System.Windows.Forms { 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 @@ -198,6 +201,8 @@ namespace System.Windows.Forms { // Handle singleton stuff first ref_count=0; + getmessage_ret = true; + message_queue = new XEventQueue (); timer_list = new ArrayList (); @@ -224,6 +229,8 @@ namespace System.Windows.Forms { hover.x = -1; hover.y = -1; + modal_window = new Stack(3); + #if __MonoCS__ pollfds = new Pollfd [2]; pollfds [0] = new Pollfd (); @@ -361,6 +368,7 @@ namespace System.Windows.Forms { 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); @@ -388,7 +396,7 @@ namespace System.Windows.Forms { } internal override void Exit() { - Console.WriteLine("XplatUIX11.Exit"); + getmessage_ret = false; } internal override void GetDisplaySize(out Size size) { @@ -463,6 +471,12 @@ namespace System.Windows.Forms { 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 @@ -528,10 +542,12 @@ namespace System.Windows.Forms { } 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); } @@ -683,8 +699,16 @@ namespace System.Windows.Forms { 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(); + + xev.ClientMessageEvent.type = XEventName.ClientMessage; + xev.ClientMessageEvent.send_event = true; + xev.ClientMessageEvent.window = handle; + xev.ClientMessageEvent.message_type = (IntPtr) net_active_window; + xev.ClientMessageEvent.format = 32; + XSendEvent(DisplayHandle, root_window, false, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xev); + + //XRaiseWindow(DisplayHandle, handle); } return; } @@ -694,18 +718,19 @@ namespace System.Windows.Forms { } internal override void SetModal(IntPtr handle, bool Modal) { - XEvent xevent = new XEvent(); - - xevent.ClientMessageEvent.type = XEventName.ClientMessage; - xevent.ClientMessageEvent.serial = 0; - xevent.ClientMessageEvent.send_event = true; - xevent.ClientMessageEvent.window = handle; - xevent.ClientMessageEvent.message_type = (IntPtr) net_wm_state; - xevent.ClientMessageEvent.format = 32; - xevent.ClientMessageEvent.ptr1 = (IntPtr) (Modal ? NetWindowManagerState.Add : NetWindowManagerState.Remove); - xevent.ClientMessageEvent.ptr2 = (IntPtr) wm_state_modal; - - XSendEvent(DisplayHandle, root_window, false, EventMask.SubstructureRedirectMask | EventMask.SubstructureNotifyMask, ref xevent); + if (Modal) { + modal_window.Push(handle); + XSelectInput(DisplayHandle, root_window, EventMask.PropertyChangeMask); + } else { + if (modal_window.Contains(handle)) { + modal_window.Pop(); + } + if (modal_window.Count > 0) { + Activate((IntPtr)modal_window.Peek()); + } else { + XSelectInput(DisplayHandle, root_window, EventMask.NoEventMask); + } + } } internal override void Invalidate (IntPtr handle, Rectangle rc, bool clear) { @@ -900,6 +925,32 @@ namespace System.Windows.Forms { 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) { @@ -1151,11 +1202,6 @@ namespace System.Windows.Forms { 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; } @@ -1171,7 +1217,7 @@ namespace System.Windows.Forms { } } - return true; + return getmessage_ret; } internal override bool TranslateMessage(ref MSG msg) { @@ -1753,6 +1799,9 @@ namespace System.Windows.Forms { [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); @@ -1783,6 +1832,12 @@ namespace System.Windows.Forms { [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); + + [DllImport ("libX11", EntryPoint="XGetAtomName")] + internal extern static string XGetAtomName(IntPtr display, int atom); + + [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 } } -- 2.25.1