Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / win / source / app / saltimer.cxx
blobc6f04be986fefbe4cf4050b82acfb7f441d1f0dc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svsys.h>
21 #include <win/saldata.hxx>
22 #include <win/saltimer.h>
23 #include <win/salinst.h>
25 #if defined ( __MINGW32__ )
26 #include <sehandler.hxx>
27 #endif
29 // maximum period
30 #define MAX_SYSPERIOD 65533
32 void CALLBACK SalTimerProc(PVOID pParameter, BOOLEAN bTimerOrWaitFired);
34 // See http://msdn.microsoft.com/en-us/library/windows/desktop/ms687003%28v=vs.85%29.aspx
35 // (and related pages) for details about the Timer Queues.
37 void ImplSalStopTimer(SalData* pSalData)
39 HANDLE hTimer = pSalData->mnTimerId;
40 pSalData->mnTimerId = 0;
41 DeleteTimerQueueTimer(NULL, hTimer, INVALID_HANDLE_VALUE);
42 MSG aMsg;
43 while (PeekMessageW(&aMsg, 0, SAL_MSG_TIMER_CALLBACK, SAL_MSG_TIMER_CALLBACK, PM_REMOVE))
45 // just remove all the SAL_MSG_TIMER_CALLBACKs
46 // when the application end, this SAL_MSG_TIMER_CALLBACK start the timer again
47 // and then crashed in "SalTimerProc" when the object "SalData" was deleted
51 void ImplSalStartTimer( sal_uLong nMS, bool bMutex )
53 SalData* pSalData = GetSalData();
55 // Remember the time of the timer
56 pSalData->mnTimerMS = nMS;
57 if (!bMutex)
58 pSalData->mnTimerOrgMS = nMS;
60 // duration has to fit into Window's sal_uInt16
61 if (nMS > MAX_SYSPERIOD)
62 nMS = MAX_SYSPERIOD;
64 // change if it exists, create if not
65 if (pSalData->mnTimerId)
66 ChangeTimerQueueTimer(NULL, pSalData->mnTimerId, nMS, nMS);
67 else
68 CreateTimerQueueTimer(&pSalData->mnTimerId, NULL, SalTimerProc, NULL, nMS, nMS, WT_EXECUTEINTIMERTHREAD);
70 pSalData->mnNextTimerTime = pSalData->mnLastEventTime + nMS;
73 WinSalTimer::~WinSalTimer()
77 void WinSalTimer::Start( sal_uLong nMS )
79 // switch to main thread
80 SalData* pSalData = GetSalData();
81 if ( pSalData->mpFirstInstance )
83 if ( pSalData->mnAppThreadId != GetCurrentThreadId() )
84 PostMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
85 else
86 SendMessageW( pSalData->mpFirstInstance->mhComWnd, SAL_MSG_STARTTIMER, 0, (LPARAM)nMS );
88 else
89 ImplSalStartTimer( nMS, FALSE );
92 void WinSalTimer::Stop()
94 SalData* pSalData = GetSalData();
96 // If we have a timer, than
97 if ( pSalData->mnTimerId )
99 ImplSalStopTimer(pSalData);
100 pSalData->mnNextTimerTime = 0;
104 /** This gets invoked from a Timer Queue thread.
106 Don't acquire the SolarMutex to avoid deadlocks, just wake up the main thread
107 at better resolution than 10ms.
109 void CALLBACK SalTimerProc(PVOID, BOOLEAN)
111 #if defined ( __MINGW32__ ) && !defined ( _WIN64 )
112 jmp_buf jmpbuf;
113 __SEHandler han;
114 if (__builtin_setjmp(jmpbuf) == 0)
116 han.Set(jmpbuf, NULL, (__SEHandler::PF)EXCEPTION_EXECUTE_HANDLER);
117 #else
118 __try
120 #endif
122 SalData* pSalData = GetSalData();
124 // always post message when the timer fires, we will remove the ones
125 // that happened during execution of the callback later directly from
126 // the message queue
127 PostMessageW(pSalData->mpFirstInstance->mhComWnd, SAL_MSG_TIMER_CALLBACK, 0, 0);
129 #if defined ( __MINGW32__ ) && !defined ( _WIN64 )
131 han.Reset();
132 #else
134 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
137 #endif
140 /** Called in the main thread.
142 We assured that by posting the message from the SalTimeProc only, the real
143 call then happens when the main thread gets SAL_MSG_TIMER_CALLBACK.
145 void EmitTimerCallback()
147 SalData* pSalData = GetSalData();
148 ImplSVData* pSVData = ImplGetSVData();
150 // Test for MouseLeave
151 SalTestMouseLeave();
153 // Try to acquire the mutex. If we don't get the mutex then we
154 // try this a short time later again.
155 if (pSVData->mpSalTimer && ImplSalYieldMutexTryToAcquire())
157 bool idle = true; // TODO
158 pSVData->mpSalTimer->CallCallback( idle );
159 ImplSalYieldMutexRelease();
161 // Run the timer in the correct time, if we started this
162 // with a small timeout, because we didn't get the mutex
163 if (pSalData->mnTimerId && (pSalData->mnTimerMS != pSalData->mnTimerOrgMS))
164 ImplSalStartTimer(pSalData->mnTimerOrgMS, false);
166 else
168 ImplSalStartTimer(10, true);
172 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */