tools/source/datetime/ttime.cxx | 13 ++++++------- vcl/inc/win/saldata.hxx | 2 +- vcl/win/source/app/salinst.cxx | 17 ++++++++++++++--- vcl/win/source/app/saltimer.cxx | 27 ++++++++++++++++----------- 4 files changed, 37 insertions(+), 22 deletions(-)
New commits: commit d68ce6e173502e1b1ce214503f41729a8502cd92 Author: Jan Holesovsky <ke...@collabora.com> Date: Thu Sep 25 16:30:05 2014 +0200 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 diff --git a/tools/source/datetime/ttime.cxx b/tools/source/datetime/ttime.cxx index 71836e7..66d16b4 100644 --- a/tools/source/datetime/ttime.cxx +++ b/tools/source/datetime/ttime.cxx @@ -400,19 +400,18 @@ Time Time::GetUTCOffset() sal_uIntPtr Time::GetSystemTicks() { #if defined WNT - static LARGE_INTEGER nTicksPerMS; - static bool bTicksPerMSInitialized = false; - if (!bTicksPerMSInitialized) + static LARGE_INTEGER nTicksPerSecond; + static bool bTicksPerSecondInitialized = false; + if (!bTicksPerSecondInitialized) { - QueryPerformanceFrequency(&nTicksPerMS); - nTicksPerMS.QuadPart /= 1000; - bTicksPerMSInitialized = true; + QueryPerformanceFrequency(&nTicksPerSecond); + bTicksPerSecondInitialized = true; } LARGE_INTEGER nPerformanceCount; QueryPerformanceCounter(&nPerformanceCount); - return (sal_uIntPtr)(nPerformanceCount.QuadPart/nTicksPerMS.QuadPart); + return (sal_uIntPtr)((nPerformanceCount.QuadPart*1000)/nTicksPerSecond.QuadPart); #else timeval tv; gettimeofday (&tv, 0); diff --git a/vcl/inc/win/saldata.hxx b/vcl/inc/win/saldata.hxx index a50e67d..e1ae8cc 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 57dfc28..b1d33e4 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 9191d5e..e1ce31e 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 { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits