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 <tools/time.hxx>
23 #include <vcl/svapp.hxx>
24 #include <vcl/timer.hxx>
26 #include <saltimer.hxx>
28 #include <salinst.hxx>
31 // =======================================================================
33 #define MAX_TIMER_PERIOD ((sal_uLong)0xFFFFFFFF)
35 // ---------------------
36 // - TimeManager-Types -
37 // ---------------------
41 ImplTimerData
* mpNext
; // Pointer to the next Instance
42 Timer
* mpSVTimer
; // Pointer to SV Timer instance
43 sal_uLong mnUpdateTime
; // Last Update Time
44 sal_uLong mnTimerUpdate
; // TimerCallbackProcs on stack
45 bool mbDelete
; // Was timer deleted during Update()?
46 bool mbInTimeout
; // Are we in a timeout handler?
49 // =======================================================================
51 void Timer::ImplDeInitTimer()
53 ImplSVData
* pSVData
= ImplGetSVData();
54 ImplTimerData
* pTimerData
= pSVData
->mpFirstTimerData
;
60 ImplTimerData
* pTempTimerData
= pTimerData
;
61 if ( pTimerData
->mpSVTimer
)
63 pTimerData
->mpSVTimer
->mbActive
= sal_False
;
64 pTimerData
->mpSVTimer
->mpTimerData
= NULL
;
66 pTimerData
= pTimerData
->mpNext
;
67 delete pTempTimerData
;
71 pSVData
->mpFirstTimerData
= NULL
;
72 pSVData
->mnTimerPeriod
= 0;
73 delete pSVData
->mpSalTimer
;
74 pSVData
->mpSalTimer
= NULL
;
78 // -----------------------------------------------------------------------
80 static void ImplStartTimer( ImplSVData
* pSVData
, sal_uLong nMS
)
85 if ( nMS
!= pSVData
->mnTimerPeriod
)
87 pSVData
->mnTimerPeriod
= nMS
;
88 pSVData
->mpSalTimer
->Start( nMS
);
92 // -----------------------------------------------------------------------
94 void Timer::ImplTimerCallbackProc()
96 ImplSVData
* pSVData
= ImplGetSVData();
97 ImplTimerData
* pTimerData
;
98 ImplTimerData
* pPrevTimerData
;
99 sal_uLong nMinPeriod
= MAX_TIMER_PERIOD
;
100 sal_uLong nDeltaTime
;
101 sal_uLong nTime
= Time::GetSystemTicks();
103 if ( pSVData
->mbNoCallTimer
)
106 pSVData
->mnTimerUpdate
++;
107 pSVData
->mbNotAllTimerCalled
= sal_True
;
109 // find timer where the timer handler needs to be called
110 pTimerData
= pSVData
->mpFirstTimerData
;
113 // If the timer is not new, was not deleted, and if it is not in the timeout handler, then
114 // call the handler as soon as the time is up.
115 if ( (pTimerData
->mnTimerUpdate
< pSVData
->mnTimerUpdate
) &&
116 !pTimerData
->mbDelete
&& !pTimerData
->mbInTimeout
)
119 if ( (pTimerData
->mnUpdateTime
+pTimerData
->mpSVTimer
->mnTimeout
) <= nTime
)
121 // set new update time
122 pTimerData
->mnUpdateTime
= nTime
;
124 // if no AutoTimer than stop
125 if ( !pTimerData
->mpSVTimer
->mbAuto
)
127 pTimerData
->mpSVTimer
->mbActive
= sal_False
;
128 pTimerData
->mbDelete
= true;
132 pTimerData
->mbInTimeout
= true;
133 pTimerData
->mpSVTimer
->Timeout();
134 pTimerData
->mbInTimeout
= false;
138 pTimerData
= pTimerData
->mpNext
;
141 // determine new time
142 sal_uLong nNewTime
= Time::GetSystemTicks();
143 pPrevTimerData
= NULL
;
144 pTimerData
= pSVData
->mpFirstTimerData
;
147 // ignore if timer is still in timeout handler
148 if ( pTimerData
->mbInTimeout
)
150 pPrevTimerData
= pTimerData
;
151 pTimerData
= pTimerData
->mpNext
;
153 // Was timer destroyed in the meantime?
154 else if ( pTimerData
->mbDelete
)
156 if ( pPrevTimerData
)
157 pPrevTimerData
->mpNext
= pTimerData
->mpNext
;
159 pSVData
->mpFirstTimerData
= pTimerData
->mpNext
;
160 if ( pTimerData
->mpSVTimer
)
161 pTimerData
->mpSVTimer
->mpTimerData
= NULL
;
162 ImplTimerData
* pTempTimerData
= pTimerData
;
163 pTimerData
= pTimerData
->mpNext
;
164 delete pTempTimerData
;
168 pTimerData
->mnTimerUpdate
= 0;
169 // determine smallest time slot
170 if ( pTimerData
->mnUpdateTime
== nTime
)
172 nDeltaTime
= pTimerData
->mpSVTimer
->mnTimeout
;
173 if ( nDeltaTime
< nMinPeriod
)
174 nMinPeriod
= nDeltaTime
;
178 nDeltaTime
= pTimerData
->mnUpdateTime
+ pTimerData
->mpSVTimer
->mnTimeout
;
179 if ( nDeltaTime
< nNewTime
)
183 nDeltaTime
-= nNewTime
;
184 if ( nDeltaTime
< nMinPeriod
)
185 nMinPeriod
= nDeltaTime
;
188 pPrevTimerData
= pTimerData
;
189 pTimerData
= pTimerData
->mpNext
;
193 // delete clock if no more timers available
194 if ( !pSVData
->mpFirstTimerData
)
196 pSVData
->mpSalTimer
->Stop();
197 pSVData
->mnTimerPeriod
= MAX_TIMER_PERIOD
;
200 ImplStartTimer( pSVData
, nMinPeriod
);
202 pSVData
->mnTimerUpdate
--;
203 pSVData
->mbNotAllTimerCalled
= sal_False
;
206 // =======================================================================
213 mbActive
= sal_False
;
216 // -----------------------------------------------------------------------
218 Timer::Timer( const Timer
& rTimer
)
221 mnTimeout
= rTimer
.mnTimeout
;
223 mbActive
= sal_False
;
224 maTimeoutHdl
= rTimer
.maTimeoutHdl
;
226 if ( rTimer
.IsActive() )
230 // -----------------------------------------------------------------------
236 mpTimerData
->mbDelete
= true;
237 mpTimerData
->mpSVTimer
= NULL
;
241 // -----------------------------------------------------------------------
243 void Timer::Timeout()
245 maTimeoutHdl
.Call( this );
248 // -----------------------------------------------------------------------
250 void Timer::SetTimeout( sal_uLong nNewTimeout
)
252 mnTimeout
= nNewTimeout
;
254 // if timer is active then renew clock
257 ImplSVData
* pSVData
= ImplGetSVData();
258 if ( !pSVData
->mnTimerUpdate
&& (mnTimeout
< pSVData
->mnTimerPeriod
) )
259 ImplStartTimer( pSVData
, mnTimeout
);
263 // -----------------------------------------------------------------------
269 ImplSVData
* pSVData
= ImplGetSVData();
272 if ( !pSVData
->mpFirstTimerData
)
274 pSVData
->mnTimerPeriod
= MAX_TIMER_PERIOD
;
275 if( ! pSVData
->mpSalTimer
)
277 pSVData
->mpSalTimer
= pSVData
->mpDefInst
->CreateSalTimer();
278 pSVData
->mpSalTimer
->SetCallback( ImplTimerCallbackProc
);
282 // insert timer and start
283 mpTimerData
= new ImplTimerData
;
284 mpTimerData
->mpSVTimer
= this;
285 mpTimerData
->mnUpdateTime
= Time::GetSystemTicks();
286 mpTimerData
->mnTimerUpdate
= pSVData
->mnTimerUpdate
;
287 mpTimerData
->mbDelete
= false;
288 mpTimerData
->mbInTimeout
= false;
290 // insert last due to SFX!
291 ImplTimerData
* pPrev
= NULL
;
292 ImplTimerData
* pData
= pSVData
->mpFirstTimerData
;
296 pData
= pData
->mpNext
;
298 mpTimerData
->mpNext
= NULL
;
300 pPrev
->mpNext
= mpTimerData
;
302 pSVData
->mpFirstTimerData
= mpTimerData
;
304 if ( mnTimeout
< pSVData
->mnTimerPeriod
)
305 ImplStartTimer( pSVData
, mnTimeout
);
307 else if( !mpTimerData
->mpSVTimer
) // TODO: remove when guilty found
309 OSL_FAIL( "Timer::Start() on a destroyed Timer!" );
313 mpTimerData
->mnUpdateTime
= Time::GetSystemTicks();
314 mpTimerData
->mnTimerUpdate
= pSVData
->mnTimerUpdate
;
315 mpTimerData
->mbDelete
= false;
319 // -----------------------------------------------------------------------
323 mbActive
= sal_False
;
326 mpTimerData
->mbDelete
= true;
329 // -----------------------------------------------------------------------
331 Timer
& Timer::operator=( const Timer
& rTimer
)
336 mbActive
= sal_False
;
337 mnTimeout
= rTimer
.mnTimeout
;
338 maTimeoutHdl
= rTimer
.maTimeoutHdl
;
340 if ( rTimer
.IsActive() )
346 // =======================================================================
348 AutoTimer::AutoTimer()
353 // -----------------------------------------------------------------------
355 AutoTimer::AutoTimer( const AutoTimer
& rTimer
) : Timer( rTimer
)
360 // -----------------------------------------------------------------------
362 AutoTimer
& AutoTimer::operator=( const AutoTimer
& rTimer
)
364 Timer::operator=( rTimer
);
368 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */