diff options
author | Jan Holesovsky <kendy@collabora.com> | 2014-09-25 16:30:05 +0200 |
---|---|---|
committer | Jan Holesovsky <kendy@collabora.com> | 2014-09-25 21:57:37 +0200 |
commit | d68ce6e173502e1b1ce214503f41729a8502cd92 (patch) | |
tree | 92565f97630910f1678e3eab2b465392884ca2ab /vcl | |
parent | c1f8437dbed0e8b989e41a345ef7e658a6e8a4cd (diff) |
fdo#84000: Sort out problems with short timeouts & long callbacks.
Previously, the timer events could have accumulated in that scenario leading
to unresponsiveness to user events.
Change-Id: I455d726ae7475f7dbf98d871c54d8c156cb64e52
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/win/saldata.hxx | 2 | ||||
-rw-r--r-- | vcl/win/source/app/salinst.cxx | 17 | ||||
-rw-r--r-- | vcl/win/source/app/saltimer.cxx | 27 |
3 files changed, 31 insertions, 15 deletions
diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx index a50e67df1954..e1ae8cc06ff2 100644 --- a/vcl/inc/win/saldata.hxx +++ b/vcl/inc/win/saldata.hxx @@ -180,7 +180,7 @@ void ImplSalAcquireYieldMutex( sal_uLong nCount ); LRESULT CALLBACK SalFrameWndProcW( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam ); -void EmitTimerCallback(bool bAllowRecursive); +void EmitTimerCallback(); void SalTestMouseLeave(); bool ImplWriteLastError( DWORD lastError, const char *szApiCall ); diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx index 57dfc2801fbd..b1d33e498792 100644 --- a/vcl/win/source/app/salinst.cxx +++ b/vcl/win/source/app/salinst.cxx @@ -345,7 +345,6 @@ SalData::SalData() mnNextTimerTime = 0; mnLastEventTime = 0; mnTimerId = 0; // windows timer id - mbInTimerProc = FALSE; // timer event is currently being dispatched mhSalObjMsgHook = 0; // hook to get interesting msg for SalObject mhWantLeaveMsg = 0; // window handle, that want a MOUSELEAVE message mpMouseLeaveTimer = 0; // Timer for MouseLeave Test @@ -731,10 +730,22 @@ LRESULT CALLBACK SalComWndProc( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lPar rDef = FALSE; break; case SAL_MSG_POSTTIMER: - EmitTimerCallback(/*bAllowRecursive = */ true); + EmitTimerCallback(); break; case SAL_MSG_TIMER_CALLBACK: - EmitTimerCallback(/*bAllowRecursive = */ false); + EmitTimerCallback(); + MSG aMsg; + while (PeekMessageW(&aMsg, 0, SAL_MSG_TIMER_CALLBACK, SAL_MSG_TIMER_CALLBACK, PM_REMOVE)) + { + // nothing; just remove all the SAL_MSG_TIMER_CALLBACKs that + // accumulated in the queue during the EmitTimerCallback(), + // otherwise it happens with short timeouts and long callbacks + // that no other events will ever be processed, as the queue + // is full of SAL_MSG_TIMER_CALLBACKs. + // It is impossible to limit the amount of them being emited + // in the first place, as they are emited asynchronously, but + // here we are already fully synchronized. + } break; } diff --git a/vcl/win/source/app/saltimer.cxx b/vcl/win/source/app/saltimer.cxx index 9191d5e5619a..e1ce31e7be76 100644 --- a/vcl/win/source/app/saltimer.cxx +++ b/vcl/win/source/app/saltimer.cxx @@ -54,9 +54,11 @@ void ImplSalStartTimer( sal_uLong nMS, bool bMutex ) if (nMS > MAX_SYSPERIOD) nMS = MAX_SYSPERIOD; - // can't change a one-shot timer if it has fired already (odd) so delete & re-create - ImplSalStopTimer(pSalData); - CreateTimerQueueTimer(&pSalData->mnTimerId, NULL, SalTimerProc, NULL, nMS, nMS, WT_EXECUTEDEFAULT); + // change if it exists, create if not + if (pSalData->mnTimerId) + ChangeTimerQueueTimer(NULL, pSalData->mnTimerId, nMS, nMS); + else + CreateTimerQueueTimer(&pSalData->mnTimerId, NULL, SalTimerProc, NULL, nMS, nMS, WT_EXECUTEDEFAULT); pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS; } @@ -111,6 +113,10 @@ void CALLBACK SalTimerProc(PVOID, BOOLEAN) #endif SalData* pSalData = GetSalData(); + + // always post message when the timer fires, we will remove the ones + // that happened during execution of the callback later directly from + // the message queue PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK, 0, 0); #if defined ( __MINGW32__ ) && !defined ( _WIN64 ) @@ -128,11 +134,8 @@ void CALLBACK SalTimerProc(PVOID, BOOLEAN) We assured that by posting the message from the SalTimeProc only, the real call then happens when the main thread gets SAL_MSG_TIMER_CALLBACK. - -@param bAllowRecursive allows to skip the check that assures that two timeouts -do not overlap. */ -void EmitTimerCallback(bool bAllowRecursive) +void EmitTimerCallback() { SalData* pSalData = GetSalData(); ImplSVData* pSVData = ImplGetSVData(); @@ -142,13 +145,15 @@ void EmitTimerCallback(bool bAllowRecursive) // Try to acquire the mutex. If we don't get the mutex then we // try this a short time later again. - if (ImplSalYieldMutexTryToAcquire() && - (pSVData->mpSalTimer && (!pSalData->mbInTimerProc || bAllowRecursive))) + if (pSVData->mpSalTimer && ImplSalYieldMutexTryToAcquire()) { - pSalData->mbInTimerProc = true; pSVData->mpSalTimer->CallCallback(); - pSalData->mbInTimerProc = false; ImplSalYieldMutexRelease(); + + // Run the timer in the correct time, if we started this + // with a small timeout, because we didn't get the mutex + if (pSalData->mnTimerId && (pSalData->mnTimerMS != pSalData->mnTimerOrgMS)) + ImplSalStartTimer(pSalData->mnTimerOrgMS, false); } else { |