delete wxNativeContainerWindow when the native window is destroyed, even if this means leaking memory in GTK case -- still better than getting X errors and crashing
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@52437 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
4f6b94a33a
commit
2aee749cb1
@ -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)
|
||||
};
|
||||
|
@ -30,12 +30,42 @@
|
||||
|
||||
#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()
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user