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
&& !(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
;
157 wine_server_call( req
);
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
;
194 wine_server_call( req
);
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( hwnd
, id
, timeout
, (WNDPROC16
)proc
, WIN_PROC_32A
, FALSE
);
250 /***********************************************************************
253 BOOL
TIMER_IsTimerValid( HWND hwnd
, UINT id
, HWINDOWPROC hProc
)
259 hwnd
= WIN_GetFullHandle( hwnd
);
260 EnterCriticalSection( &csTimer
);
262 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
263 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
264 (pTimer
->proc
== hProc
))
270 LeaveCriticalSection( &csTimer
);
275 /***********************************************************************
276 * SetSystemTimer (USER.11)
278 UINT16 WINAPI
SetSystemTimer16( HWND16 hwnd
, UINT16 id
, UINT16 timeout
,
281 TRACE("%04x %d %d %08lx\n",
282 hwnd
, id
, timeout
, (LONG
)proc
);
283 return TIMER_SetTimer( WIN_Handle32(hwnd
), id
, timeout
, (WNDPROC16
)proc
,
288 /***********************************************************************
289 * SetSystemTimer (USER32.@)
291 UINT WINAPI
SetSystemTimer( HWND hwnd
, UINT id
, UINT timeout
,
294 TRACE("%04x %d %d %08lx\n",
295 hwnd
, id
, timeout
, (LONG
)proc
);
296 return TIMER_SetTimer( hwnd
, id
, timeout
, (WNDPROC16
)proc
, WIN_PROC_32A
, TRUE
);
300 /***********************************************************************
301 * KillTimer (USER32.@)
303 BOOL WINAPI
KillTimer( HWND hwnd
, UINT id
)
305 TRACE("%04x %d\n", hwnd
, id
);
306 return TIMER_KillTimer( hwnd
, id
, FALSE
);
310 /***********************************************************************
311 * KillSystemTimer (USER32.@)
313 BOOL WINAPI
KillSystemTimer( HWND hwnd
, UINT id
)
315 TRACE("%04x %d\n", hwnd
, id
);
316 return TIMER_KillTimer( hwnd
, id
, TRUE
);