cui/source/dialogs/cuigaldlg.cxx | 3 -- include/vcl/scheduler.hxx | 11 ++++++++- include/vcl/svapp.hxx | 14 ++++++----- svx/source/form/fmsrcimp.cxx | 39 ++++---------------------------- sw/source/ui/dbui/addresslistdialog.cxx | 3 -- sw/source/ui/dbui/mmresultdialogs.cxx | 9 ++----- sw/source/uibase/dbui/dbmgr.cxx | 19 ++++----------- vcl/headless/svpinst.cxx | 2 - vcl/inc/win/saltimer.h | 15 +++++------- vcl/osx/salinst.cxx | 3 +- vcl/source/app/svapp.cxx | 8 +++++- vcl/source/gdi/print2.cxx | 3 -- vcl/unx/kde4/KDEXLib.cxx | 3 -- vcl/unx/kde4/KDEXLib.hxx | 2 - vcl/win/app/salinst.cxx | 38 ++++++++++++++++++++----------- 15 files changed, 79 insertions(+), 93 deletions(-)
New commits: commit b9688ddf45e191de9eae7010a9011ba5118b6c7f Author: Jan-Marek Glogowski <[email protected]> AuthorDate: Mon Oct 2 09:23:38 2017 +0200 Commit: Thorsten Behrens <[email protected]> CommitDate: Wed Jan 16 19:31:58 2019 +0100 WIN handle timer Impl* access via friend function Not sure if this is the better approach, but this gives the application window dispatch function access to the now private timer implementation, so nobody else can call them. Change-Id: Ic361d2c93116fbd6c85b20f7da3cffbd538b3558 Reviewed-on: https://gerrit.libreoffice.org/43041 Tested-by: Jenkins <[email protected]> Reviewed-by: Jan-Marek Glogowski <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/66448 Reviewed-by: Thorsten Behrens <[email protected]> Tested-by: Thorsten Behrens <[email protected]> diff --git a/vcl/inc/win/saltimer.h b/vcl/inc/win/saltimer.h index 9107dd1a0b19..f87361e55ed8 100644 --- a/vcl/inc/win/saltimer.h +++ b/vcl/inc/win/saltimer.h @@ -24,10 +24,17 @@ class WinSalTimer : public SalTimer { + // for access to Impl* functions + friend LRESULT CALLBACK SalComWndProc( HWND, UINT nMsg, WPARAM wParam, LPARAM lParam, int& rDef ); + HANDLE m_nTimerId; ///< Windows timer id sal_uInt32 m_nTimerStartTicks; ///< system ticks at timer start % SAL_MAX_UINT32 bool m_bPollForMessage; ///< Run yield until a message is caught (most likely the 0ms timer) + void ImplStart( sal_uIntPtr nMS ); + void ImplStop(); + void ImplEmitTimerCallback(); + public: WinSalTimer(); virtual ~WinSalTimer() override; @@ -38,14 +45,6 @@ public: inline bool IsValidWPARAM( WPARAM wParam ) const; inline bool PollForMessage() const; - - // The Impl functions are just public to be called from the static - // SalComWndProc on main thread redirect! Otherwise they would be private. - // They must be called from the main application thread only! - - void ImplStart( sal_uIntPtr nMS ); - void ImplStop(); - void ImplEmitTimerCallback(); }; inline bool WinSalTimer::IsValidWPARAM( WPARAM aWPARAM ) const commit a7b5ae1126cce8da82b745853f118ad58a4c6b17 Author: Jan-Marek Glogowski <[email protected]> AuthorDate: Tue Aug 29 10:29:51 2017 +0200 Commit: Thorsten Behrens <[email protected]> CommitDate: Wed Jan 16 19:31:45 2019 +0100 tdf#112288 Clarify Reschedule implementations Application::Reschedule(true) must just process all currently pending events and ignore all new events generated while processing them. In contrast to Scheduler::ProcessEventsToIdle, this way it can't busy-lock the application with background jobs. This way we also can drop nMaxEvents from the Windows backend. This limit was also never implemented on OSX and for the KDE4 backend it's actually impossible to handle single events, and a call to QAbstractEventDispatcher::processEvents works like this. Also changes various call sites to just process all pending events instead of some made up number of times. Change-Id: I1ab95df89b079cc8c6319a808194fe3127144d1c Reviewed-on: https://gerrit.libreoffice.org/42659 Tested-by: Jenkins <[email protected]> Reviewed-by: Jan-Marek Glogowski <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/66447 Reviewed-by: Thorsten Behrens <[email protected]> Tested-by: Thorsten Behrens <[email protected]> diff --git a/cui/source/dialogs/cuigaldlg.cxx b/cui/source/dialogs/cuigaldlg.cxx index 36e95cf50845..04b453c1b23e 100644 --- a/cui/source/dialogs/cuigaldlg.cxx +++ b/cui/source/dialogs/cuigaldlg.cxx @@ -494,8 +494,7 @@ IMPL_LINK_TYPED( ActualizeProgress, TimeoutHdl, Timer*, _pTimer, void) IMPL_LINK_TYPED( ActualizeProgress, ActualizeHdl, const INetURLObject&, rURL, void ) { - for( long i = 0; i < 128; i++ ) - Application::Reschedule(); + Application::Reschedule( true ); Flush(); diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx index d23148a7fde3..7e3d566de0af 100644 --- a/include/vcl/scheduler.hxx +++ b/include/vcl/scheduler.hxx @@ -56,7 +56,16 @@ public: static void CallbackTaskScheduling(); /// Process one pending task ahead of time with highest priority. static bool ProcessTaskScheduling(); - /// Process all events until we are idle + /** + * Process all events until none is pending + * + * This can busy-lock, if some task or system event always generates new + * events when being processed. Most time it's called in unit tests to + * process all pending events. Internally it just calls + * Application::Reschedule( true ) until it fails. + * + * @see Application::Reschedule + */ static void ProcessEventsToIdle(); /** * Process events until the parameter turns true, diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx index 34b659fa7f33..431681e5f1c0 100644 --- a/include/vcl/svapp.hxx +++ b/include/vcl/svapp.hxx @@ -467,17 +467,19 @@ public: /** Attempt to process current pending event(s) It doesn't sleep if no events are available for processing. + This doesn't processs any events generated after invoking the function. + So in contrast to Scheduler::ProcessEventsToIdle, this cannot become + busy-locked by an event-generating event in the event queue. - @param bAllEvents If set to true, then try to process all the - events. If set to false, then only process the current - event. Defaults to false. + @param bHandleAllCurrentEvents If set to true, then try to process all + the current events. If set to false, then only process one event. + Defaults to false. @returns true if any event was processed. - @see Execute, Quit, Yield, EndYield, GetSolarMutex, - GetMainThreadIdentifier, ReleaseSolarMutex, AcquireSolarMutex, + @see Yield, Scheduler::ProcessEventsToIdle */ - static bool Reschedule( bool bAllEvents = false ); + static bool Reschedule( bool bHandleAllCurrentEvents = false ); /** Process the next event. diff --git a/svx/source/form/fmsrcimp.cxx b/svx/source/form/fmsrcimp.cxx index 5d0e72d9a80a..3a6ab77a5cea 100644 --- a/svx/source/form/fmsrcimp.cxx +++ b/svx/source/form/fmsrcimp.cxx @@ -405,18 +405,9 @@ FmSearchEngine::SEARCH_RESULT FmSearchEngine::SearchSpecial(bool _bSearchForNull bool bMovedAround(false); do { - if (m_eMode == SM_ALLOWSCHEDULE) - { - Application::Reschedule(); - Application::Reschedule(); - // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event - // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings - // or anything like that. So within each loop we create one user event and handle one user event (and no - // paintings and these), so the office seems to be frozen while searching. - // FS - 70226 - 02.12.99 - } + Application::Reschedule( true ); - // der aktuell zu vergleichende Inhalt + // the content to be compared currently iterFieldLoop->xContents->getString(); // needed for wasNull bFound = _bSearchForNull == bool(iterFieldLoop->xContents->wasNull()); if (bFound) @@ -472,18 +463,9 @@ FmSearchEngine::SEARCH_RESULT FmSearchEngine::SearchWildcard(const OUString& str bool bMovedAround(false); do { - if (m_eMode == SM_ALLOWSCHEDULE) - { - Application::Reschedule(); - Application::Reschedule(); - // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event - // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings - // or anything like that. So within each loop we create one user event and handle one user event (and no - // paintings and these), so the office seems to be frozen while searching. - // FS - 70226 - 02.12.99 - } + Application::Reschedule( true ); - // der aktuell zu vergleichende Inhalt + // the content to be compared currently OUString sCurrentCheck; if (m_bFormatter) sCurrentCheck = FormatField(nFieldPos); @@ -574,18 +556,9 @@ FmSearchEngine::SEARCH_RESULT FmSearchEngine::SearchRegularApprox(const OUString bool bMovedAround(false); do { - if (m_eMode == SM_ALLOWSCHEDULE) - { - Application::Reschedule(); - Application::Reschedule(); - // do 2 reschedules because of #70226# : some things done within this loop's body may cause an user event - // to be posted (deep within vcl), and these user events will be handled before any keyinput or paintings - // or anything like that. So within each loop we create one user event and handle one user event (and no - // paintings and these), so the office seems to be frozen while searching. - // FS - 70226 - 02.12.99 - } + Application::Reschedule( true ); - // der aktuell zu vergleichende Inhalt + // the content to be compared currently OUString sCurrentCheck; if (m_bFormatter) sCurrentCheck = FormatField(nFieldPos); diff --git a/sw/source/ui/dbui/addresslistdialog.cxx b/sw/source/ui/dbui/addresslistdialog.cxx index bef855f4010e..3c7b80ba21a6 100644 --- a/sw/source/ui/dbui/addresslistdialog.cxx +++ b/sw/source/ui/dbui/addresslistdialog.cxx @@ -487,8 +487,7 @@ IMPL_LINK_TYPED(SwAddressListDialog, StaticListBoxSelectHdl_Impl, void*, p, void m_pListLB->SetEntryText(m_sConnecting, pSelect, ITEMID_TABLE - 1); // allow painting of the new entry m_pListLB->Window::Invalidate(InvalidateFlags::Update); - for (int i = 0; i < 10; ++i) - Application::Reschedule(); + Application::Reschedule( true ); } pUserData = static_cast<AddressUserData_Impl*>(pSelect->GetUserData()); diff --git a/sw/source/ui/dbui/mmresultdialogs.cxx b/sw/source/ui/dbui/mmresultdialogs.cxx index 1c6218af3697..df46e8cef590 100644 --- a/sw/source/ui/dbui/mmresultdialogs.cxx +++ b/sw/source/ui/dbui/mmresultdialogs.cxx @@ -718,8 +718,7 @@ IMPL_LINK_TYPED(SwMMResultSaveDialog, SaveOutputHdl_Impl, Button*, pButton, void while(true) { //time for other slots is needed - for(sal_Int16 r = 0; r < 10; ++r) - Application::Reschedule(); + Application::Reschedule( true ); bool bFailed = false; try { @@ -1090,8 +1089,7 @@ IMPL_LINK_TYPED(SwMMResultEmailDialog, SendDocumentsHdl_Impl, Button*, pButton, //help to force painting the dialog //TODO/CLEANUP //predetermined breaking point - for ( sal_Int16 i = 0; i < 25; i++) - Application::Reschedule(); + Application::Reschedule( true ); for(sal_uInt32 nDoc = nBegin; nDoc < nEnd; ++nDoc) { SwDocMergeInfo& rInfo = pConfigItem->GetDocumentMergeInfo(nDoc); @@ -1234,8 +1232,7 @@ IMPL_LINK_TYPED(SwMMResultEmailDialog, SendDocumentsHdl_Impl, Button*, pButton, aDesc.sBCC = m_sBCC; pDlg->AddDocument( aDesc ); //help to force painting the dialog - for ( sal_Int16 i = 0; i < 25; i++) - Application::Reschedule(); + Application::Reschedule( true ); //stop creating of data when dialog has been closed if(!pDlg->IsVisible()) { diff --git a/sw/source/uibase/dbui/dbmgr.cxx b/sw/source/uibase/dbui/dbmgr.cxx index 5ab4d70aaa9d..7489ef1bd909 100644 --- a/sw/source/uibase/dbui/dbmgr.cxx +++ b/sw/source/uibase/dbui/dbmgr.cxx @@ -160,15 +160,6 @@ const sal_Char cActiveConnection[] = "ActiveConnection"; SfxGetpApp()->NotifyEvent(SfxEventHint(SW_EVENT_##type, \ SwDocShell::GetEventName(STR_SW_EVENT_##type), shell)) -namespace { - -void rescheduleGui() { - for( sal_uInt16 i = 0; i < 25; i++) - Application::Reschedule(); -} - -} - enum class SwDBNextRecord { NEXT, FIRST }; static bool lcl_ToNextRecord( SwDSParam* pParam, const SwDBNextRecord action = SwDBNextRecord::NEXT ); @@ -1234,7 +1225,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, pProgressDlg->SetCancelHdl( LINK(this, SwDBManager, PrtCancelHdl) ); pProgressDlg->Show(); - rescheduleGui(); + Application::Reschedule( true ); } if( bCreateSingleFile && !pTargetView ) @@ -1379,7 +1370,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, pProgressDlg->Update(); } - rescheduleGui(); + Application::Reschedule( true ); // Create a copy of the source document and work with that one instead of the source. // If we're not in the single file mode (which requires modifying the document for the merging), @@ -1549,7 +1540,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, } else if( IsMergeOk() ) // && bCreateSingleFile { - rescheduleGui(); + Application::Reschedule( true ); // sw::DocumentLayoutManager::CopyLayoutFormat() did not generate // unique fly names, do it here once. @@ -1565,7 +1556,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, aLayout->AllCheckPageDescs(); } - rescheduleGui(); + Application::Reschedule( true ); if( IsMergeOk() && bMT_FILE ) { @@ -1602,7 +1593,7 @@ bool SwDBManager::MergeMailFiles(SwWrtShell* pSourceShell, xTargetDocShell->DoClose(); } - rescheduleGui(); + Application::Reschedule( true ); pProgressDlg.disposeAndClear(); diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx index ef502f63e35e..d76ee1f1fe7f 100644 --- a/vcl/headless/svpinst.cxx +++ b/vcl/headless/svpinst.cxx @@ -173,7 +173,7 @@ bool SvpSalInstance::PostedEventsInQueue() bool result = false; { osl::MutexGuard g(m_aEventGuard); - result = m_aUserEvents.size() > 0; + result = !m_aUserEvents.empty(); } return result; } diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx index c38d1dd1e9e8..825c4a0849be 100644 --- a/vcl/osx/salinst.cxx +++ b/vcl/osx/salinst.cxx @@ -596,13 +596,14 @@ bool AquaSalInstance::DoYield(bool bWait, bool bHandleAllCurrentEvents, sal_uLon // handle available events NSEvent* pEvent = nil; + NSDate *now = [[NSDate alloc] init]; do { sal_uLong nCount = ReleaseYieldMutex(); // 'NSAnyEventMask' is deprecated: first deprecated in macOS 10.12 pEvent = [NSApp nextEventMatchingMask: NSAnyEventMask - untilDate: nil + untilDate: now inMode: NSDefaultRunLoopMode dequeue: YES]; diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 6af3c7c1c7cf..4a01e3f5aa61 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -512,6 +512,11 @@ bool Application::Reschedule( bool i_bAllEvents ) return ImplYield(false, i_bAllEvents, 0); } +void Scheduler::ProcessEventsToSignal(bool& bSignal) +{ + while (!bSignal && Application::Reschedule() ); +} + void Scheduler::ProcessEventsToIdle() { int nSanity = 1; @@ -545,7 +550,8 @@ void Scheduler::ProcessEventsToIdle() if ( pIdle && pIdle->IsActive() ) { bAnyIdle = true; - SAL_WARN( "vcl.schedule", "Unprocessed Idle: " << pIdle->GetDebugName() ); + SAL_WARN( "vcl.schedule", "Unprocessed Idle: " + << pIdle << " " << pIdle->GetDebugName() ); } } pSchedulerData = pSchedulerData->mpNext; diff --git a/vcl/source/gdi/print2.cxx b/vcl/source/gdi/print2.cxx index d7056bc897e8..28a2e69a9c41 100644 --- a/vcl/source/gdi/print2.cxx +++ b/vcl/source/gdi/print2.cxx @@ -1232,8 +1232,7 @@ bool OutputDevice::RemoveTransparenciesFromMetaFile( const GDIMetaFile& rInMtf, pCurrAct->Execute( aPaintVDev.get() ); } - if( !( nActionNum % 8 ) ) - Application::Reschedule(); + Application::Reschedule( true ); } const bool bOldMap = mbMap; diff --git a/vcl/unx/kde4/KDEXLib.cxx b/vcl/unx/kde4/KDEXLib.cxx index 528da8f511a0..2ad24272d55f 100644 --- a/vcl/unx/kde4/KDEXLib.cxx +++ b/vcl/unx/kde4/KDEXLib.cxx @@ -304,8 +304,7 @@ bool KDEXLib::Yield( bool bWait, bool bHandleAllCurrentEvents ) // (it's ok to release it here, since even normal processYield() would // temporarily do it while checking for new events) SalYieldMutexReleaser aReleaser; - Q_EMIT processYieldSignal( bWait, bHandleAllCurrentEvents ); - return false; + return Q_EMIT processYieldSignal( bWait, bHandleAllCurrentEvents ); } } diff --git a/vcl/unx/kde4/KDEXLib.hxx b/vcl/unx/kde4/KDEXLib.hxx index 246a9382b776..06ffb1c0c228 100644 --- a/vcl/unx/kde4/KDEXLib.hxx +++ b/vcl/unx/kde4/KDEXLib.hxx @@ -69,7 +69,7 @@ class KDEXLib : public QObject, public SalXLib Q_SIGNALS: void startTimeoutTimerSignal(); - void processYieldSignal( bool bWait, bool bHandleAllCurrentEvents ); + bool processYieldSignal( bool bWait, bool bHandleAllCurrentEvents ); css::uno::Reference< css::ui::dialogs::XFilePicker2 > createFilePickerSignal( const css::uno::Reference< css::uno::XComponentContext >& ); int getFrameWidthSignal(); diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index 707df7cc9aa5..7d5bdde80f75 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -578,12 +578,17 @@ static void ImplSalDispatchMessage( MSG* pMsg ) bool ImplSalYield( bool bWait, bool bHandleAllCurrentEvents ) { + static sal_uInt32 nLastTicks = 0; MSG aMsg; bool bWasMsg = false, bOneEvent = false; ImplSVData *const pSVData = ImplGetSVData(); WinSalTimer* pTimer = static_cast<WinSalTimer*>( pSVData->maSchedCtx.mpSalTimer ); - int nMaxEvents = bHandleAllCurrentEvents ? 100 : 1; + sal_uInt32 nCurTicks = 0; + if ( bHandleAllCurrentEvents ) + nCurTicks = GetTickCount(); + + bool bHadNewerEvent = false; do { bOneEvent = PeekMessageW( &aMsg, nullptr, 0, 0, PM_REMOVE ); @@ -592,20 +597,26 @@ ImplSalYield( bool bWait, bool bHandleAllCurrentEvents ) bWasMsg = true; TranslateMessage( &aMsg ); ImplSalDispatchMessage( &aMsg ); + if ( bHandleAllCurrentEvents + && !bHadNewerEvent && aMsg.time > nCurTicks + && (nLastTicks <= nCurTicks || aMsg.time < nLastTicks) ) + bHadNewerEvent = true; + bOneEvent = !bHadNewerEvent; } - else - // busy loop to catch the 0ms timeout - // We don't need to busy loop, if we wait anyway. - // Even if we didn't process the event directly, report it. - if ( pTimer && pTimer->PollForMessage() && !bWait ) - { - SwitchToThread(); - nMaxEvents++; - bOneEvent = true; - bWasMsg = true; - } + // busy loop to catch a message, eventually the 0ms timer. + // we don't need to loop, if we wait anyway. + if ( !bWait && !bWasMsg && pTimer && pTimer->PollForMessage() ) + { + SwitchToThread(); + continue; + } + if ( !(bHandleAllCurrentEvents && bOneEvent) ) + break; } - while( --nMaxEvents && bOneEvent ); + while( true ); + + if ( bHandleAllCurrentEvents ) + nLastTicks = nCurTicks; // Also check that we don't wait when application already has quit if ( bWait && !bWasMsg && !pSVData->maAppData.mbAppQuit ) @@ -617,6 +628,7 @@ ImplSalYield( bool bWait, bool bHandleAllCurrentEvents ) ImplSalDispatchMessage( &aMsg ); } } + return bWasMsg; } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
