blob: 9163dffaf82196ba325016173f7393edc47bbfc0 [file] [log] [blame]
Alexandre Julliard401710d1993-09-04 10:09:32 +00001/*
2 * Timer functions
3 *
4 * Copyright 1993 Alexandre Julliard
5 */
6
Jeremy Whited3e22d92000-02-10 19:03:02 +00007#include "windef.h"
8#include "wingdi.h"
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +00009#include "wine/winuser16.h"
Marcus Meissner61afa331999-02-22 10:16:00 +000010#include "winuser.h"
Alexandre Julliard51ab43b2001-05-18 22:51:56 +000011#include "winerror.h"
12
Alexandre Julliardca22b331996-07-12 19:02:39 +000013#include "winproc.h"
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +000014#include "message.h"
Alexandre Julliard37e95032001-07-19 00:39:09 +000015#include "wine/server.h"
Alexandre Julliard359f497e1999-07-04 16:02:24 +000016#include "debugtools.h"
Alexandre Julliard401710d1993-09-04 10:09:32 +000017
Dimitrie O. Paun529da542000-11-27 23:54:25 +000018DEFAULT_DEBUG_CHANNEL(timer);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000019
Alexandre Julliard401710d1993-09-04 10:09:32 +000020
Alexandre Julliard5f721f81994-01-04 20:14:34 +000021typedef struct tagTIMER
Alexandre Julliard401710d1993-09-04 10:09:32 +000022{
Alexandre Julliarda3960291999-02-26 11:11:13 +000023 HWND hwnd;
Ulrich Weiganda9238081999-06-22 19:11:33 +000024 HQUEUE16 hq;
25 UINT16 msg; /* WM_TIMER or WM_SYSTIMER */
Alexandre Julliarda3960291999-02-26 11:11:13 +000026 UINT id;
27 UINT timeout;
Ulrich Weiganda9238081999-06-22 19:11:33 +000028 HWINDOWPROC proc;
Alexandre Julliard401710d1993-09-04 10:09:32 +000029} TIMER;
30
31#define NB_TIMERS 34
32#define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
33
Alexandre Julliard51ab43b2001-05-18 22:51:56 +000034#define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
Uwe Bonnes23cadd31999-09-04 14:32:27 +000035
Alexandre Julliard401710d1993-09-04 10:09:32 +000036static TIMER TimersArray[NB_TIMERS];
37
Alexandre Julliard227a0892000-04-08 21:06:06 +000038static CRITICAL_SECTION csTimer = CRITICAL_SECTION_INIT;
Stephane Lussier35ffc5d1999-03-25 13:23:26 +000039
40
41/***********************************************************************
Alexandre Julliardef702d81996-05-28 18:54:58 +000042 * TIMER_ClearTimer
43 *
44 * Clear and remove a timer.
45 */
46static void TIMER_ClearTimer( TIMER * pTimer )
47{
Alexandre Julliardef702d81996-05-28 18:54:58 +000048 pTimer->hwnd = 0;
49 pTimer->msg = 0;
50 pTimer->id = 0;
51 pTimer->timeout = 0;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +000052 WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER );
Alexandre Julliardef702d81996-05-28 18:54:58 +000053}
54
55
Alexandre Julliardc981d0b1996-03-31 16:40:13 +000056/***********************************************************************
Alexandre Julliardef702d81996-05-28 18:54:58 +000057 * TIMER_RemoveWindowTimers
58 *
59 * Remove all timers for a given window.
60 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000061void TIMER_RemoveWindowTimers( HWND hwnd )
Alexandre Julliardef702d81996-05-28 18:54:58 +000062{
63 int i;
64 TIMER *pTimer;
65
Stephane Lussier35ffc5d1999-03-25 13:23:26 +000066 EnterCriticalSection( &csTimer );
67
Alexandre Julliardef702d81996-05-28 18:54:58 +000068 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
69 if ((pTimer->hwnd == hwnd) && pTimer->timeout)
70 TIMER_ClearTimer( pTimer );
Alexandre Julliard51ab43b2001-05-18 22:51:56 +000071
Stephane Lussier35ffc5d1999-03-25 13:23:26 +000072 LeaveCriticalSection( &csTimer );
Alexandre Julliardef702d81996-05-28 18:54:58 +000073}
74
75
76/***********************************************************************
77 * TIMER_RemoveQueueTimers
78 *
79 * Remove all timers for a given queue.
80 */
Alexandre Julliardca22b331996-07-12 19:02:39 +000081void TIMER_RemoveQueueTimers( HQUEUE16 hqueue )
Alexandre Julliardef702d81996-05-28 18:54:58 +000082{
83 int i;
84 TIMER *pTimer;
85
Stephane Lussier35ffc5d1999-03-25 13:23:26 +000086 EnterCriticalSection( &csTimer );
87
Alexandre Julliardef702d81996-05-28 18:54:58 +000088 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
89 if ((pTimer->hq == hqueue) && pTimer->timeout)
90 TIMER_ClearTimer( pTimer );
Stephane Lussier35ffc5d1999-03-25 13:23:26 +000091
92 LeaveCriticalSection( &csTimer );
Alexandre Julliardef702d81996-05-28 18:54:58 +000093}
94
95
Alexandre Julliard5f721f81994-01-04 20:14:34 +000096/***********************************************************************
Alexandre Julliard401710d1993-09-04 10:09:32 +000097 * TIMER_SetTimer
98 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000099static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
100 WNDPROC16 proc, WINDOWPROCTYPE type, BOOL sys )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000101{
102 int i;
103 TIMER * pTimer;
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000104 HWINDOWPROC winproc = 0;
105
Gerard Patel22a04e12001-05-19 17:35:43 +0000106 if (hwnd && GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId())
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000107 {
108 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
109 return 0;
110 }
Alexandre Julliard5f721f81994-01-04 20:14:34 +0000111
Uwe Bonnes23cadd31999-09-04 14:32:27 +0000112 if (!timeout)
113 { /* timeout==0 is a legal argument UB 990821*/
114 WARN("Timeout== 0 not implemented, using timeout=1\n");
115 timeout=1;
116 }
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000117
Stephane Lussier35ffc5d1999-03-25 13:23:26 +0000118 EnterCriticalSection( &csTimer );
119
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000120 /* Check if there's already a timer with the same hwnd and id */
121
Alexandre Julliardaca05781994-10-17 18:12:41 +0000122 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
123 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
124 (pTimer->timeout != 0))
125 {
Ulrich Weiganda9238081999-06-22 19:11:33 +0000126 TIMER_ClearTimer( pTimer );
127 break;
Alexandre Julliardaca05781994-10-17 18:12:41 +0000128 }
Alexandre Julliard940d58c1994-09-16 09:24:37 +0000129
Ulrich Weiganda9238081999-06-22 19:11:33 +0000130 if ( i == NB_TIMERS )
Stephane Lussier35ffc5d1999-03-25 13:23:26 +0000131 {
Ulrich Weiganda9238081999-06-22 19:11:33 +0000132 /* Find a free timer */
Stephane Lussier35ffc5d1999-03-25 13:23:26 +0000133
Ulrich Weiganda9238081999-06-22 19:11:33 +0000134 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
135 if (!pTimer->timeout) break;
136
137 if ( (i >= NB_TIMERS) ||
138 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) )
139 {
140 LeaveCriticalSection( &csTimer );
141 return 0;
142 }
143 }
144
Alexandre Julliard401710d1993-09-04 10:09:32 +0000145 if (!hwnd) id = i + 1;
146
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000147 if (proc) WINPROC_SetProc( &winproc, proc, type, WIN_PROC_TIMER );
148
149 SERVER_START_REQ( set_win_timer )
150 {
151 req->win = hwnd;
152 req->msg = sys ? WM_SYSTIMER : WM_TIMER;
153 req->id = id;
154 req->rate = max( timeout, SYS_TIMER_RATE );
155 req->lparam = (unsigned int)winproc;
156 SERVER_CALL();
157 }
158 SERVER_END_REQ;
159
Alexandre Julliard401710d1993-09-04 10:09:32 +0000160 /* Add the timer */
161
162 pTimer->hwnd = hwnd;
Alexandre Julliard8afe6622001-07-26 20:12:22 +0000163 pTimer->hq = InitThreadInput16( 0, 0 );
Alexandre Julliard401710d1993-09-04 10:09:32 +0000164 pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
165 pTimer->id = id;
166 pTimer->timeout = timeout;
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000167 pTimer->proc = winproc;
Ulrich Weiganda9238081999-06-22 19:11:33 +0000168
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000169 TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
Alexandre Julliardca22b331996-07-12 19:02:39 +0000170 pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
171 (DWORD)pTimer->proc );
Ulrich Weiganda9238081999-06-22 19:11:33 +0000172
Stephane Lussier35ffc5d1999-03-25 13:23:26 +0000173 LeaveCriticalSection( &csTimer );
174
Alexandre Julliardca22b331996-07-12 19:02:39 +0000175 if (!id) return TRUE;
176 else return id;
Alexandre Julliard401710d1993-09-04 10:09:32 +0000177}
178
179
180/***********************************************************************
181 * TIMER_KillTimer
182 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000183static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000184{
185 int i;
186 TIMER * pTimer;
187
Alexandre Julliard51ab43b2001-05-18 22:51:56 +0000188 SERVER_START_REQ( kill_win_timer )
189 {
190 req->win = hwnd;
191 req->msg = sys ? WM_SYSTIMER : WM_TIMER;
192 req->id = id;
193 SERVER_CALL();
194 }
195 SERVER_END_REQ;
196
Stephane Lussier35ffc5d1999-03-25 13:23:26 +0000197 EnterCriticalSection( &csTimer );
198
Alexandre Julliardef702d81996-05-28 18:54:58 +0000199 /* Find the timer */
Alexandre Julliard401710d1993-09-04 10:09:32 +0000200
201 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
202 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
203 (pTimer->timeout != 0)) break;
Stephane Lussier35ffc5d1999-03-25 13:23:26 +0000204
205 if ( (i >= NB_TIMERS) ||
206 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ||
207 (!sys && (pTimer->msg != WM_TIMER)) ||
208 (sys && (pTimer->msg != WM_SYSTIMER)) )
209 {
210 LeaveCriticalSection( &csTimer );
211 return FALSE;
212 }
Alexandre Julliard401710d1993-09-04 10:09:32 +0000213
Alexandre Julliardef702d81996-05-28 18:54:58 +0000214 /* Delete the timer */
Alexandre Julliard401710d1993-09-04 10:09:32 +0000215
Alexandre Julliardef702d81996-05-28 18:54:58 +0000216 TIMER_ClearTimer( pTimer );
Stephane Lussier35ffc5d1999-03-25 13:23:26 +0000217
218 LeaveCriticalSection( &csTimer );
219
Alexandre Julliard401710d1993-09-04 10:09:32 +0000220 return TRUE;
221}
222
223
224/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000225 * SetTimer (USER.10)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000226 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000227UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
228 TIMERPROC16 proc )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000229{
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000230 TRACE("%04x %d %d %08lx\n",
Alexandre Julliardca22b331996-07-12 19:02:39 +0000231 hwnd, id, timeout, (LONG)proc );
232 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
233 WIN_PROC_16, FALSE );
Alexandre Julliard401710d1993-09-04 10:09:32 +0000234}
235
236
237/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000238 * SetTimer (USER32.@)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000239 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000240UINT WINAPI SetTimer( HWND hwnd, UINT id, UINT timeout,
241 TIMERPROC proc )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000242{
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000243 TRACE("%04x %d %d %08lx\n",
Alexandre Julliardca22b331996-07-12 19:02:39 +0000244 hwnd, id, timeout, (LONG)proc );
245 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
246 WIN_PROC_32A, FALSE );
Alexandre Julliard401710d1993-09-04 10:09:32 +0000247}
248
249
250/***********************************************************************
Stephane Lussier6bac4f22000-09-29 00:56:05 +0000251 * TIMER_IsTimerValid
252 */
253BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, HWINDOWPROC hProc )
254{
255 int i;
256 TIMER *pTimer;
257 BOOL ret = FALSE;
258
259 EnterCriticalSection( &csTimer );
260
261 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
262 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
263 (pTimer->proc == hProc))
264 {
265 ret = TRUE;
266 break;
267 }
268
269 LeaveCriticalSection( &csTimer );
270 return ret;
271}
272
273
274/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000275 * SetSystemTimer (USER.11)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000276 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000277UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
278 TIMERPROC16 proc )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000279{
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000280 TRACE("%04x %d %d %08lx\n",
Alexandre Julliardca22b331996-07-12 19:02:39 +0000281 hwnd, id, timeout, (LONG)proc );
282 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
283 WIN_PROC_16, TRUE );
284}
285
286
287/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000288 * SetSystemTimer (USER32.@)
Alexandre Julliardca22b331996-07-12 19:02:39 +0000289 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000290UINT WINAPI SetSystemTimer( HWND hwnd, UINT id, UINT timeout,
291 TIMERPROC proc )
Alexandre Julliardca22b331996-07-12 19:02:39 +0000292{
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000293 TRACE("%04x %d %d %08lx\n",
Alexandre Julliardca22b331996-07-12 19:02:39 +0000294 hwnd, id, timeout, (LONG)proc );
295 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
296 WIN_PROC_32A, TRUE );
297}
298
299
300/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000301 * KillTimer (USER.12)
Alexandre Julliardca22b331996-07-12 19:02:39 +0000302 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000303BOOL16 WINAPI KillTimer16( HWND16 hwnd, UINT16 id )
Alexandre Julliardca22b331996-07-12 19:02:39 +0000304{
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000305 TRACE("%04x %d\n", hwnd, id );
Alexandre Julliard401710d1993-09-04 10:09:32 +0000306 return TIMER_KillTimer( hwnd, id, FALSE );
307}
308
309
310/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000311 * KillTimer (USER32.@)
Alexandre Julliard401710d1993-09-04 10:09:32 +0000312 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000313BOOL WINAPI KillTimer( HWND hwnd, UINT id )
Alexandre Julliard401710d1993-09-04 10:09:32 +0000314{
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000315 TRACE("%04x %d\n", hwnd, id );
Alexandre Julliardca22b331996-07-12 19:02:39 +0000316 return TIMER_KillTimer( hwnd, id, FALSE );
317}
318
319
320/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000321 * KillSystemTimer (USER.182)
Alexandre Julliardca22b331996-07-12 19:02:39 +0000322 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000323BOOL16 WINAPI KillSystemTimer16( HWND16 hwnd, UINT16 id )
Alexandre Julliardca22b331996-07-12 19:02:39 +0000324{
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000325 TRACE("%04x %d\n", hwnd, id );
Alexandre Julliardca22b331996-07-12 19:02:39 +0000326 return TIMER_KillTimer( hwnd, id, TRUE );
327}
328
329
330/***********************************************************************
Patrik Stridvall2ece70e2000-12-22 01:38:01 +0000331 * KillSystemTimer (USER32.@)
Alexandre Julliardca22b331996-07-12 19:02:39 +0000332 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000333BOOL WINAPI KillSystemTimer( HWND hwnd, UINT id )
Alexandre Julliardca22b331996-07-12 19:02:39 +0000334{
Alexandre Julliard359f497e1999-07-04 16:02:24 +0000335 TRACE("%04x %d\n", hwnd, id );
Alexandre Julliard401710d1993-09-04 10:09:32 +0000336 return TIMER_KillTimer( hwnd, id, TRUE );
337}