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
22 #include "wine/port.h"
29 #include "wine/winuser16.h"
36 #include "wine/server.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(timer
);
42 typedef struct tagTIMER
46 UINT msg
; /* WM_TIMER or WM_SYSTIMER */
53 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
55 #define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
57 static TIMER TimersArray
[NB_TIMERS
];
59 static CRITICAL_SECTION csTimer
;
60 static CRITICAL_SECTION_DEBUG critsect_debug
=
63 { &critsect_debug
.ProcessLocksList
, &critsect_debug
.ProcessLocksList
},
64 0, 0, { 0, (DWORD
)(__FILE__
": csTimer") }
66 static CRITICAL_SECTION csTimer
= { &critsect_debug
, -1, 0, 0, 0, 0 };
69 /***********************************************************************
72 * Clear and remove a timer.
74 static void TIMER_ClearTimer( TIMER
* pTimer
)
80 WINPROC_FreeProc( pTimer
->proc
, WIN_PROC_TIMER
);
84 /***********************************************************************
85 * TIMER_RemoveWindowTimers
87 * Remove all timers for a given window.
89 void TIMER_RemoveWindowTimers( HWND hwnd
)
94 EnterCriticalSection( &csTimer
);
96 for (i
= NB_TIMERS
, pTimer
= TimersArray
; i
> 0; i
--, pTimer
++)
97 if ((pTimer
->hwnd
== hwnd
) && pTimer
->timeout
)
98 TIMER_ClearTimer( pTimer
);
100 LeaveCriticalSection( &csTimer
);
104 /***********************************************************************
105 * TIMER_RemoveThreadTimers
107 * Remove all timers for the current thread.
109 void TIMER_RemoveThreadTimers(void)
114 EnterCriticalSection( &csTimer
);
116 for (i
= NB_TIMERS
, pTimer
= TimersArray
; i
> 0; i
--, pTimer
++)
117 if ((pTimer
->thread
== GetCurrentThreadId()) && pTimer
->timeout
)
118 TIMER_ClearTimer( pTimer
);
120 LeaveCriticalSection( &csTimer
);
124 /***********************************************************************
127 static UINT_PTR
TIMER_SetTimer( HWND hwnd
, UINT_PTR id
, UINT timeout
,
128 WNDPROC proc
, WINDOWPROCTYPE type
, BOOL sys
)
134 if (hwnd
&& !(hwnd
= WIN_IsCurrentThread( hwnd
)))
136 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
141 { /* timeout==0 is a legal argument UB 990821*/
142 WARN("Timeout== 0 not implemented, using timeout=1\n");
146 EnterCriticalSection( &csTimer
);
148 /* Check if there's already a timer with the same hwnd and id */
150 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
151 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
152 (pTimer
->timeout
!= 0))
154 TIMER_ClearTimer( pTimer
);
158 if ( i
== NB_TIMERS
)
160 /* Find a free timer */
162 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
163 if (!pTimer
->timeout
) break;
165 if ( (i
>= NB_TIMERS
) ||
166 (!sys
&& (i
>= NB_TIMERS
-NB_RESERVED_TIMERS
)) )
168 LeaveCriticalSection( &csTimer
);
173 if (!hwnd
) id
= i
+ 1;
175 if (proc
) WINPROC_SetProc( &winproc
, proc
, type
, WIN_PROC_TIMER
);
177 SERVER_START_REQ( set_win_timer
)
180 req
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
182 req
->rate
= max( timeout
, SYS_TIMER_RATE
);
183 req
->lparam
= (unsigned int)winproc
;
184 wine_server_call( req
);
191 pTimer
->thread
= GetCurrentThreadId();
192 pTimer
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
194 pTimer
->timeout
= timeout
;
195 pTimer
->proc
= winproc
;
197 TRACE("Timer added: %p, %p, %04x, %04x, %p\n",
198 pTimer
, pTimer
->hwnd
, pTimer
->msg
, pTimer
->id
, pTimer
->proc
);
200 LeaveCriticalSection( &csTimer
);
202 if (!id
) return TRUE
;
207 /***********************************************************************
210 static BOOL
TIMER_KillTimer( HWND hwnd
, UINT_PTR id
, BOOL sys
)
215 SERVER_START_REQ( kill_win_timer
)
218 req
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
220 wine_server_call( req
);
224 EnterCriticalSection( &csTimer
);
228 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
229 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
230 (pTimer
->timeout
!= 0)) break;
232 if ( (i
>= NB_TIMERS
) ||
233 (!sys
&& (i
>= NB_TIMERS
-NB_RESERVED_TIMERS
)) ||
234 (!sys
&& (pTimer
->msg
!= WM_TIMER
)) ||
235 (sys
&& (pTimer
->msg
!= WM_SYSTIMER
)) )
237 LeaveCriticalSection( &csTimer
);
241 /* Delete the timer */
243 TIMER_ClearTimer( pTimer
);
245 LeaveCriticalSection( &csTimer
);
251 /***********************************************************************
254 UINT16 WINAPI
SetTimer16( HWND16 hwnd
, UINT16 id
, UINT16 timeout
,
257 TRACE("%04x %d %d %08lx\n",
258 hwnd
, id
, timeout
, (LONG
)proc
);
259 return TIMER_SetTimer( WIN_Handle32(hwnd
), id
, timeout
, (WNDPROC
)proc
,
260 WIN_PROC_16
, FALSE
);
264 /***********************************************************************
265 * SetTimer (USER32.@)
267 UINT_PTR WINAPI
SetTimer( HWND hwnd
, UINT_PTR id
, UINT timeout
,
270 TRACE("%p %d %d %p\n", hwnd
, id
, timeout
, proc
);
271 return TIMER_SetTimer( hwnd
, id
, timeout
, (WNDPROC
)proc
, WIN_PROC_32A
, FALSE
);
275 /***********************************************************************
278 BOOL
TIMER_IsTimerValid( HWND hwnd
, UINT_PTR id
, WNDPROC proc
)
284 hwnd
= WIN_GetFullHandle( hwnd
);
285 EnterCriticalSection( &csTimer
);
287 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
288 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) && (pTimer
->proc
== proc
))
294 LeaveCriticalSection( &csTimer
);
299 /***********************************************************************
300 * SetSystemTimer (USER.11)
302 UINT16 WINAPI
SetSystemTimer16( HWND16 hwnd
, UINT16 id
, UINT16 timeout
,
305 TRACE("%04x %d %d %08lx\n",
306 hwnd
, id
, timeout
, (LONG
)proc
);
307 return TIMER_SetTimer( WIN_Handle32(hwnd
), id
, timeout
, (WNDPROC
)proc
, WIN_PROC_16
, TRUE
);
311 /***********************************************************************
312 * SetSystemTimer (USER32.@)
314 UINT_PTR WINAPI
SetSystemTimer( HWND hwnd
, UINT_PTR id
, UINT timeout
,
317 TRACE("%p %d %d %p\n", hwnd
, id
, timeout
, proc
);
318 return TIMER_SetTimer( hwnd
, id
, timeout
, (WNDPROC
)proc
, WIN_PROC_32A
, TRUE
);
322 /***********************************************************************
323 * KillTimer (USER32.@)
325 BOOL WINAPI
KillTimer( HWND hwnd
, UINT_PTR id
)
327 TRACE("%p %d\n", hwnd
, id
);
328 return TIMER_KillTimer( hwnd
, id
, FALSE
);
332 /***********************************************************************
333 * KillSystemTimer (USER32.@)
335 BOOL WINAPI
KillSystemTimer( HWND hwnd
, UINT_PTR id
)
337 TRACE("%p %d\n", hwnd
, id
);
338 return TIMER_KillTimer( hwnd
, id
, TRUE
);