]> git.saurik.com Git - wxWidgets.git/commitdiff
changed exceptions handling to work under wxGTK
authorVáclav Slavík <vslavik@fastmail.fm>
Mon, 20 Jun 2005 08:20:50 +0000 (08:20 +0000)
committerVáclav Slavík <vslavik@fastmail.fm>
Mon, 20 Jun 2005 08:20:50 +0000 (08:20 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@34717 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

14 files changed:
docs/changes.txt
docs/latex/wx/app.tex
docs/latex/wx/evthand.tex
include/wx/app.h
include/wx/event.h
include/wx/object.h
src/common/appbase.cpp
src/common/appcmn.cpp
src/common/event.cpp
src/gtk/dialog.cpp
src/gtk/toplevel.cpp
src/gtk1/dialog.cpp
src/gtk1/toplevel.cpp
src/msw/evtloop.cpp

index a03e6752097c814fefb1e8856ad1ab3a08f78c73..8042cee430fdf18efd43efa65787223879f0c09a 100644 (file)
@@ -9,6 +9,8 @@ All:
 
 - Fixed wxScopeGuard to work with VC++, documented it.
 - Fixed proxy handling in wxURL.
+- Changed exceptions handling to work under wxGTK, added
+  virtual wxEvtHandler::DoHandleEvent()
 
 wxMSW:
 
index 461dcc6f10113452b188c8ac103fa02985995357..fc1fa101d680a91a2ab4129107096344ed998d97 100644 (file)
@@ -197,6 +197,20 @@ different visuals, false otherwise.
 Returns the application's vendor name.
 
 
+\membersection{wxApp::HandleEvent}\label{wxapphandleevent}
+
+\constfunc{virtual void}{HandleEvent}{\param{wxEvtHandler}{ *handler}, \param{wxEventFunction}{ func}, \param{wxEvent\& }{event}}
+
+This function simply invokes the
+\helpref{DoHandleEvent}{wxevthandlerdohandleevent} method of event handler
+\arg{handler}, passing \arg{func} and \arg{event} as parameters. If an
+exception occurs, \helpref{OnExceptionInMainLoop}{wxapponexceptioninmainloop}
+is called by this function. You can override it to customize exceptions
+handling.
+
+If you want to modify this behaviour, override this function.
+
+
 \membersection{wxApp::IsActive}\label{wxappisactive}
 
 \constfunc{bool}{IsActive}{\void}
@@ -665,18 +679,6 @@ This function currently only has effect under GTK.
 
 \docparam{flag}{If true, the app will use the best visual.}
 
-
-\membersection{wxApp::HandleEvent}\label{wxapphandleevent}
-
-\constfunc{virtual void}{HandleEvent}{\param{wxEvtHandler}{ *handler}, \param{wxEventFunction}{ func}, \param{wxEvent\& }{event}}
-
-This function simply invokes the given method \arg{func} of the specified
-event handler \arg{handler} with the \arg{event} as parameter. It exists solely
-to allow to catch the C++ exceptions which could be thrown by all event
-handlers in the application in one place: if you want to do this, override this
-function in your wxApp-derived class and add try/catch clause(s) to it.
-
-
 \membersection{wxApp::Yield}\label{wxappyield}
 
 \func{bool}{Yield}{\param{bool}{ onlyIfNeeded = false}}
index 98fed356957a0a225c4c69b9fe8bbec988f0bb73..8c3e91fc836eab4e516115ed394f740e23debb06 100644 (file)
@@ -155,6 +155,20 @@ to disconnect functions connected using the (static) event tables.
 \perlnote{In wxPerl this function takes 3 arguments: \texttt{id,
 lastid, type}.}
 
+\membersection{wxEvtHandler::DoHandleEvent}\label{wxevthandlerdohandleevent}
+
+\func{virtual void}{DoHandleEvent}{\param{wxEventFunction}{ func}, \param{wxEvent\& }{event}}
+
+This function simply invokes the given method \arg{func} of this
+event handler with the \arg{event} as parameter. It exists solely
+to allow to catch the C++ exceptions which could be thrown by this event
+handlers in one place: if you want to do this, override this
+function in your wxEvtHandler-derived class and add try/catch clause(s) to it.
+
+Exceptions not caught at this level propagate to
+\helpref{wxApp::HandleEvent}{wxapphandleevent} which in turn calls
+\helpref{wxApp::OnExceptionInMainLoop}{wxapponexceptioninmainloop}.
+
 \membersection{wxEvtHandler::GetClientData}\label{wxevthandlergetclientdata}
 
 \func{void* }{GetClientData}{\void}
index 02c5aee54d3bfee1fada5b7cb6a710af94adaf63..334c4d7c206ca3ab54e3518cfe0ea70308b63ab0 100644 (file)
@@ -433,6 +433,12 @@ public:
         // Perform standard OnIdle behaviour: call from port's OnIdle
     void OnIdle(wxIdleEvent& event);
 
+#if wxUSE_EXCEPTIONS
+    virtual void HandleEvent(wxEvtHandler *handler,
+                             wxEventFunction func,
+                             wxEvent& event) const;
+#endif // wxUSE_EXCEPTIONS
+
 
     // top level window functions
     // --------------------------
index 2e083e46b51f88da2c5f36baf8068d36e61e7c78..c8dda1ec36f274bf0223d198064830f62abe7a70 100644 (file)
@@ -2295,6 +2295,8 @@ protected:
 // wxEvtHandler: the base class for all objects handling wxWidgets events
 // ----------------------------------------------------------------------------
 
+typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
+
 class WXDLLIMPEXP_BASE wxEvtHandler : public wxObject
 {
 public:
@@ -2322,6 +2324,15 @@ public:
     bool ProcessThreadEvent(wxEvent& event);
 #endif
 
+#if wxUSE_EXCEPTIONS
+    // call the specified handler with the given event
+    //
+    // this method only exists to allow catching the exceptions thrown by any
+    // event handler, it would lead to an extra (useless) virtual function call
+    // if the exceptions were not used, so it doesn't even exist in that case
+    virtual void DoHandleEvent(wxEventFunction func, wxEvent& event);
+#endif // wxUSE_EXCEPTIONS
+
     // Dynamic association of a member function handler with the event handler,
     // winid and event type
     void Connect(int winid,
@@ -2482,8 +2493,6 @@ inline void wxPostEvent(wxEvtHandler *dest, wxEvent& event)
     dest->AddPendingEvent(event);
 }
 
-typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
-
 #define wxEventHandler(func) \
     (wxObjectEventFunction)wxStaticCastEvent(wxEventFunction, &func)
 
index 8f949c0979586d1cfd09edf12400efd918e89511..b88a0d850a4fc43b28f9b441143f3c63e8a8d3fa 100644 (file)
 
 class WXDLLIMPEXP_BASE wxObject;
 
+// FIXME: remove in wx-2.7:
+class WXDLLIMPEXP_BASE wxEvent;
+class WXDLLIMPEXP_BASE wxEvtHandler;
+
 #ifndef wxUSE_EXTENDED_RTTI
 #define wxUSE_EXTENDED_RTTI 0
 #endif
@@ -478,7 +482,9 @@ public:
     virtual void ReservedObjectFunc6() {}
     virtual void ReservedObjectFunc7() {}
     virtual void ReservedObjectFunc8() {}
-    virtual void ReservedObjectFunc9() {}
+    // FIXME: turn back into ReservedObjectFunc9() in wx-2.7 (see also FIXME
+    //        near the top of this file)
+    virtual void DoHandleEvent(void (wxEvtHandler::*)(wxEvent&), wxEvent&) {}
 
 protected:
     // ensure that our data is not shared with anybody else: if we have no
index 0892aab62d0e8724923a18458de698eefa927921..d9f65368b675cc641d8c3ca7ad93d6c9fef24714 100644 (file)
@@ -316,8 +316,15 @@ wxAppConsole::HandleEvent(wxEvtHandler *handler,
                           wxEventFunction func,
                           wxEvent& event) const
 {
-    // by default, simply call the handler
-    (handler->*func)(event);
+    // by default, call wxApp::OnExceptionInMainLoop if an exception occurs
+    try
+    {
+        handler->DoHandleEvent(func, event);
+    }
+    catch ( ... )
+    {
+        wxConstCast(this, wxAppConsole)->OnExceptionInMainLoop();
+    }
 }
 
 bool
index dddd390ab56bf8192c08b921a46e1e4d46057867..e5d27ef093e39e55741cace37d8ab5dcada6251d 100644 (file)
@@ -46,6 +46,7 @@
 #include "wx/thread.h"
 #include "wx/utils.h"
 #include "wx/ptr_scpd.h"
+#include "wx/evtloop.h"
 
 #if defined(__WXMSW__)
     #include  "wx/msw/private.h"  // includes windows.h for LOGFONT
@@ -467,6 +468,35 @@ void wxAppBase::OnIdle(wxIdleEvent& WXUNUSED(event))
 
 }
 
+// ----------------------------------------------------------------------------
+// exception handling
+// ----------------------------------------------------------------------------
+
+#if wxUSE_EXCEPTIONS
+
+void wxAppBase::HandleEvent(wxEvtHandler *handler,
+                            wxEventFunction func,
+                            wxEvent& event) const
+{
+    // by default, call wxApp::OnExceptionInMainLoop if an exception occurs
+    try
+    {
+        handler->DoHandleEvent(func, event);
+    }
+    catch ( ... )
+    {
+        if ( !wxConstCast(this, wxAppBase)->OnExceptionInMainLoop() )
+        {
+            wxEventLoop *loop = wxEventLoop::GetActive();
+            if ( loop )
+                loop->Exit(-1);
+        }
+        //else: continue running the event loop
+    }
+}
+
+#endif // wxUSE_EXCEPTIONS
+
 // ----------------------------------------------------------------------------
 // wxGUIAppTraitsBase
 // ----------------------------------------------------------------------------
index ae6acd19794f2ecc60c08660beed6b94b920cf00..648c80e2b78587d4f27d7c892649a432349f5c98 100644 (file)
@@ -1081,6 +1081,14 @@ void wxEvtHandler::ClearEventLocker()
 
 #endif // wxUSE_THREADS
 
+#if wxUSE_EXCEPTIONS
+void wxEvtHandler::DoHandleEvent(wxEventFunction func, wxEvent& event)
+{
+    // by default, just call then handler
+    (this->*func)(event);
+}
+#endif // wxUSE_EXCEPTIONS
+
 void wxEvtHandler::AddPendingEvent(wxEvent& event)
 {
     // 1) Add event to list of pending events of this event handler
index 115965adc4bd380586589c531dbcd68b5818f197..17df0e50d03676b7e3adad0230673fe1c7f0a3ad 100644 (file)
@@ -18,6 +18,7 @@
 #include "wx/frame.h"
 #include "wx/app.h"
 #include "wx/cursor.h"
+#include "wx/evtloop.h"
 
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
@@ -212,7 +213,9 @@ int wxDialog::ShowModal()
     g_openDialogs++;
 
     gtk_grab_add( m_widget );
-    gtk_main();
+
+    wxEventLoop().Run();
+
     gtk_grab_remove( m_widget );
 
     g_openDialogs--;
index 00d8ba76312a024ff0424ebedff7cee6e5190059..d13acd7d6827f0ce965f5c27dae6a9afea5273e0 100644 (file)
@@ -37,6 +37,7 @@
 #include "wx/gtk/private.h"
 #include "wx/timer.h"
 #include "wx/settings.h"
+#include "wx/evtloop.h"
 
 #include <glib.h>
 #include <gdk/gdk.h>
@@ -1202,7 +1203,7 @@ void wxTopLevelWindowGTK::AddGrab()
     {
         m_grabbed = TRUE;
         gtk_grab_add( m_widget );
-        gtk_main();
+        wxEventLoop().Run();
         gtk_grab_remove( m_widget );
     }
 }
index 115965adc4bd380586589c531dbcd68b5818f197..17df0e50d03676b7e3adad0230673fe1c7f0a3ad 100644 (file)
@@ -18,6 +18,7 @@
 #include "wx/frame.h"
 #include "wx/app.h"
 #include "wx/cursor.h"
+#include "wx/evtloop.h"
 
 #include <gdk/gdk.h>
 #include <gtk/gtk.h>
@@ -212,7 +213,9 @@ int wxDialog::ShowModal()
     g_openDialogs++;
 
     gtk_grab_add( m_widget );
-    gtk_main();
+
+    wxEventLoop().Run();
+
     gtk_grab_remove( m_widget );
 
     g_openDialogs--;
index 00d8ba76312a024ff0424ebedff7cee6e5190059..d13acd7d6827f0ce965f5c27dae6a9afea5273e0 100644 (file)
@@ -37,6 +37,7 @@
 #include "wx/gtk/private.h"
 #include "wx/timer.h"
 #include "wx/settings.h"
+#include "wx/evtloop.h"
 
 #include <glib.h>
 #include <gdk/gdk.h>
@@ -1202,7 +1203,7 @@ void wxTopLevelWindowGTK::AddGrab()
     {
         m_grabbed = TRUE;
         gtk_grab_add( m_widget );
-        gtk_main();
+        wxEventLoop().Run();
         gtk_grab_remove( m_widget );
     }
 }
index 4325bbdd0a33c0c313e8d67986e33d412a84e181..27877fa3f2fc3b17e7622dcdda256044673a8814 100644 (file)
@@ -207,74 +207,48 @@ int wxEventLoop::Run()
     // should undo
     wxEventLoopActivator activate(&ms_activeLoop, this);
 
-    // 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 ( ;; )
+    try
     {
-        try
+#endif
+        // this is the event loop itself
+        for ( ;; )
         {
-#endif // wxUSE_EXCEPTIONS
-
-            // 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() && (wxTheApp && wxTheApp->ProcessIdle()) )
+                ;
+
+            // 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_shouldExit )
             {
-                #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() && (wxTheApp && wxTheApp->ProcessIdle()) )
-                    ;
-
-                // 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_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;
-                }
-            }
+                while ( Pending() )
+                    Dispatch();
 
-#if wxUSE_EXCEPTIONS
-            // exit the outer loop as well
-            break;
-        }
-        catch ( ... )
-        {
-            try
-            {
-                if ( !wxTheApp || !wxTheApp->OnExceptionInMainLoop() )
-                {
-                    OnExit();
-                    break;
-                }
-                //else: continue running the event loop
+                break;
             }
-            catch ( ... )
+
+            // a message came or no more idle processing to do, sit in
+            // Dispatch() waiting for the next message
+            if ( !Dispatch() )
             {
-                // OnException() throwed, possibly rethrowing the same
-                // exception again: very good, but we still need OnExit() to
-                // be called
-                OnExit();
-                throw;
+                // we got WM_QUIT
+                break;
             }
         }
+#if wxUSE_EXCEPTIONS
+    }
+    catch ( ... )
+    {
+        // we need OnExit() to be called before the event loop stops
+        OnExit();
+        throw;
     }
 #endif // wxUSE_EXCEPTIONS