]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/nativewin.cpp
include 'Version' in version string, it's what Apple apps do
[wxWidgets.git] / src / gtk / nativewin.cpp
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()
 }