From 16cc6273325c5ffe2efcd4ea9100f6be63d5cfd0 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Mon, 25 Nov 2013 13:51:12 +0000 Subject: [PATCH] making sure no pending deletes get executed while a modal loop is running, avoiding double deletes because the dialogs are mostly allocated on the stack. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@75289 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/osx/evtloop.h | 4 +++- src/osx/cocoa/evtloop.mm | 39 +++++++++++++++++++++++++++++++++++++ src/osx/core/evtloop_cf.cpp | 4 ++-- 3 files changed, 44 insertions(+), 3 deletions(-) diff --git a/include/wx/osx/evtloop.h b/include/wx/osx/evtloop.h index 995a713701..98772dd97f 100644 --- a/include/wx/osx/evtloop.h +++ b/include/wx/osx/evtloop.h @@ -30,7 +30,9 @@ public: #ifdef __WXOSX_COCOA__ // skip wxGUIEventLoop to avoid missing Enter/Exit notifications - int Run() { return wxCFEventLoop::Run(); } + virtual int Run() { return wxCFEventLoop::Run(); } + + virtual bool ProcessIdle(); #endif protected: virtual void OSXDoRun(); diff --git a/src/osx/cocoa/evtloop.mm b/src/osx/cocoa/evtloop.mm index c6c55d948f..97276ae40d 100644 --- a/src/osx/cocoa/evtloop.mm +++ b/src/osx/cocoa/evtloop.mm @@ -421,6 +421,45 @@ void wxModalEventLoop::OSXDoStop() [NSApp abortModal]; } +// we need our own version of ProcessIdle here in order to +// avoid deletion of pending objects, because ProcessIdle is running +// to soon and ends up in destroying the object too early, ie before +// a stack allocated instance is removed resulting in double deletes +bool wxModalEventLoop::ProcessIdle() +{ + bool needMore = false; + if ( wxTheApp ) + { + // synthesize an idle event and check if more of them are needed + wxIdleEvent event; + event.SetEventObject(wxTheApp); + wxTheApp->ProcessEvent(event); + +#if wxUSE_LOG + // flush the logged messages if any (do this after processing the events + // which could have logged new messages) + wxLog::FlushActive(); +#endif + bool needMore = event.MoreRequested(); + + wxWindowList::compatibility_iterator node = wxTopLevelWindows.GetFirst(); + while (node) + { + wxWindow* win = node->GetData(); + + // Don't send idle events to the windows that are about to be destroyed + // anyhow, this is wasteful and unexpected. + if ( !wxPendingDelete.Member(win) && win->SendIdleEvents(event) ) + needMore = true; + node = node->GetNext(); + } + + wxUpdateUIEvent::ResetUpdateTime(); + + } + return needMore; +} + void wxGUIEventLoop::BeginModalSession( wxWindow* modalWindow ) { WXWindow nsnow = nil; diff --git a/src/osx/core/evtloop_cf.cpp b/src/osx/core/evtloop_cf.cpp index e3e0752f04..37b22b5909 100644 --- a/src/osx/core/evtloop_cf.cpp +++ b/src/osx/core/evtloop_cf.cpp @@ -71,14 +71,14 @@ wxCFEventLoopSource::~wxCFEventLoopSource() void wxCFEventLoop::OSXCommonModeObserverCallBack(CFRunLoopObserverRef observer, int activity, void *info) { wxCFEventLoop * eventloop = static_cast(info); - if ( eventloop ) + if ( eventloop && eventloop->IsRunning() ) eventloop->CommonModeObserverCallBack(observer, activity); } void wxCFEventLoop::OSXDefaultModeObserverCallBack(CFRunLoopObserverRef observer, int activity, void *info) { wxCFEventLoop * eventloop = static_cast(info); - if ( eventloop ) + if ( eventloop && eventloop->IsRunning() ) eventloop->DefaultModeObserverCallBack(observer, activity); }