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
23 #include "wine/winuser16.h"
30 #include "wine/server.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(timer
);
36 typedef struct tagTIMER
40 UINT msg
; /* WM_TIMER or WM_SYSTIMER */
47 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
49 #define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
51 static TIMER TimersArray
[NB_TIMERS
];
53 static CRITICAL_SECTION csTimer
= CRITICAL_SECTION_INIT("csTimer");
56 /***********************************************************************
59 * Clear and remove a timer.
61 static void TIMER_ClearTimer( TIMER
* pTimer
)
67 WINPROC_FreeProc( pTimer
->proc
, WIN_PROC_TIMER
);
71 /***********************************************************************
72 * TIMER_RemoveWindowTimers
74 * Remove all timers for a given window.
76 void TIMER_RemoveWindowTimers( HWND hwnd
)
81 EnterCriticalSection( &csTimer
);
83 for (i
= NB_TIMERS
, pTimer
= TimersArray
; i
> 0; i
--, pTimer
++)
84 if ((pTimer
->hwnd
== hwnd
) && pTimer
->timeout
)
85 TIMER_ClearTimer( pTimer
);
87 LeaveCriticalSection( &csTimer
);
91 /***********************************************************************
92 * TIMER_RemoveThreadTimers
94 * Remove all timers for the current thread.
96 void TIMER_RemoveThreadTimers(void)
101 EnterCriticalSection( &csTimer
);
103 for (i
= NB_TIMERS
, pTimer
= TimersArray
; i
> 0; i
--, pTimer
++)
104 if ((pTimer
->thread
== GetCurrentThreadId()) && pTimer
->timeout
)
105 TIMER_ClearTimer( pTimer
);
107 LeaveCriticalSection( &csTimer
);
111 /***********************************************************************
114 static UINT
TIMER_SetTimer( HWND hwnd
, UINT id
, UINT timeout
,
115 WNDPROC16 proc
, WINDOWPROCTYPE type
, BOOL sys
)
119 HWINDOWPROC winproc
= 0;
121 if (hwnd
&& !(hwnd
= WIN_IsCurrentThread( hwnd
)))
123 SetLastError( ERROR_INVALID_WINDOW_HANDLE
);
128 { /* timeout==0 is a legal argument UB 990821*/
129 WARN("Timeout== 0 not implemented, using timeout=1\n");
133 EnterCriticalSection( &csTimer
);
135 /* Check if there's already a timer with the same hwnd and id */
137 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
138 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
139 (pTimer
->timeout
!= 0))
141 TIMER_ClearTimer( pTimer
);
145 if ( i
== NB_TIMERS
)
147 /* Find a free timer */
149 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
150 if (!pTimer
->timeout
) break;
152 if ( (i
>= NB_TIMERS
) ||
153 (!sys
&& (i
>= NB_TIMERS
-NB_RESERVED_TIMERS
)) )
155 LeaveCriticalSection( &csTimer
);
160 if (!hwnd
) id
= i
+ 1;
162 if (proc
) WINPROC_SetProc( &winproc
, proc
, type
, WIN_PROC_TIMER
);
164 SERVER_START_REQ( set_win_timer
)
167 req
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
169 req
->rate
= max( timeout
, SYS_TIMER_RATE
);
170 req
->lparam
= (unsigned int)winproc
;
171 wine_server_call( req
);
178 pTimer
->thread
= GetCurrentThreadId();
179 pTimer
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
181 pTimer
->timeout
= timeout
;
182 pTimer
->proc
= winproc
;
184 TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
185 pTimer
, pTimer
->hwnd
, pTimer
->msg
, pTimer
->id
,
186 (DWORD
)pTimer
->proc
);
188 LeaveCriticalSection( &csTimer
);
190 if (!id
) return TRUE
;
195 /***********************************************************************
198 static BOOL
TIMER_KillTimer( HWND hwnd
, UINT id
, BOOL sys
)
203 SERVER_START_REQ( kill_win_timer
)
206 req
->msg
= sys
? WM_SYSTIMER
: WM_TIMER
;
208 wine_server_call( req
);
212 EnterCriticalSection( &csTimer
);
216 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
217 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
218 (pTimer
->timeout
!= 0)) break;
220 if ( (i
>= NB_TIMERS
) ||
221 (!sys
&& (i
>= NB_TIMERS
-NB_RESERVED_TIMERS
)) ||
222 (!sys
&& (pTimer
->msg
!= WM_TIMER
)) ||
223 (sys
&& (pTimer
->msg
!= WM_SYSTIMER
)) )
225 LeaveCriticalSection( &csTimer
);
229 /* Delete the timer */
231 TIMER_ClearTimer( pTimer
);
233 LeaveCriticalSection( &csTimer
);
239 /***********************************************************************
242 UINT16 WINAPI
SetTimer16( HWND16 hwnd
, UINT16 id
, UINT16 timeout
,
245 TRACE("%04x %d %d %08lx\n",
246 hwnd
, id
, timeout
, (LONG
)proc
);
247 return TIMER_SetTimer( WIN_Handle32(hwnd
), id
, timeout
, (WNDPROC16
)proc
,
248 WIN_PROC_16
, FALSE
);
252 /***********************************************************************
253 * SetTimer (USER32.@)
255 UINT WINAPI
SetTimer( HWND hwnd
, UINT id
, UINT timeout
,
258 TRACE("%04x %d %d %08lx\n",
259 hwnd
, id
, timeout
, (LONG
)proc
);
260 return TIMER_SetTimer( hwnd
, id
, timeout
, (WNDPROC16
)proc
, WIN_PROC_32A
, FALSE
);
264 /***********************************************************************
267 BOOL
TIMER_IsTimerValid( HWND hwnd
, UINT id
, HWINDOWPROC hProc
)
273 hwnd
= WIN_GetFullHandle( hwnd
);
274 EnterCriticalSection( &csTimer
);
276 for (i
= 0, pTimer
= TimersArray
; i
< NB_TIMERS
; i
++, pTimer
++)
277 if ((pTimer
->hwnd
== hwnd
) && (pTimer
->id
== id
) &&
278 (pTimer
->proc
== hProc
))
284 LeaveCriticalSection( &csTimer
);
289 /***********************************************************************
290 * SetSystemTimer (USER.11)
292 UINT16 WINAPI
SetSystemTimer16( HWND16 hwnd
, UINT16 id
, UINT16 timeout
,
295 TRACE("%04x %d %d %08lx\n",
296 hwnd
, id
, timeout
, (LONG
)proc
);
297 return TIMER_SetTimer( WIN_Handle32(hwnd
), id
, timeout
, (WNDPROC16
)proc
,
302 /***********************************************************************
303 * SetSystemTimer (USER32.@)
305 UINT WINAPI
SetSystemTimer( HWND hwnd
, UINT id
, UINT timeout
,
308 TRACE("%04x %d %d %08lx\n",
309 hwnd
, id
, timeout
, (LONG
)proc
);
310 return TIMER_SetTimer( hwnd
, id
, timeout
, (WNDPROC16
)proc
, WIN_PROC_32A
, TRUE
);
314 /***********************************************************************
315 * KillTimer (USER32.@)
317 BOOL WINAPI
KillTimer( HWND hwnd
, UINT id
)
319 TRACE("%04x %d\n", hwnd
, id
);
320 return TIMER_KillTimer( hwnd
, id
, FALSE
);
324 /***********************************************************************
325 * KillSystemTimer (USER32.@)
327 BOOL WINAPI
KillSystemTimer( HWND hwnd
, UINT id
)
329 TRACE("%04x %d\n", hwnd
, id
);
330 return TIMER_KillTimer( hwnd
, id
, TRUE
);