]> git.saurik.com Git - wxWidgets.git/commitdiff
delete wxNativeContainerWindow when the native window is destroyed, even if this...
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 11 Mar 2008 00:03:46 +0000 (00:03 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 11 Mar 2008 00:03:46 +0000 (00:03 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@52437 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/nativewin.h
src/gtk/nativewin.cpp
src/msw/nativewin.cpp

index ca663ba4d7a754847d4fcac97bf252cec3e25922..3aa6ffc79055f41aa3c73b1e634437d9c0d78080 100644 (file)
@@ -145,6 +145,13 @@ public:
         return false;
     }
 
+
+    // this is an implementation detail: called when the native window is
+    // destroyed by an outside agency; deletes the C++ object too but can in
+    // principle be overridden to something else (knowing that the window
+    // handle of this object and all of its children is invalid any more)
+    virtual void OnNativeDestroyed();
+
 private:
     DECLARE_NO_COPY_CLASS(wxNativeContainerWindow)
 };
index 0ccb183ff17c528db31bc0949b9130d701e6558d..8647cc0aca100ccb08de341e6c492f0aee7ab8ec 100644 (file)
 
 #include <gtk/gtk.h>
 
+#ifdef GDK_WINDOWING_X11
+    #include <X11/Xlib.h>
+#endif
+
 // ============================================================================
 // implementation
 // ============================================================================
 
+// TODO: we probably need equivalent code for other GDK platforms
+#ifdef GDK_WINDOWING_X11
+
+extern "C" GdkFilterReturn
+wxNativeContainerWindowFilter(GdkXEvent *gdkxevent,
+                              GdkEvent *event,
+                              gpointer data)
+{
+    XEvent * const xevent = static_cast<XEvent *>(gdkxevent);
+    if ( xevent->type == DestroyNotify )
+    {
+        // we won't need it any more
+        gdk_window_remove_filter(event->any.window,
+                                 wxNativeContainerWindowFilter, data);
+
+        // the underlying window got destroyed, notify the C++ object
+        static_cast<wxNativeContainerWindow *>(data)->OnNativeDestroyed();
+    }
+
+    return GDK_FILTER_CONTINUE;
+}
+
+#endif // GDK_WINDOWING_X11
+
 bool wxNativeContainerWindow::Create(wxNativeContainerWindowHandle win)
 {
+    wxCHECK( win, false );
+
     if ( !wxTopLevelWindow::Create(NULL, wxID_ANY, "") )
         return false;
 
@@ -43,6 +73,15 @@ bool wxNativeContainerWindow::Create(wxNativeContainerWindowHandle win)
     gtk_widget_realize(m_widget);
     gdk_window_reparent(m_widget->window, win, 0, 0);
 
+#ifdef GDK_WINDOWING_X11
+    // if the native window is destroyed, our own window will be destroyed too
+    // but GTK doesn't expect it and will complain about "unexpectedly
+    // destroyed" GdkWindow, so intercept to DestroyNotify ourselves to fix
+    // this and also destroy the associated C++ object when its window is
+    // destroyed
+    gdk_window_add_filter(m_widget->window, wxNativeContainerWindowFilter, this);
+#endif // GDK_WINDOWING_X11
+
     // we should be initially visible as we suppose that the native window we
     // wrap is (we could use gdk_window_is_visible() to test for this but this
     // doesn't make much sense unless we also react to visibility changes, so
@@ -69,8 +108,27 @@ bool wxNativeContainerWindow::Create(wxNativeContainerWindowId anid)
     return rc;
 }
 
+void wxNativeContainerWindow::OnNativeDestroyed()
+{
+    // unfortunately we simply can't do anything else than leak memory here:
+    // we really need to call _gdk_window_destroy(m_widget->win, TRUE) to
+    // indicate that the native window was deleted, but we can't do this
+    // because it's a private GDK function and calling normal
+    // gdk_window_destroy() results in X errors while nulling just the window
+    // pointer and destroying m_widget results in many GTK errors
+    m_widget = NULL;
+
+    // notice that we intentionally don't use Close() nor Delete() here as our
+    // window (and the windows of all of our children) is invalid any more and
+    // any attempts to use it, as may happen with the delayed destruction, will
+    // result in GDK warnings at best and crashes or X errors at worst
+    delete this;
+}
+
 wxNativeContainerWindow::~wxNativeContainerWindow()
 {
-    // there doesn't seem to be anything to do here, GTK+ seems to handle
-    // everything correctly due to its use of reference counting
+    // nothing to do here, either we have a valid m_widget and it will be
+    // destroyed as usual (this corresponds to manual destruction of this C++
+    // object) or we are being deleted because the native window was destroyed
+    // and in this case our m_widget was set to NULL by OnNativeDestroyed()
 }
index 1f0ddeca87811540ad77960a374633b0e0043c97..3ac00548a74a94e45482e72465296151379cf8cb 100644 (file)
@@ -54,6 +54,11 @@ bool wxNativeContainerWindow::Create(wxNativeContainerWindowHandle hwnd)
     return true;
 }
 
+void wxNativeContainerWindow::OnNativeDestroyed()
+{
+    // currently this is not called so nothing to do here
+}
+
 wxNativeContainerWindow::~wxNativeContainerWindow()
 {
     // prevent the base class dtor from destroying the window, it doesn't