added OnExit(); made event loop exception safe; added wxModalEvtLoop

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23647 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2003-09-17 23:32:32 +00:00
parent efbfda9d66
commit 4300caa7a6
2 changed files with 91 additions and 19 deletions

View File

@@ -16,6 +16,8 @@
#pragma interface "evtloop.h" #pragma interface "evtloop.h"
#endif #endif
class WXDLLEXPORT wxEventLoopImpl;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxEventLoop: a GUI event loop // wxEventLoop: a GUI event loop
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -51,12 +53,48 @@ public:
static void SetActive(wxEventLoop* loop) { ms_activeLoop = loop; } static void SetActive(wxEventLoop* loop) { ms_activeLoop = loop; }
protected: protected:
// the pointer to the port specific implementation class // this function should be called before the event loop terminates, whether
class WXDLLEXPORT wxEventLoopImpl *m_impl; // this happens normally (because of Exit() call) or abnormally (because of
// an exception thrown from inside the loop)
virtual void OnExit() { }
// the pointer to currently active loop // the pointer to currently active loop
static wxEventLoop *ms_activeLoop; static wxEventLoop *ms_activeLoop;
// the pointer to the port specific implementation class
wxEventLoopImpl *m_impl;
DECLARE_NO_COPY_CLASS(wxEventLoop) DECLARE_NO_COPY_CLASS(wxEventLoop)
}; };
// ----------------------------------------------------------------------------
// wxModalEventLoop
// ----------------------------------------------------------------------------
// this is a naive generic implementation which uses wxWindowDisabler to
// implement modality, we will surely need platform-specific implementations
// too, this generic implementation is here only temporarily to see how it
// works
class WXDLLEXPORT wxModalEventLoop : public wxEventLoop
{
public:
wxModalEventLoop(wxWindow *winModal)
{
m_windowDisabler = new wxWindowDisabler(winModal);
}
protected:
virtual void OnExit()
{
delete m_windowDisabler;
m_windowDisabler = NULL;
wxEventLoop::OnExit();
}
private:
wxWindowDisabler *m_windowDisabler;
};
#endif // _WX_EVTLOOP_H_ #endif // _WX_EVTLOOP_H_

View File

@@ -34,17 +34,24 @@
#endif //WX_PRECOMP #endif //WX_PRECOMP
#include "wx/evtloop.h" #include "wx/evtloop.h"
#include "wx/tooltip.h" #include "wx/tooltip.h"
#include "wx/except.h"
#include "wx/ptr_scpd.h"
#include "wx/scopeguard.h"
#include "wx/msw/private.h" #include "wx/msw/private.h"
#if wxUSE_THREADS #if wxUSE_THREADS
#include "wx/thread.h"
// define the array of MSG strutures // define the array of MSG strutures
WX_DECLARE_OBJARRAY(MSG, wxMsgArray); WX_DECLARE_OBJARRAY(MSG, wxMsgArray);
// VS: this is a bit dirty - it duplicates same declaration in app.cpp
// (and there's no WX_DEFINE_OBJARRAY for that reason - it is already #include "wx/arrimpl.cpp"
// defined in app.cpp).
#endif WX_DEFINE_OBJARRAY(wxMsgArray);
#endif // wxUSE_THREADS
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxEventLoopImpl // wxEventLoopImpl
@@ -75,6 +82,36 @@ private:
int m_exitcode; int m_exitcode;
}; };
// ----------------------------------------------------------------------------
// helper class
// ----------------------------------------------------------------------------
wxDEFINE_TIED_SCOPED_PTR_TYPE(wxEventLoopImpl);
// this object sets the wxEventLoop given to the ctor as the currently active
// one and unsets it in its dtor
class wxEventLoopActivator
{
public:
wxEventLoopActivator(wxEventLoop **pActive,
wxEventLoop *evtLoop)
{
m_pActive = pActive;
m_evtLoopOld = *pActive;
*pActive = evtLoop;
}
~wxEventLoopActivator()
{
// restore the previously active event loop
*m_pActive = m_evtLoopOld;
}
private:
wxEventLoop *m_evtLoopOld;
wxEventLoop **m_pActive;
};
// ============================================================================ // ============================================================================
// wxEventLoopImpl implementation // wxEventLoopImpl implementation
// ============================================================================ // ============================================================================
@@ -198,10 +235,13 @@ int wxEventLoop::Run()
// event loops are not recursive, you need to create another loop! // event loops are not recursive, you need to create another loop!
wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") ); wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
m_impl = new wxEventLoopImpl; // SendIdleMessage() and Dispatch() below may throw so the code here should
// be exception-safe, hence we must use local objects for all actions we
wxEventLoop *oldLoop = ms_activeLoop; // should undo
ms_activeLoop = this; wxEventLoopActivator activate(&ms_activeLoop, this);
wxEventLoopImplTiedPtr impl(&m_impl, new wxEventLoopImpl);
wxON_BLOCK_EXIT_OBJ0(*this, &wxEventLoop::OnExit);
for ( ;; ) for ( ;; )
{ {
@@ -214,8 +254,8 @@ int wxEventLoop::Run()
while ( !Pending() && m_impl->SendIdleMessage() ) while ( !Pending() && m_impl->SendIdleMessage() )
; ;
// a message came or no more idle processing to do, sit in Dispatch() // a message came or no more idle processing to do, sit in
// waiting for the next message // Dispatch() waiting for the next message
if ( !Dispatch() ) if ( !Dispatch() )
{ {
// we got WM_QUIT // we got WM_QUIT
@@ -223,13 +263,7 @@ int wxEventLoop::Run()
} }
} }
int exitcode = m_impl->GetExitCode(); return m_impl->GetExitCode();
delete m_impl;
m_impl = NULL;
ms_activeLoop = oldLoop;
return exitcode;
} }
void wxEventLoop::Exit(int rc) void wxEventLoop::Exit(int rc)