summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorJan Holesovsky <kendy@collabora.com>2014-09-25 16:30:05 +0200
committerJan Holesovsky <kendy@collabora.com>2014-09-25 21:57:37 +0200
commitd68ce6e173502e1b1ce214503f41729a8502cd92 (patch)
tree92565f97630910f1678e3eab2b465392884ca2ab /vcl
parentc1f8437dbed0e8b989e41a345ef7e658a6e8a4cd (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.hxx2
-rw-r--r--vcl/win/source/app/salinst.cxx17
-rw-r--r--vcl/win/source/app/saltimer.cxx27
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
{