1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <win/saldata.hxx>
22 #include <win/saltimer.h>
23 #include <win/salinst.h>
25 #if defined ( __MINGW32__ )
26 #include <sehandler.hxx>
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
);
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
;
58 pSalData
->mnTimerOrgMS
= nMS
;
60 // duration has to fit into Window's sal_uInt16
61 if (nMS
> MAX_SYSPERIOD
)
64 // change if it exists, create if not
65 if (pSalData
->mnTimerId
)
66 ChangeTimerQueueTimer(NULL
, pSalData
->mnTimerId
, nMS
, nMS
);
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
);
86 SendMessageW( pSalData
->mpFirstInstance
->mhComWnd
, SAL_MSG_STARTTIMER
, 0, (LPARAM
)nMS
);
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 )
114 if (__builtin_setjmp(jmpbuf
) == 0)
116 han
.Set(jmpbuf
, NULL
, (__SEHandler::PF
)EXCEPTION_EXECUTE_HANDLER
);
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
127 PostMessageW(pSalData
->mpFirstInstance
->mhComWnd
, SAL_MSG_TIMER_CALLBACK
, 0, 0);
129 #if defined ( __MINGW32__ ) && !defined ( _WIN64 )
134 __except(WinSalInstance::WorkaroundExceptionHandlingInUSER32Lib(GetExceptionCode(), GetExceptionInformation()))
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
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);
168 ImplSalStartTimer(10, true);
172 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */