From: Francesco Montorsi Date: Mon, 29 Dec 2008 15:03:39 +0000 (+0000) Subject: use a common m_isInsideYield flag instead of static booleans in all ports; add a... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/d181e877b04950068cb809b0d3d1a911bea3de74?ds=sidebyside use a common m_isInsideYield flag instead of static booleans in all ports; add a IsYielding() test which can help to fix unwanted re-entrancies git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57637 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/app.h b/include/wx/app.h index d61b3b5613..c3b87dd018 100644 --- a/include/wx/app.h +++ b/include/wx/app.h @@ -454,6 +454,10 @@ public: // with _extreme_ care or, better, don't use at all! virtual bool Yield(bool onlyIfNeeded = false) = 0; + // returns true if the main thread is inside a Yield() call + bool IsYielding() const + { return m_isInsideYield; } + // this virtual function is called in the GUI mode when the application // becomes idle and normally just sends wxIdleEvent to all interested // parties @@ -576,6 +580,7 @@ protected: // does any of our windows have focus? bool m_isActive; + bool m_isInsideYield; DECLARE_NO_COPY_CLASS(wxAppBase) }; diff --git a/interface/wx/app.h b/interface/wx/app.h index ab2d90b964..4b93f3f140 100644 --- a/interface/wx/app.h +++ b/interface/wx/app.h @@ -176,6 +176,11 @@ public: */ static bool IsMainLoopRunning(); + /** + Returns @true if called from inside Yield(). + */ + bool IsYielding() const; + /** Process all pending events; it is necessary to call this function to process posted events. @@ -466,6 +471,7 @@ public: user to perform actions which are not compatible with the current task. Disabling menu items or whole menus during processing can avoid unwanted reentrance of code: see ::wxSafeYield for a better function. + You can avoid unwanted reentrancies also using IsYielding(). Note that Yield() will not flush the message logs. This is intentional as calling Yield() is usually done to quickly update the screen and popping up diff --git a/src/cocoa/app.mm b/src/cocoa/app.mm index 444cccfb89..662859f091 100644 --- a/src/cocoa/app.mm +++ b/src/cocoa/app.mm @@ -297,16 +297,13 @@ void wxApp::Exit() // Yield to other processes bool wxApp::Yield(bool onlyIfNeeded) { - // MT-FIXME - static bool s_inYield = false; - #if wxUSE_LOG // disable log flushing from here because a call to wxYield() shouldn't // normally result in message boxes popping up &c wxLog::Suspend(); #endif // wxUSE_LOG - if (s_inYield) + if (m_isInsideYield) { if ( !onlyIfNeeded ) { @@ -316,7 +313,7 @@ bool wxApp::Yield(bool onlyIfNeeded) return false; } - s_inYield = true; + m_isInsideYield = true; // Run the event loop until it is out of events while(1) @@ -358,7 +355,7 @@ bool wxApp::Yield(bool onlyIfNeeded) wxLog::Resume(); #endif // wxUSE_LOG - s_inYield = false; + m_isInsideYield = false; return true; } diff --git a/src/common/appcmn.cpp b/src/common/appcmn.cpp index ef67c91681..a38f84583f 100644 --- a/src/common/appcmn.cpp +++ b/src/common/appcmn.cpp @@ -78,6 +78,8 @@ wxAppBase::wxAppBase() m_isActive = true; + m_isInsideYield = false; + // We don't want to exit the app if the user code shows a dialog from its // OnInit() -- but this is what would happen if we set m_exitOnFrameDelete // to Yes initially as this dialog would be the last top level window. diff --git a/src/dfb/app.cpp b/src/dfb/app.cpp index ad9144d250..c95912e538 100644 --- a/src/dfb/app.cpp +++ b/src/dfb/app.cpp @@ -171,9 +171,7 @@ bool wxApp::Yield(bool onlyIfNeeded) return true; // can't process events from other threads #endif // wxUSE_THREADS - static bool s_inYield = false; - - if ( s_inYield ) + if ( m_isInsideYield ) { if ( !onlyIfNeeded ) { @@ -183,7 +181,7 @@ bool wxApp::Yield(bool onlyIfNeeded) return false; } - s_inYield = true; + m_isInsideYield = true; #if wxUSE_LOG wxLog::Suspend(); @@ -203,7 +201,7 @@ bool wxApp::Yield(bool onlyIfNeeded) wxLog::Resume(); #endif // wxUSE_LOG - s_inYield = false; + m_isInsideYield = false; return true; } diff --git a/src/gtk/app.cpp b/src/gtk/app.cpp index 2041a588a7..2847577dde 100644 --- a/src/gtk/app.cpp +++ b/src/gtk/app.cpp @@ -54,14 +54,9 @@ static GtkWidget *gs_RootWindow = (GtkWidget*) NULL; // wxYield //----------------------------------------------------------------------------- -// not static because used by textctrl.cpp -// -// MT-FIXME -bool wxIsInsideYield = false; - bool wxApp::Yield(bool onlyIfNeeded) { - if ( wxIsInsideYield ) + if ( m_isInsideYield ) { if ( !onlyIfNeeded ) { @@ -79,7 +74,7 @@ bool wxApp::Yield(bool onlyIfNeeded) } #endif // wxUSE_THREADS - wxIsInsideYield = true; + m_isInsideYield = true; #if wxUSE_LOG // disable log flushing from here because a call to wxYield() shouldn't @@ -103,7 +98,7 @@ bool wxApp::Yield(bool onlyIfNeeded) wxLog::Resume(); #endif - wxIsInsideYield = false; + m_isInsideYield = false; return true; } diff --git a/src/gtk1/app.cpp b/src/gtk1/app.cpp index d2e2211643..9810be0320 100644 --- a/src/gtk1/app.cpp +++ b/src/gtk1/app.cpp @@ -103,14 +103,9 @@ static wxMutex gs_idleTagsMutex; // wxYield //----------------------------------------------------------------------------- -// not static because used by textctrl.cpp -// -// MT-FIXME -bool wxIsInsideYield = false; - bool wxApp::Yield(bool onlyIfNeeded) { - if ( wxIsInsideYield ) + if ( m_isInsideYield ) { if ( !onlyIfNeeded ) { @@ -128,7 +123,7 @@ bool wxApp::Yield(bool onlyIfNeeded) } #endif // wxUSE_THREADS - wxIsInsideYield = true; + m_isInsideYield = true; // We need to remove idle callbacks or the loop will // never finish. @@ -156,7 +151,7 @@ bool wxApp::Yield(bool onlyIfNeeded) wxLog::Resume(); #endif - wxIsInsideYield = false; + m_isInsideYield = false; return true; } diff --git a/src/gtk1/textctrl.cpp b/src/gtk1/textctrl.cpp index ea289a657e..f623672fc8 100644 --- a/src/gtk1/textctrl.cpp +++ b/src/gtk1/textctrl.cpp @@ -175,8 +175,6 @@ gtk_scrollbar_changed_callback( GtkWidget *WXUNUSED(widget), wxTextCtrl *win ) // which implicitly calls wxYield()) so we override GtkText::draw() and simply // don't do anything if we're inside wxYield() -extern bool wxIsInsideYield; - extern "C" { typedef void (*GtkDrawCallback)(GtkWidget *widget, GdkRectangle *rect); } @@ -186,7 +184,7 @@ static GtkDrawCallback gs_gtk_text_draw = NULL; extern "C" { static void wxgtk_text_draw( GtkWidget *widget, GdkRectangle *rect) { - if ( !wxIsInsideYield ) + if ( !wxTheApp->IsYielding() ) { wxCHECK_RET( gs_gtk_text_draw != wxgtk_text_draw, _T("infinite recursion in wxgtk_text_draw aborted") ); diff --git a/src/mgl/app.cpp b/src/mgl/app.cpp index c0338c7834..0c0a1ac7d4 100644 --- a/src/mgl/app.cpp +++ b/src/mgl/app.cpp @@ -48,11 +48,9 @@ void wxApp::Exit() // wxYield //----------------------------------------------------------------------------- -static bool gs_inYield = false; - bool wxApp::Yield(bool onlyIfNeeded) { - if ( gs_inYield ) + if ( m_isInsideYield ) { if ( !onlyIfNeeded ) { @@ -70,7 +68,7 @@ bool wxApp::Yield(bool onlyIfNeeded) } #endif // wxUSE_THREADS - gs_inYield = true; + m_isInsideYield = true; wxLog::Suspend(); @@ -88,7 +86,7 @@ bool wxApp::Yield(bool onlyIfNeeded) wxLog::Resume(); - gs_inYield = false; + m_isInsideYield = false; return true; } diff --git a/src/motif/app.cpp b/src/motif/app.cpp index 5807769612..6f85268d75 100644 --- a/src/motif/app.cpp +++ b/src/motif/app.cpp @@ -472,9 +472,7 @@ void wxApp::SetTopLevelRealizedWidget(WXDisplay* display, WXWidget widget) bool wxApp::Yield(bool onlyIfNeeded) { - static bool s_inYield = false; - - if ( s_inYield ) + if ( m_isInsideYield ) { if ( !onlyIfNeeded ) { @@ -484,13 +482,13 @@ bool wxApp::Yield(bool onlyIfNeeded) return false; } - s_inYield = true; + m_isInsideYield = true; wxEventLoopGuarantor dummyLoopIfNeeded; while (wxTheApp && wxTheApp->Pending()) wxTheApp->Dispatch(); - s_inYield = false; + m_isInsideYield = false; return true; } diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 646470fe6f..56af196bdd 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -1015,10 +1015,7 @@ int wxApp::GetShell32Version() bool wxApp::Yield(bool onlyIfNeeded) { - // MT-FIXME - static bool s_inYield = false; - - if ( s_inYield ) + if ( m_isInsideYield ) { if ( !onlyIfNeeded ) { @@ -1029,8 +1026,8 @@ bool wxApp::Yield(bool onlyIfNeeded) } // set the flag and don't forget to reset it before returning - s_inYield = true; - wxON_BLOCK_EXIT_SET(s_inYield, false); + m_isInsideYield = true; + wxON_BLOCK_EXIT_SET(m_isInsideYield, false); #if wxUSE_LOG diff --git a/src/os2/app.cpp b/src/os2/app.cpp index f896e02201..097b323973 100644 --- a/src/os2/app.cpp +++ b/src/os2/app.cpp @@ -509,9 +509,7 @@ void wxApp::OnQueryEndSession( wxCloseEvent& rEvent ) // bool wxApp::Yield(bool onlyIfNeeded) { - static bool s_inYield = false; - - if ( s_inYield ) + if ( m_isInsideYield ) { if ( !onlyIfNeeded ) { @@ -530,7 +528,7 @@ bool wxApp::Yield(bool onlyIfNeeded) // wxLog::Suspend(); - s_inYield = true; + m_isInsideYield = true; // // We want to go back to the main message loop @@ -545,6 +543,7 @@ bool wxApp::Yield(bool onlyIfNeeded) if (!wxTheApp->Dispatch()) break; } + // // If they are pending events, we must process them. // @@ -552,11 +551,13 @@ bool wxApp::Yield(bool onlyIfNeeded) wxTheApp->ProcessPendingEvents(); HandleSockets(); + // // Let the logs be flashed again // wxLog::Resume(); - s_inYield = false; + m_isInsideYield = false; + return true; } // end of wxYield diff --git a/src/osx/carbon/app.cpp b/src/osx/carbon/app.cpp index 9f85b4dda2..be9227b5fb 100644 --- a/src/osx/carbon/app.cpp +++ b/src/osx/carbon/app.cpp @@ -184,7 +184,7 @@ short wxApp::MacHandleAEGURL(const WXEVENTREF event, WXEVENTREF WXUNUSED(reply)) if (err != noErr) return err; - url[actualSize] = '\0'; // Terminate the C string + url[actualSize] = '\0'; // Terminate the C string ProcessSerialNumber PSN ; PSN.highLongOfPSN = 0 ; @@ -357,9 +357,9 @@ void wxApp::MacReopenApp() // make sure we don't show 'virtual toplevel windows' like wxTaskBarIconWindow if ( firstHidden == NULL && ( wxDynamicCast( win, wxFrame ) || wxDynamicCast( win, wxDialog ) ) ) firstHidden = win ; - } + } else if ( win->IsIconized() ) - { + { if ( firstIconized == NULL ) firstIconized = win ; } @@ -499,7 +499,7 @@ wxMenu* wxFindMenuFromMacCommand( const HICommand &command , wxMenuItem* &item ) // is it part of the application or the Help menu, then look for the id directly if ( ( GetMenuHandle( kwxMacAppleMenuId ) != NULL && command.menu.menuRef == GetMenuHandle( kwxMacAppleMenuId ) ) || - ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) || + ( helpMenuHandle != NULL && command.menu.menuRef == helpMenuHandle ) || wxMenuBar::MacGetWindowMenuHMenu() != NULL && command.menu.menuRef == wxMenuBar::MacGetWindowMenuHMenu() ) { wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar() ; @@ -576,7 +576,7 @@ wxMacAppMenuEventHandler( EventHandlerCallRef WXUNUSED(handler), case kEventMenuTargetItem: { HICommand command ; - + command.menu.menuRef = menuRef; command.menu.menuItemIndex = cEvent.GetParameter(kEventParamMenuItemIndex,typeMenuItemIndex) ; command.commandID = cEvent.GetParameter(kEventParamMenuCommand,typeMenuCommand) ; @@ -900,7 +900,7 @@ bool wxApp::DoInitGui() if ( !wxMacInitCocoa() ) return false; - + return true; } @@ -1130,9 +1130,7 @@ bool wxApp::Yield(bool onlyIfNeeded) } #endif // wxUSE_THREADS - static bool s_inYield = false; - - if (s_inYield) + if (m_isInsideYield) { if ( !onlyIfNeeded ) { @@ -1142,7 +1140,7 @@ bool wxApp::Yield(bool onlyIfNeeded) return false; } - s_inYield = true; + m_isInsideYield = true; #if wxUSE_LOG // disable log flushing from here because a call to wxYield() shouldn't @@ -1158,16 +1156,16 @@ bool wxApp::Yield(bool onlyIfNeeded) while ( loop->Pending() ) loop->Dispatch(); } - + // it's necessary to call ProcessIdle() to update the frames sizes which // might have been changed (it also will update other things set from // OnUpdateUI() which is a nice (and desired) side effect) while ( ProcessIdle() ) {} - + #if wxUSE_LOG wxLog::Resume(); #endif // wxUSE_LOG - s_inYield = false; + m_isInsideYield = false; return true; } @@ -1558,34 +1556,34 @@ void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymess { keyval = (keyval - '0') + WXK_NUMPAD0; } - else if (keycode >= 65 && keycode <= 81) + else if (keycode >= 65 && keycode <= 81) { switch (keycode) { case 76 : keyval = WXK_NUMPAD_ENTER; break; - + case 81: keyval = WXK_NUMPAD_EQUAL; break; - + case 67: keyval = WXK_NUMPAD_MULTIPLY; break; - + case 75: keyval = WXK_NUMPAD_DIVIDE; break; - + case 78: keyval = WXK_NUMPAD_SUBTRACT; break; - + case 69: keyval = WXK_NUMPAD_ADD; break; - + case 65: keyval = WXK_NUMPAD_DECIMAL; break; @@ -1594,7 +1592,7 @@ void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymess } } } - + event.m_shiftDown = modifiers & shiftKey; event.m_controlDown = modifiers & controlKey; event.m_altDown = modifiers & optionKey; @@ -1621,7 +1619,7 @@ void wxApp::MacHideApp() HICommand command; memset( &command, 0 , sizeof(command) ); command.commandID = kHICommandHide ; - event.SetParameter(kEventParamDirectObject, command ); + event.SetParameter(kEventParamDirectObject, command ); SendEventToApplication( event ); #endif } diff --git a/src/x11/app.cpp b/src/x11/app.cpp index 4c9868ce0c..772abba8c6 100644 --- a/src/x11/app.cpp +++ b/src/x11/app.cpp @@ -777,9 +777,7 @@ bool wxApp::Yield(bool onlyIfNeeded) int i; for (i = 0; i < 2; i++) { - static bool s_inYield = false; - - if ( s_inYield ) + if ( m_isInsideYield ) { if ( !onlyIfNeeded ) { @@ -789,11 +787,12 @@ bool wxApp::Yield(bool onlyIfNeeded) return false; } - s_inYield = true; + m_isInsideYield = true; // Make sure we have an event loop object, // or Pending/Dispatch will fail - wxEventLoopGuarantor dummyLoopIfNeeded; + wxEventLoopGuarantor dummyLoopIfNeeded; + // Call dispatch at least once so that sockets // can be tested wxTheApp->Dispatch(); @@ -806,7 +805,7 @@ bool wxApp::Yield(bool onlyIfNeeded) #endif ProcessIdle(); - s_inYield = false; + m_isInsideYield = false; } return true;