4 * Copyright 1993 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "wine/winuser16.h"
33 #include "wine/server.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(timer
);
39 typedef struct tagTIMER
43 UINT msg
; /* WM_TIMER or WM_SYSTIMER */
50 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
52 #define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
54 static TIMER TimersArray
[NB_TIMERS
];
56 static CRITICAL_SECTION csTimer
;
57 static CRITICAL_SECTION_DEBUG critsect_debug
=
60 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
61 0, 0, { 0, (DWORD
)(__FILE__
": csTimer") }
63 static CRITICAL_SECTION csTimer
= { &critsect_debug
, -1, 0, 0, 0, 0 };
66 /***********************************************************************
69 * Clear and remove a timer.
71 static void TIMER_ClearTimer( TIMER
* pTimer
)
77 WINPROC_FreeProc( pTimer
->proc
, WIN_PROC_TIMER
);
81 /***********************************************************************
82 * TIMER_RemoveWindowTimers
84 * Remove all timers for a given window.
86 void TIMER_RemoveWindowTimers( HWND hwnd
)
91 EnterCriticalSection( &csTimer
);
93 for (i
= NB_TIMERS
, pTimer
= TimersArray
; i
> 0; i
--, pTimer
++)
94 if ((pTimer
->hwnd
== hwnd
) && pTimer
->timeout
)
95 TIMER_ClearTimer( pTimer
);
97 LeaveCriticalSection( &csTimer
);
101 /***********************************************************************
102 * TIMER_RemoveThreadTimers
104 * Remove all timers for the current thread.
106 void TIMER_RemoveThreadTimers(void)
111 EnterCriticalSection( &csTimer
);
113 for (i
= NB_TIMERS
, pTimer
= TimersArray
; i
> 0; i
--, pTimer
++)
114 if ((pTimer
->thread
== GetCurrentThreadId()) && pTimer
->timeout
)
115 TIMER_ClearTimer( pTimer
);
117 LeaveCriticalSection( &csTimer
);
121 /***********************************************************************
124 static UINT_PTR
TIMER_SetTimer( HWND hwnd
, UINT_PTR id
, UINT timeout
,
125 WNDPROC proc
, WINDOWPROCTYPE type
, BOOL sys
)
131 if (hwnd
&& !(hwnd
= WIN_IsCurrentThread( hwnd
)))
133 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
138 { /* timeout==0 is a legal argument UB 990821*/
139 WARN("Timeout== 0 not implemented, using timeout=1\n");
143 EnterCriticalSection( &csTimer
);
145 /* Check if there's already a timer with the same hwnd and id */
147 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
148 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
149 (pTimer
->timeout
!= 0))
151 TIMER_ClearTimer( pTimer
);
155 if ( i
== NB_TIMERS
)
157 /* Find a free timer */
159 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
160 if (!pTimer
->timeout
) break;
162 if ( (i
>= NB_TIMERS
) ||
163 (!sys
&& (i
>= NB_TIMERS
-NB_RESERVED_TIMERS
)) )
165 LeaveCriticalSection( &csTimer
);
170 if (!hwnd
) id
= i
+ 1;
172 if (proc
) WINPROC_SetProc( &winproc
, proc
, type
, WIN_PROC_TIMER
);
174 SERVER_START_REQ( set_win_timer
)
177 req
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
179 req
->rate
= max( timeout
, SYS_TIMER_RATE
);
180 req
->lparam
= (unsigned int)winproc
;
181 wine_server_call( req
);
188 pTimer
->thread
= GetCurrentThreadId();
189 pTimer
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
191 pTimer
->timeout
= timeout
;
192 pTimer
->proc
= winproc
;
194 TRACE("Timer added: %p, %p, %04x, %04x, %p\n",
195 pTimer
, pTimer
->hwnd
, pTimer
->msg
, pTimer
->id
, pTimer
->proc
);
197 LeaveCriticalSection( &csTimer
);
199 if (!id
) return TRUE
;
204 /***********************************************************************
207 static BOOL
TIMER_KillTimer( HWND hwnd
, UINT_PTR id
, BOOL sys
)
212 SERVER_START_REQ( kill_win_timer
)
215 req
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
217 wine_server_call( req
);
221 EnterCriticalSection( &csTimer
);
225 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
226 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
227 (pTimer
->timeout
!= 0)) break;
229 if ( (i
>= NB_TIMERS
) ||
230 (!sys
&& (i
>= NB_TIMERS
-NB_RESERVED_TIMERS
)) ||
231 (!sys
&& (pTimer
->msg
!= WM_TIMER
)) ||
232 (sys
&& (pTimer
->msg
!= WM_SYSTIMER
)) )
234 LeaveCriticalSection( &csTimer
);
238 /* Delete the timer */
240 TIMER_ClearTimer( pTimer
);
242 LeaveCriticalSection( &csTimer
);
248 /***********************************************************************
251 UINT16 WINAPI
SetTimer16( HWND16 hwnd
, UINT16 id
, UINT16 timeout
,
254 TRACE("%04x %d %d %08lx\n",
255 hwnd
, id
, timeout
, (LONG
)proc
);
256 return TIMER_SetTimer( WIN_Handle32(hwnd
), id
, timeout
, (WNDPROC
)proc
,
257 WIN_PROC_16
, FALSE
);
261 /***********************************************************************
262 * SetTimer (USER32.@)
264 UINT_PTR WINAPI
SetTimer( HWND hwnd
, UINT_PTR id
, UINT timeout
,
267 TRACE("%p %d %d %p\n", hwnd
, id
, timeout
, proc
);
268 return TIMER_SetTimer( hwnd
, id
, timeout
, (WNDPROC
)proc
, WIN_PROC_32A
, FALSE
);
272 /***********************************************************************
275 BOOL
TIMER_IsTimerValid( HWND hwnd
, UINT_PTR id
, WNDPROC proc
)
281 hwnd
= WIN_GetFullHandle( hwnd
);
282 EnterCriticalSection( &csTimer
);
284 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
285 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) && (pTimer
->proc
== proc
))
291 LeaveCriticalSection( &csTimer
);
296 /***********************************************************************
297 * SetSystemTimer (USER.11)
299 UINT16 WINAPI
SetSystemTimer16( HWND16 hwnd
, UINT16 id
, UINT16 timeout
,
302 TRACE("%04x %d %d %08lx\n",
303 hwnd
, id
, timeout
, (LONG
)proc
);
304 return TIMER_SetTimer( WIN_Handle32(hwnd
), id
, timeout
, (WNDPROC
)proc
, WIN_PROC_16
, TRUE
);
308 /***********************************************************************
309 * SetSystemTimer (USER32.@)
311 UINT_PTR WINAPI
SetSystemTimer( HWND hwnd
, UINT_PTR id
, UINT timeout
,
314 TRACE("%p %d %d %p\n", hwnd
, id
, timeout
, proc
);
315 return TIMER_SetTimer( hwnd
, id
, timeout
, (WNDPROC
)proc
, WIN_PROC_32A
, TRUE
);
319 /***********************************************************************
320 * KillTimer (USER32.@)
322 BOOL WINAPI
KillTimer( HWND hwnd
, UINT_PTR id
)
324 TRACE("%p %d\n", hwnd
, id
);
325 return TIMER_KillTimer( hwnd
, id
, FALSE
);
329 /***********************************************************************
330 * KillSystemTimer (USER32.@)
332 BOOL WINAPI
KillSystemTimer( HWND hwnd
, UINT_PTR id
)
334 TRACE("%p %d\n", hwnd
, id
);
335 return TIMER_KillTimer( hwnd
, id
, TRUE
);