4 * Copyright 1993 Alexandre Julliard
9 #include "wine/winuser16.h"
15 #include "wine/server.h"
16 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(timer);
21 typedef struct tagTIMER
25 UINT16 msg; /* WM_TIMER or WM_SYSTIMER */
32 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
34 #define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
36 static TIMER TimersArray[NB_TIMERS];
38 static CRITICAL_SECTION csTimer = CRITICAL_SECTION_INIT("csTimer");
41 /***********************************************************************
44 * Clear and remove a timer.
46 static void TIMER_ClearTimer( TIMER * pTimer )
52 WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER );
56 /***********************************************************************
57 * TIMER_RemoveWindowTimers
59 * Remove all timers for a given window.
61 void TIMER_RemoveWindowTimers( HWND hwnd )
66 EnterCriticalSection( &csTimer );
68 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
69 if ((pTimer->hwnd == hwnd) && pTimer->timeout)
70 TIMER_ClearTimer( pTimer );
72 LeaveCriticalSection( &csTimer );
76 /***********************************************************************
77 * TIMER_RemoveQueueTimers
79 * Remove all timers for a given queue.
81 void TIMER_RemoveQueueTimers( HQUEUE16 hqueue )
86 EnterCriticalSection( &csTimer );
88 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
89 if ((pTimer->hq == hqueue) && pTimer->timeout)
90 TIMER_ClearTimer( pTimer );
92 LeaveCriticalSection( &csTimer );
96 /***********************************************************************
99 static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
100 WNDPROC16 proc, WINDOWPROCTYPE type, BOOL sys )
104 HWINDOWPROC winproc = 0;
106 if (hwnd && GetWindowThreadProcessId( hwnd, NULL ) != GetCurrentThreadId())
108 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
113 { /* timeout==0 is a legal argument UB 990821*/
114 WARN("Timeout== 0 not implemented, using timeout=1\n");
118 EnterCriticalSection( &csTimer );
120 /* Check if there's already a timer with the same hwnd and id */
122 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
123 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
124 (pTimer->timeout != 0))
126 TIMER_ClearTimer( pTimer );
130 if ( i == NB_TIMERS )
132 /* Find a free timer */
134 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
135 if (!pTimer->timeout) break;
137 if ( (i >= NB_TIMERS) ||
138 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) )
140 LeaveCriticalSection( &csTimer );
145 if (!hwnd) id = i + 1;
147 if (proc) WINPROC_SetProc( &winproc, proc, type, WIN_PROC_TIMER );
149 SERVER_START_REQ( set_win_timer )
152 req->msg = sys ? WM_SYSTIMER : WM_TIMER;
154 req->rate = max( timeout, SYS_TIMER_RATE );
155 req->lparam = (unsigned int)winproc;
163 pTimer->hq = InitThreadInput16( 0, 0 );
164 pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
166 pTimer->timeout = timeout;
167 pTimer->proc = winproc;
169 TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
170 pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
171 (DWORD)pTimer->proc );
173 LeaveCriticalSection( &csTimer );
175 if (!id) return TRUE;
180 /***********************************************************************
183 static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
188 SERVER_START_REQ( kill_win_timer )
191 req->msg = sys ? WM_SYSTIMER : WM_TIMER;
197 EnterCriticalSection( &csTimer );
201 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
202 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
203 (pTimer->timeout != 0)) break;
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)) )
210 LeaveCriticalSection( &csTimer );
214 /* Delete the timer */
216 TIMER_ClearTimer( pTimer );
218 LeaveCriticalSection( &csTimer );
224 /***********************************************************************
227 UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
230 TRACE("%04x %d %d %08lx\n",
231 hwnd, id, timeout, (LONG)proc );
232 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
233 WIN_PROC_16, FALSE );
237 /***********************************************************************
238 * SetTimer (USER32.@)
240 UINT WINAPI SetTimer( HWND hwnd, UINT id, UINT timeout,
243 TRACE("%04x %d %d %08lx\n",
244 hwnd, id, timeout, (LONG)proc );
245 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
246 WIN_PROC_32A, FALSE );
250 /***********************************************************************
253 BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, HWINDOWPROC hProc )
259 EnterCriticalSection( &csTimer );
261 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
262 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
263 (pTimer->proc == hProc))
269 LeaveCriticalSection( &csTimer );
274 /***********************************************************************
275 * SetSystemTimer (USER.11)
277 UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
280 TRACE("%04x %d %d %08lx\n",
281 hwnd, id, timeout, (LONG)proc );
282 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
287 /***********************************************************************
288 * SetSystemTimer (USER32.@)
290 UINT WINAPI SetSystemTimer( HWND hwnd, UINT id, UINT timeout,
293 TRACE("%04x %d %d %08lx\n",
294 hwnd, id, timeout, (LONG)proc );
295 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
296 WIN_PROC_32A, TRUE );
300 /***********************************************************************
301 * KillTimer (USER.12)
303 BOOL16 WINAPI KillTimer16( HWND16 hwnd, UINT16 id )
305 TRACE("%04x %d\n", hwnd, id );
306 return TIMER_KillTimer( hwnd, id, FALSE );
310 /***********************************************************************
311 * KillTimer (USER32.@)
313 BOOL WINAPI KillTimer( HWND hwnd, UINT id )
315 TRACE("%04x %d\n", hwnd, id );
316 return TIMER_KillTimer( hwnd, id, FALSE );
320 /***********************************************************************
321 * KillSystemTimer (USER.182)
323 BOOL16 WINAPI KillSystemTimer16( HWND16 hwnd, UINT16 id )
325 TRACE("%04x %d\n", hwnd, id );
326 return TIMER_KillTimer( hwnd, id, TRUE );
330 /***********************************************************************
331 * KillSystemTimer (USER32.@)
333 BOOL WINAPI KillSystemTimer( HWND hwnd, UINT id )
335 TRACE("%04x %d\n", hwnd, id );
336 return TIMER_KillTimer( hwnd, id, TRUE );