2006-03-07 Peter Dennis Bartok <pbartok@novell.com>
authorPeter Dennis Bartok <pbartok@mono-cvs.ximian.com>
Tue, 7 Mar 2006 21:21:26 +0000 (21:21 -0000)
committerPeter Dennis Bartok <pbartok@mono-cvs.ximian.com>
Tue, 7 Mar 2006 21:21:26 +0000 (21:21 -0000)
* Control.cs:
  - Added new IsRecreating and ParentIsRecreating properties to
    allow testing if RecreateHandle has been called on ourselves
    or one of our parents
  - WndProc(WM_DESTROY): If our control handle is being recreated
    we immediately need to create the handle when receiving the
    destroy, that way our child windows find a valid parent handle
    when they themselves are being recreated upon WM_DESTROY receipt
    (fix for bug #77654 part 1)
* XplatUIX11.cs:
  - DestroyWindow: WM_DESTROY must be sent to our own window before
    notifying any child windows. MS documents that child windows
    are still valid when WM_DESTROY is received. (Control now relies on
    this behaviour)
  - Added some fine-grain debug options

svn path=/trunk/mcs/; revision=57665

mcs/class/Managed.Windows.Forms/System.Windows.Forms/ChangeLog
mcs/class/Managed.Windows.Forms/System.Windows.Forms/Control.cs
mcs/class/Managed.Windows.Forms/System.Windows.Forms/XplatUIX11.cs

index 0c8a7650a0a2e157e5aab7c91309758f63839153..c69827a50c2fcbcc6dc654385aefba070c4f642b 100644 (file)
@@ -1,3 +1,21 @@
+2006-03-07  Peter Dennis Bartok  <pbartok@novell.com>
+
+       * Control.cs: 
+         - Added new IsRecreating and ParentIsRecreating properties to
+           allow testing if RecreateHandle has been called on ourselves
+           or one of our parents
+         - WndProc(WM_DESTROY): If our control handle is being recreated
+           we immediately need to create the handle when receiving the
+           destroy, that way our child windows find a valid parent handle
+           when they themselves are being recreated upon WM_DESTROY receipt
+           (fix for bug #77654 part 1)
+       * XplatUIX11.cs:
+         - DestroyWindow: WM_DESTROY must be sent to our own window before
+           notifying any child windows. MS documents that child windows
+           are still valid when WM_DESTROY is received. (Control now relies on
+           this behaviour)
+         - Added some fine-grain debug options
+
 2006-03-06  Jackson Harper  <jackson@ximian.com>
 
        * MdiClient.cs: Redid scrolling logic a bit to create a virtual
index 4b841d02f33284f9ea419b107555a61804e8be60..6db2f7cc05ce4fc72fa7f128fa47e63523da521c 100644 (file)
@@ -842,6 +842,29 @@ namespace System.Windows.Forms
                        XplatUI.ClientToScreen (Handle, ref x, ref y);
                }
 
+               private bool IsRecreating {
+                       get {
+                               if (is_recreating) {
+                                       return true;
+                               }
+
+                               if (parent != null) {
+                                       return parent.IsRecreating;
+                               }
+
+                               return false;
+                       }
+               }
+
+               private bool ParentIsRecreating {
+                       get {
+                               if (parent != null) {
+                                       return parent.IsRecreating;
+                               }
+                               return false;
+                       }
+               }
+
                internal Graphics DeviceContext {
                        get { 
                                if (dc_mem==null) {
@@ -3275,7 +3298,7 @@ namespace System.Windows.Forms
 
                        if (IsHandleCreated) {
                                DestroyHandle();
-                               CreateHandle();
+                               // WM_DESTROY will CreateHandle for us
                        } else {
                                if (!is_created) {
                                        CreateControl();
@@ -3657,6 +3680,12 @@ namespace System.Windows.Forms
                                case Msg.WM_DESTROY: {
                                        OnHandleDestroyed(EventArgs.Empty);
                                        window.InvalidateHandle();
+
+                                       if (ParentIsRecreating) {
+                                               RecreateHandle();
+                                       } else if (is_recreating) {
+                                               CreateHandle();
+                                       }
                                        return;
                                }
 
@@ -3670,7 +3699,7 @@ namespace System.Windows.Forms
                                        return;
                                }
 
-                               case Msg.WM_PAINT: {                            
+                               case Msg.WM_PAINT: {
                                        PaintEventArgs  paint_event;
 
                                        paint_event = XplatUI.PaintEventStart(Handle, true);
index 149841ccbf7796d189654a44dca649cb05037a02..5e2bca6fe28473de45d08aee512a8507d35b27f6 100644 (file)
@@ -41,6 +41,9 @@
 
 // Extra detailed debug
 #undef DriverDebugExtra
+#define DriverDebugParent
+#define DriverDebugCreate
+#define DriverDebugDestroy
 
 using System;
 using System.ComponentModel;
@@ -1340,6 +1343,9 @@ namespace System.Windows.Forms {
                                for (i = 0; i < controls.Length; i++) {
                                        if (controls[i].IsHandleCreated) {
                                                hwnd = Hwnd.ObjectFromHandle(controls[i].Handle);
+                                               #if DriverDebugDestroy
+                                                       Console.WriteLine("Destroying {0} [Child of {1}]", XplatUI.Window(controls[i].Handle), XplatUI.Window(controls[i].parent.Handle));
+                                               #endif
                                                SendMessage(controls[i].Handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
                                                hwnd.Dispose();
                                        }
@@ -1967,7 +1973,7 @@ namespace System.Windows.Forms {
                        hwnd.WholeWindow = WholeWindow;
                        hwnd.ClientWindow = ClientWindow;
 
-                       #if DriverDebug
+                       #if DriverDebug || DriverDebugCreate
                                Console.WriteLine("Created window {0:X} / {1:X} parent {2:X}", ClientWindow.ToInt32(), WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0);
                        #endif
                                       
@@ -2366,12 +2372,12 @@ namespace System.Windows.Forms {
                                DestroyCaret(handle);
                        }
 
-                       // Mark our children as gone as well
-                       DestroyChildWindow(Control.ControlNativeWindow.ControlFromHandle(handle));
-
                        // Send destroy message
                        SendMessage(handle, Msg.WM_DESTROY, IntPtr.Zero, IntPtr.Zero);
 
+                       // Mark our children as gone as well
+                       DestroyChildWindow(Control.ControlNativeWindow.ControlFromHandle(handle));
+
                        lock (XlibLock) {
                                if (hwnd.client_window != IntPtr.Zero) {
                                        XDestroyWindow(DisplayHandle, hwnd.client_window);
@@ -3744,8 +3750,8 @@ namespace System.Windows.Forms {
                        hwnd.parent = Hwnd.ObjectFromHandle(parent);
 
                        lock (XlibLock) {
-                               #if DriverDebug
-                                       Console.WriteLine("Parent for window {0:X} / {1:X} = {2:X} (Handle:{3:X})", hwnd.ClientWindow.ToInt32(), hwnd.WholeWindow.ToInt32(), hwnd.parent != null ? hwnd.parent.Handle.ToInt32() : 0, parent.ToInt32());
+                               #if DriverDebug || DriverDebugParent
+                                       Console.WriteLine("Parent for window {0} = {1}", XplatUI.Window(hwnd.Handle), XplatUI.Window(hwnd.parent != null ? hwnd.parent.Handle : IntPtr.Zero));
                                #endif
                                XReparentWindow(DisplayHandle, hwnd.whole_window, hwnd.parent.client_window, hwnd.x, hwnd.y);
                        }