]> git.saurik.com Git - wxWidgets.git/commitdiff
added OnExit(); made event loop exception safe; added wxModalEvtLoop
authorVadim Zeitlin <vadim@wxwidgets.org>
Wed, 17 Sep 2003 23:32:32 +0000 (23:32 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Wed, 17 Sep 2003 23:32:32 +0000 (23:32 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@23647 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/evtloop.h
src/msw/evtloop.cpp

index 95e2fce43e26f0e6e63c0c6cec7354812f1d4393..dcd2a766e07cb1eaf4e842c35a5172b73e03029d 100644 (file)
@@ -16,6 +16,8 @@
     #pragma interface "evtloop.h"
 #endif
 
+class WXDLLEXPORT wxEventLoopImpl;
+
 // ----------------------------------------------------------------------------
 // wxEventLoop: a GUI event loop
 // ----------------------------------------------------------------------------
@@ -51,12 +53,48 @@ public:
     static void SetActive(wxEventLoop* loop) { ms_activeLoop = loop; }
 
 protected:
-    // the pointer to the port specific implementation class
-    class WXDLLEXPORT wxEventLoopImpl *m_impl;
+    // this function should be called before the event loop terminates, whether
+    // 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
     static wxEventLoop *ms_activeLoop;
 
+    // the pointer to the port specific implementation class
+    wxEventLoopImpl *m_impl;
+
     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_
index a36caa946dfa4a1bc8a54bddec951be45fb99661..c2540c8ee913daae1d97d5ca1b884502f3b2c616 100644 (file)
 #endif //WX_PRECOMP
 
 #include "wx/evtloop.h"
+
 #include "wx/tooltip.h"
+#include "wx/except.h"
+#include "wx/ptr_scpd.h"
+#include "wx/scopeguard.h"
 
 #include "wx/msw/private.h"
 
 #if wxUSE_THREADS
+    #include "wx/thread.h"
+
     // define the array of MSG strutures
     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
-    //     defined in app.cpp).
-#endif
+
+    #include "wx/arrimpl.cpp"
+
+    WX_DEFINE_OBJARRAY(wxMsgArray);
+#endif // wxUSE_THREADS
 
 // ----------------------------------------------------------------------------
 // wxEventLoopImpl
@@ -75,6 +82,36 @@ private:
     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
 // ============================================================================
@@ -198,10 +235,13 @@ int wxEventLoop::Run()
     // event loops are not recursive, you need to create another loop!
     wxCHECK_MSG( !IsRunning(), -1, _T("can't reenter a message loop") );
 
-    m_impl = new wxEventLoopImpl;
-    
-    wxEventLoop *oldLoop = ms_activeLoop;
-    ms_activeLoop = this;
+    // SendIdleMessage() and Dispatch() below may throw so the code here should
+    // be exception-safe, hence we must use local objects for all actions we
+    // should undo
+    wxEventLoopActivator activate(&ms_activeLoop, this);
+    wxEventLoopImplTiedPtr impl(&m_impl, new wxEventLoopImpl);
+
+    wxON_BLOCK_EXIT_OBJ0(*this, &wxEventLoop::OnExit);
 
     for ( ;; )
     {
@@ -214,8 +254,8 @@ int wxEventLoop::Run()
         while ( !Pending() && m_impl->SendIdleMessage() )
             ;
 
-        // a message came or no more idle processing to do, sit in Dispatch()
-        // waiting for the next message
+        // a message came or no more idle processing to do, sit in
+        // Dispatch() waiting for the next message
         if ( !Dispatch() )
         {
             // we got WM_QUIT
@@ -223,13 +263,7 @@ int wxEventLoop::Run()
         }
     }
 
-    int exitcode = m_impl->GetExitCode();
-    delete m_impl;
-    m_impl = NULL;
-
-    ms_activeLoop = oldLoop;
-
-    return exitcode;
+    return m_impl->GetExitCode();
 }
 
 void wxEventLoop::Exit(int rc)