4 * Copyright 1993 Alexandre Julliard
9 #include "wine/winuser16.h"
16 #include "wine/server.h"
17 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(timer
);
22 typedef struct tagTIMER
26 UINT16 msg
; /* WM_TIMER or WM_SYSTIMER */
33 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
35 #define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
37 static TIMER TimersArray
[NB_TIMERS
];
39 static CRITICAL_SECTION csTimer
= CRITICAL_SECTION_INIT("csTimer");
42 /***********************************************************************
45 * Clear and remove a timer.
47 static void TIMER_ClearTimer( TIMER
* pTimer
)
53 WINPROC_FreeProc( pTimer
->proc
, WIN_PROC_TIMER
);
57 /***********************************************************************
58 * TIMER_RemoveWindowTimers
60 * Remove all timers for a given window.
62 void TIMER_RemoveWindowTimers( HWND hwnd
)
67 EnterCriticalSection( &csTimer
);
69 for (i
= NB_TIMERS
, pTimer
= TimersArray
; i
> 0; i
--, pTimer
++)
70 if ((pTimer
->hwnd
== hwnd
) && pTimer
->timeout
)
71 TIMER_ClearTimer( pTimer
);
73 LeaveCriticalSection( &csTimer
);
77 /***********************************************************************
78 * TIMER_RemoveQueueTimers
80 * Remove all timers for a given queue.
82 void TIMER_RemoveQueueTimers( HQUEUE16 hqueue
)
87 EnterCriticalSection( &csTimer
);
89 for (i
= NB_TIMERS
, pTimer
= TimersArray
; i
> 0; i
--, pTimer
++)
90 if ((pTimer
->hq
== hqueue
) && pTimer
->timeout
)
91 TIMER_ClearTimer( pTimer
);
93 LeaveCriticalSection( &csTimer
);
97 /***********************************************************************
100 static UINT
TIMER_SetTimer( HWND hwnd
, UINT id
, UINT timeout
,
101 WNDPROC16 proc
, WINDOWPROCTYPE type
, BOOL sys
)
105 HWINDOWPROC winproc
= 0;
107 if (hwnd
&& !WIN_IsCurrentThread( hwnd
))
109 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
114 { /* timeout==0 is a legal argument UB 990821*/
115 WARN("Timeout== 0 not implemented, using timeout=1\n");
119 EnterCriticalSection( &csTimer
);
121 /* Check if there's already a timer with the same hwnd and id */
123 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
124 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
125 (pTimer
->timeout
!= 0))
127 TIMER_ClearTimer( pTimer
);
131 if ( i
== NB_TIMERS
)
133 /* Find a free timer */
135 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
136 if (!pTimer
->timeout
) break;
138 if ( (i
>= NB_TIMERS
) ||
139 (!sys
&& (i
>= NB_TIMERS
-NB_RESERVED_TIMERS
)) )
141 LeaveCriticalSection( &csTimer
);
146 if (!hwnd
) id
= i
+ 1;
148 if (proc
) WINPROC_SetProc( &winproc
, proc
, type
, WIN_PROC_TIMER
);
150 SERVER_START_REQ( set_win_timer
)
153 req
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
155 req
->rate
= max( timeout
, SYS_TIMER_RATE
);
156 req
->lparam
= (unsigned int)winproc
;
164 pTimer
->hq
= InitThreadInput16( 0, 0 );
165 pTimer
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
167 pTimer
->timeout
= timeout
;
168 pTimer
->proc
= winproc
;
170 TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
171 pTimer
, pTimer
->hwnd
, pTimer
->msg
, pTimer
->id
,
172 (DWORD
)pTimer
->proc
);
174 LeaveCriticalSection( &csTimer
);
176 if (!id
) return TRUE
;
181 /***********************************************************************
184 static BOOL
TIMER_KillTimer( HWND hwnd
, UINT id
, BOOL sys
)
189 SERVER_START_REQ( kill_win_timer
)
192 req
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
198 EnterCriticalSection( &csTimer
);
202 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
203 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
204 (pTimer
->timeout
!= 0)) break;
206 if ( (i
>= NB_TIMERS
) ||
207 (!sys
&& (i
>= NB_TIMERS
-NB_RESERVED_TIMERS
)) ||
208 (!sys
&& (pTimer
->msg
!= WM_TIMER
)) ||
209 (sys
&& (pTimer
->msg
!= WM_SYSTIMER
)) )
211 LeaveCriticalSection( &csTimer
);
215 /* Delete the timer */
217 TIMER_ClearTimer( pTimer
);
219 LeaveCriticalSection( &csTimer
);
225 /***********************************************************************
228 UINT16 WINAPI
SetTimer16( HWND16 hwnd
, UINT16 id
, UINT16 timeout
,
231 TRACE("%04x %d %d %08lx\n",
232 hwnd
, id
, timeout
, (LONG
)proc
);
233 return TIMER_SetTimer( WIN_Handle32(hwnd
), id
, timeout
, (WNDPROC16
)proc
,
234 WIN_PROC_16
, FALSE
);
238 /***********************************************************************
239 * SetTimer (USER32.@)
241 UINT WINAPI
SetTimer( HWND hwnd
, UINT id
, UINT timeout
,
244 TRACE("%04x %d %d %08lx\n",
245 hwnd
, id
, timeout
, (LONG
)proc
);
246 return TIMER_SetTimer( WIN_GetFullHandle(hwnd
), id
, timeout
, (WNDPROC16
)proc
,
247 WIN_PROC_32A
, FALSE
);
251 /***********************************************************************
254 BOOL
TIMER_IsTimerValid( HWND hwnd
, UINT id
, HWINDOWPROC hProc
)
260 hwnd
= WIN_GetFullHandle( hwnd
);
261 EnterCriticalSection( &csTimer
);
263 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
264 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
265 (pTimer
->proc
== hProc
))
271 LeaveCriticalSection( &csTimer
);
276 /***********************************************************************
277 * SetSystemTimer (USER.11)
279 UINT16 WINAPI
SetSystemTimer16( HWND16 hwnd
, UINT16 id
, UINT16 timeout
,
282 TRACE("%04x %d %d %08lx\n",
283 hwnd
, id
, timeout
, (LONG
)proc
);
284 return TIMER_SetTimer( WIN_Handle32(hwnd
), id
, timeout
, (WNDPROC16
)proc
,
289 /***********************************************************************
290 * SetSystemTimer (USER32.@)
292 UINT WINAPI
SetSystemTimer( HWND hwnd
, UINT id
, UINT timeout
,
295 TRACE("%04x %d %d %08lx\n",
296 hwnd
, id
, timeout
, (LONG
)proc
);
297 return TIMER_SetTimer( WIN_GetFullHandle(hwnd
), id
, timeout
, (WNDPROC16
)proc
,
298 WIN_PROC_32A
, TRUE
);
302 /***********************************************************************
303 * KillTimer (USER32.@)
305 BOOL WINAPI
KillTimer( HWND hwnd
, UINT id
)
307 TRACE("%04x %d\n", hwnd
, id
);
308 return TIMER_KillTimer( hwnd
, id
, FALSE
);
312 /***********************************************************************
313 * KillSystemTimer (USER32.@)
315 BOOL WINAPI
KillSystemTimer( HWND hwnd
, UINT id
)
317 TRACE("%04x %d\n", hwnd
, id
);
318 return TIMER_KillTimer( hwnd
, id
, TRUE
);