diff --git a/include/wx/msw/app.h b/include/wx/msw/app.h index cbd4c09a46..6a8c8baf0d 100644 --- a/include/wx/msw/app.h +++ b/include/wx/msw/app.h @@ -103,6 +103,10 @@ public: // use it. static wxLayoutDirection MSWGetDefaultLayout(wxWindow* parent = NULL); + // Call ProcessPendingEvents() but only if we need to do it, i.e. there was + // a recent call to WakeUpIdle(). + void MSWProcessPendingEventsIfNeeded(); + protected: int m_printMode; // wxPRINT_WINDOWS, wxPRINT_POSTSCRIPT diff --git a/include/wx/msw/evtloopconsole.h b/include/wx/msw/evtloopconsole.h index 17df0a4e7a..87217bc64b 100644 --- a/include/wx/msw/evtloopconsole.h +++ b/include/wx/msw/evtloopconsole.h @@ -30,6 +30,10 @@ public: WXDWORD MSWWaitForThread(WXHANDLE hThread); #endif // wxUSE_THREADS + // Return true if wake up was requested and not handled yet, i.e. if + // m_heventWake is signaled. + bool MSWIsWakeUpRequested(); + protected: // get the next message from queue and return true or return false if we // got WM_QUIT or an error occurred diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 866078a53a..2c3d14273b 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -790,6 +790,16 @@ void wxApp::WakeUpIdle() evtLoop->WakeUp(); } +void wxApp::MSWProcessPendingEventsIfNeeded() +{ + // The cast below is safe as wxEventLoop derives from wxMSWEventLoopBase in + // both console and GUI applications. + wxMSWEventLoopBase * const evtLoop + = static_cast(wxEventLoop::GetActive()); + if ( evtLoop && evtLoop->MSWIsWakeUpRequested() ) + ProcessPendingEvents(); +} + // ---------------------------------------------------------------------------- // other wxApp event handlers // ---------------------------------------------------------------------------- diff --git a/src/msw/evtloopconsole.cpp b/src/msw/evtloopconsole.cpp index c0ba2716fa..869ea888fd 100644 --- a/src/msw/evtloopconsole.cpp +++ b/src/msw/evtloopconsole.cpp @@ -71,6 +71,11 @@ void wxMSWEventLoopBase::WakeUp() wxLogLastError(wxS("SetEvent(wake)")); } +bool wxMSWEventLoopBase::MSWIsWakeUpRequested() +{ + return ::WaitForSingleObject(m_heventWake, 0) == WAIT_OBJECT_0; +} + #if wxUSE_THREADS WXDWORD wxMSWEventLoopBase::MSWWaitForThread(WXHANDLE hThread) diff --git a/src/msw/window.cpp b/src/msw/window.cpp index ea92c52ed0..41e84b5559 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -7511,10 +7511,9 @@ bool wxWindowMSW::HandleHotKey(WXWPARAM wParam, WXLPARAM lParam) #endif // wxUSE_HOTKEY // this class installs a message hook which really wakes up our idle processing -// each time a WM_NULL is received (wxWakeUpIdle does this), even if we're -// sitting inside a local modal loop (e.g. a menu is opened or scrollbar is -// being dragged or even inside ::MessageBox()) and so don't control message -// dispatching otherwise +// each time a message is handled, even if we're sitting inside a local modal +// loop (e.g. a menu is opened or scrollbar is being dragged or even inside +// ::MessageBox()) and so don't control message dispatching otherwise class wxIdleWakeUpModule : public wxModule { public: @@ -7545,15 +7544,11 @@ public: static LRESULT CALLBACK MsgHookProc(int nCode, WPARAM wParam, LPARAM lParam) { - MSG *msg = (MSG*)lParam; - - // only process the message if it is actually going to be removed from - // the message queue, this prevents that the same event from being - // processed multiple times if now someone just called PeekMessage() - if ( msg->message == WM_NULL && wParam == PM_REMOVE ) - { - wxTheApp->ProcessPendingEvents(); - } + // Don't process idle events unless the message is going to be really + // handled, i.e. removed from the queue, as it seems wrong to do it + // just because someone called PeekMessage(PM_NOREMOVE). + if ( wParam == PM_REMOVE ) + wxTheApp->MSWProcessPendingEventsIfNeeded(); return CallNextHookEx(ms_hMsgHookProc, nCode, wParam, lParam); }