diff --git a/src/gtk/notebook.cpp b/src/gtk/notebook.cpp index 0f141cfe8e..93878cceb6 100644 --- a/src/gtk/notebook.cpp +++ b/src/gtk/notebook.cpp @@ -151,6 +151,13 @@ wxNotebook::wxNotebook( wxWindow *parent, wxWindowID id, wxNotebook::~wxNotebook() { + // Ensure that we don't generate page changing events during the + // destruction, this is unexpected and may reference the already (half) + // destroyed parent window, for example. So make sure our switch_page + // callback is not called from inside DeleteAllPages() by disconnecting all + // the callbacks associated with this widget. + GTKDisconnect(m_widget); + DeleteAllPages(); } diff --git a/tests/controls/notebooktest.cpp b/tests/controls/notebooktest.cpp index d8a6fb44a0..5471dda4ce 100644 --- a/tests/controls/notebooktest.cpp +++ b/tests/controls/notebooktest.cpp @@ -25,7 +25,7 @@ class NotebookTestCase : public BookCtrlBaseTestCase, public CppUnit::TestCase { public: - NotebookTestCase() { } + NotebookTestCase() { m_notebook = NULL; m_numPageChanges = 0; } virtual void setUp(); virtual void tearDown(); @@ -44,12 +44,18 @@ private: wxBOOK_CTRL_BASE_TESTS(); CPPUNIT_TEST( Image ); CPPUNIT_TEST( RowCount ); + CPPUNIT_TEST( NoEventsOnDestruction ); CPPUNIT_TEST_SUITE_END(); void RowCount(); + void NoEventsOnDestruction(); + + void OnPageChanged(wxNotebookEvent&) { m_numPageChanges++; } wxNotebook *m_notebook; + int m_numPageChanges; + wxDECLARE_NO_COPY_CLASS(NotebookTestCase); }; @@ -90,4 +96,26 @@ void NotebookTestCase::RowCount() #endif } +void NotebookTestCase::NoEventsOnDestruction() +{ + // We can't use EventCounter helper here as it doesn't deal with the window + // it's connected to being destroyed during its life-time, so do it + // manually. + m_notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, + &NotebookTestCase::OnPageChanged, this); + + // Normally deleting a page before the selected one results in page + // selection changing and the corresponding event. + m_notebook->DeletePage(0); + CHECK( m_numPageChanges == 1 ); + + // But deleting the entire control shouldn't generate any events, yet it + // used to do under GTK+ 3 when a page different from the first one was + // selected. + m_notebook->ChangeSelection(1); + m_notebook->Destroy(); + m_notebook = NULL; + CHECK( m_numPageChanges == 1 ); +} + #endif //wxUSE_NOTEBOOK