- Added NativeWindow.FindWindow() method to have a method to check for existence
authorPeter Dennis Bartok <pbartok@mono-cvs.ximian.com>
Mon, 20 Dec 2004 11:06:09 +0000 (11:06 -0000)
committerPeter Dennis Bartok <pbartok@mono-cvs.ximian.com>
Mon, 20 Dec 2004 11:06:09 +0000 (11:06 -0000)
  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

mcs/class/Managed.Windows.Forms/System.Windows.Forms/NativeWindow.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs

index 38a7bd38f0b7711d23d6964989522e2cfa00de09..075a9373cbbec0983f461b8e72944ed4b1eff3cd 100644 (file)
@@ -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;
                }
index 42c46fce1f467dabf9a6cc95e3e834f64a8a30cb..238eab7879fdda646d0b7b163aa9c121da3f66ee 100644 (file)
@@ -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;\r
                }
 
                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();\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;
                }
@@ -694,18 +718,19 @@ namespace System.Windows.Forms {
                }
 
                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) {
@@ -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);
+\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
        }
 }