summaryrefslogtreecommitdiff
path: root/vcl/win/app/saltimer.cxx
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2015-12-02 09:34:23 +0200
committerTor Lillqvist <tml@collabora.com>2015-12-02 09:50:31 +0200
commit34cf91de3d0d6455004bacda399351101789d751 (patch)
treea30186df2a26fb8798f736f75241c641cf81abdc /vcl/win/app/saltimer.cxx
parenta6aa29db423a0f728e27a2219c3c411bf739fe3c (diff)
Get rid of a superfluous directory level
Change-Id: I79e065f0c68b149d2ef69f428d31e36e97a6098b
Diffstat (limited to 'vcl/win/app/saltimer.cxx')
-rw-r--r--vcl/win/app/saltimer.cxx172
1 files changed, 172 insertions, 0 deletions
diff --git a/vcl/win/app/saltimer.cxx b/vcl/win/app/saltimer.cxx
new file mode 100644
index 000000000000..c6f04be986fe
--- /dev/null
+++ b/vcl/win/app/saltimer.cxx
@@ -0,0 +1,172 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svsys.h>
+#include <win/saldata.hxx>
+#include <win/saltimer.h>
+#include <win/salinst.h>
+
+#if defined ( __MINGW32__ )
+#include <sehandler.hxx>
+#endif
+
+// maximum period
+#define MAX_SYSPERIOD 65533
+
+void CALLBACK SalTimerProc(PVOID pParameter, BOOLEAN bTimerOrWaitFired);
+
+// See http://msdn.microsoft.com/en-us/library/windows/desktop/ms687003%28v=vs.85%29.aspx
+// (and related pages) for details about the Timer Queues.
+
+void ImplSalStopTimer(SalData* pSalData)
+{
+ HANDLE hTimer = pSalData->mnTimerId;
+ pSalData->mnTimerId = 0;
+ DeleteTimerQueueTimer(NULL, hTimer, INVALID_HANDLE_VALUE);
+ MSG aMsg;
+ while (PeekMessageW(&aMsg, 0, SAL_MSG_TIMER_CALLBACK, SAL_MSG_TIMER_CALLBACK, PM_REMOVE))
+ {
+ // just remove all the SAL_MSG_TIMER_CALLBACKs
+ // when the application end, this SAL_MSG_TIMER_CALLBACK start the timer again
+ // and then crashed in "SalTimerProc" when the object "SalData" was deleted
+ }
+}
+
+void ImplSalStartTimer( sal_uLong nMS, bool bMutex )
+{
+ SalData* pSalData = GetSalData();
+
+ // Remember the time of the timer
+ pSalData->mnTimerMS = nMS;
+ if (!bMutex)
+ pSalData->mnTimerOrgMS = nMS;
+
+ // duration has to fit into Window's sal_uInt16
+ if (nMS > MAX_SYSPERIOD)
+ nMS = MAX_SYSPERIOD;
+
+ // 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_EXECUTEINTIMERTHREAD);
+
+ pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS;
+}
+
+WinSalTimer::~WinSalTimer()
+{
+}
+
+void WinSalTimer::Start( sal_uLong nMS )
+{
+ // switch to main thread
+ SalData* pSalData = GetSalData();
+ if ( pSalData->mpFirstInstance )
+ {
+ if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
+ PostMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
+ else
+ SendMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
+ }
+ else
+ ImplSalStartTimer( nMS, FALSE );
+}
+
+void WinSalTimer::Stop()
+{
+ SalData* pSalData = GetSalData();
+
+ // If we have a timer, than
+ if ( pSalData->mnTimerId )
+ {
+ ImplSalStopTimer(pSalData);
+ pSalData->mnNextTimerTime = 0;
+ }
+}
+
+/** This gets invoked from a Timer Queue thread.
+
+Don't acquire the SolarMutex to avoid deadlocks, just wake up the main thread
+at better resolution than 10ms.
+*/
+void CALLBACK SalTimerProc(PVOID, BOOLEAN)
+{
+#if defined ( __MINGW32__ ) && !defined ( _WIN64 )
+ jmp_buf jmpbuf;
+ __SEHandler han;
+ if (__builtin_setjmp(jmpbuf) == 0)
+ {
+ han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
+#else
+ __try
+ {
+#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 )
+ }
+ han.Reset();
+#else
+ }
+ __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
+ {
+ }
+#endif
+}
+
+/** Called in the main thread.
+
+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.
+*/
+void EmitTimerCallback()
+{
+ SalData* pSalData = GetSalData();
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // Test for MouseLeave
+ SalTestMouseLeave();
+
+ // Try to acquire the mutex. If we don't get the mutex then we
+ // try this a short time later again.
+ if (pSVData->mpSalTimer && ImplSalYieldMutexTryToAcquire())
+ {
+ bool idle = true; // TODO
+ pSVData->mpSalTimer->CallCallback( idle );
+ 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
+ {
+ ImplSalStartTimer(10, true);
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */