]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/evtloop.cpp
fix for opening files with VC++ 8 (closes bug 994337)
[wxWidgets.git] / src / msw / evtloop.cpp
index c2540c8ee913daae1d97d5ca1b884502f3b2c616..80be76737198dd2bc4e493380afc1164ff3aeecc 100644 (file)
@@ -38,7 +38,6 @@
 #include "wx/tooltip.h"
 #include "wx/except.h"
 #include "wx/ptr_scpd.h"
-#include "wx/scopeguard.h"
 
 #include "wx/msw/private.h"
 
@@ -61,7 +60,7 @@ class WXDLLEXPORT wxEventLoopImpl
 {
 public:
     // ctor
-    wxEventLoopImpl() { SetExitCode(0); }
+    wxEventLoopImpl() { m_exitcode = 0; m_shouldExit = false; }
 
     // process a message
     void ProcessMessage(MSG *msg);
@@ -70,8 +69,9 @@ public:
     bool SendIdleMessage();
 
     // set/get the exit code
-    void SetExitCode(int exitcode) { m_exitcode = exitcode; }
+    void Exit(int exitcode) { m_exitcode = exitcode; m_shouldExit = true; }
     int GetExitCode() const { return m_exitcode; }
+    bool ShouldExit() const { return m_shouldExit; }
 
 private:
     // preprocess a message, return TRUE if processed (i.e. no further
@@ -80,6 +80,9 @@ private:
 
     // the exit code of the event loop
     int m_exitcode;
+
+    // true if we were asked to terminate
+    bool m_shouldExit;
 };
 
 // ----------------------------------------------------------------------------
@@ -207,7 +210,7 @@ bool wxEventLoopImpl::PreProcessMessage(MSG *msg)
 
 bool wxEventLoopImpl::SendIdleMessage()
 {
-    return wxTheApp->ProcessIdle();
+    return wxTheApp && wxTheApp->ProcessIdle();
 }
 
 // ============================================================================
@@ -241,27 +244,76 @@ int wxEventLoop::Run()
     wxEventLoopActivator activate(&ms_activeLoop, this);
     wxEventLoopImplTiedPtr impl(&m_impl, new wxEventLoopImpl);
 
-    wxON_BLOCK_EXIT_OBJ0(*this, &wxEventLoop::OnExit);
-
+    // we must ensure that OnExit() is called even if an exception is thrown
+    // from inside Dispatch() but we must call it from Exit() in normal
+    // situations because it is supposed to be called synchronously,
+    // wxModalEventLoop depends on this (so we can't just use ON_BLOCK_EXIT or
+    // something similar here)
+#if wxUSE_EXCEPTIONS
     for ( ;; )
     {
-#if wxUSE_THREADS
-        wxMutexGuiLeaveOrEnter();
-#endif // wxUSE_THREADS
+        try
+        {
+#endif // wxUSE_EXCEPTIONS
 
-        // generate and process idle events for as long as we don't have
-        // anything else to do
-        while ( !Pending() && m_impl->SendIdleMessage() )
-            ;
+            // this is the event loop itself
+            for ( ;; )
+            {
+                #if wxUSE_THREADS
+                    wxMutexGuiLeaveOrEnter();
+                #endif // wxUSE_THREADS
+
+                // generate and process idle events for as long as we don't
+                // have anything else to do
+                while ( !Pending() && m_impl->SendIdleMessage() )
+                    ;
+
+                // if the "should exit" flag is set, the loop should terminate
+                // but not before processing any remaining messages so while
+                // Pending() returns true, do process them
+                if ( m_impl->ShouldExit() )
+                {
+                    while ( Pending() )
+                        Dispatch();
+
+                    break;
+                }
+
+                // a message came or no more idle processing to do, sit in
+                // Dispatch() waiting for the next message
+                if ( !Dispatch() )
+                {
+                    // we got WM_QUIT
+                    break;
+                }
+            }
 
-        // a message came or no more idle processing to do, sit in
-        // Dispatch() waiting for the next message
-        if ( !Dispatch() )
-        {
-            // we got WM_QUIT
+#if wxUSE_EXCEPTIONS
+            // exit the outer loop as well
             break;
         }
+        catch ( ... )
+        {
+            try
+            {
+                if ( !wxTheApp || !wxTheApp->OnExceptionInMainLoop() )
+                {
+                    OnExit();
+                    break;
+                }
+                //else: continue running the event loop
+            }
+            catch ( ... )
+            {
+                // OnException() throwed, possibly rethrowing the same
+                // exception again: very good, but we still need OnExit() to
+                // be called
+                OnExit();
+                throw;
+            }
+        }
     }
+#endif // wxUSE_EXCEPTIONS
 
     return m_impl->GetExitCode();
 }
@@ -270,9 +322,18 @@ void wxEventLoop::Exit(int rc)
 {
     wxCHECK_RET( IsRunning(), _T("can't call Exit() if not running") );
 
-    m_impl->SetExitCode(rc);
+    m_impl->Exit(rc);
+
+    OnExit();
 
-    ::PostQuitMessage(rc);
+    // all we have to do to exit from the loop is to (maybe) wake it up so that
+    // it can notice that Exit() had been called
+    //
+    // in particular, we do *not* use PostQuitMessage() here because we're not
+    // sure that WM_QUIT is going to be processed by the correct event loop: it
+    // is possible that another one is started before this one has a chance to
+    // process WM_QUIT
+    ::PostMessage(NULL, WM_NULL, 0, 0);
 }
 
 // ----------------------------------------------------------------------------