+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
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) {
if (IsHandleCreated) {
DestroyHandle();
- CreateHandle();
+ // WM_DESTROY will CreateHandle for us
} else {
if (!is_created) {
CreateControl();
case Msg.WM_DESTROY: {
OnHandleDestroyed(EventArgs.Empty);
window.InvalidateHandle();
+
+ if (ParentIsRecreating) {
+ RecreateHandle();
+ } else if (is_recreating) {
+ CreateHandle();
+ }
return;
}
return;
}
- case Msg.WM_PAINT: {
+ case Msg.WM_PAINT: {
PaintEventArgs paint_event;
paint_event = XplatUI.PaintEventStart(Handle, true);
// Extra detailed debug
#undef DriverDebugExtra
+#define DriverDebugParent
+#define DriverDebugCreate
+#define DriverDebugDestroy
using System;
using System.ComponentModel;
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();
}
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
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);
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);
}