source: trunk/src/user32/timer.cpp@ 10367

Last change on this file since 10367 was 10104, checked in by sandervl, 22 years ago

Handle WM_(SYS)TIMER timer calls in DispatchMessageA/W

File size: 7.5 KB
Line 
1/* $Id: timer.cpp,v 1.16 2003-05-16 10:59:27 sandervl Exp $ */
2
3/*
4 * timer functions for USER32
5 *
6 * Copyright 1993 Alexandre Julliard
7 * Copyright 1999 Daniela Engert (dani@ngrt.de)
8 *
9 * Project Odin Software License can be found in LICENSE.TXT
10 *
11 */
12
13#define INCL_WIN
14#define INCL_DOSSEMAPHORES
15#define INCL_DOSPROCESS
16#include <os2wrap.h>
17#include <os2sel.h>
18#include <stdlib.h>
19#include "win32type.h"
20#include <winconst.h>
21#include <misc.h>
22#include <win32wbase.h>
23#include "oslibutil.h"
24#include "timer.h"
25#include <odincrt.h>
26
27#define DBG_LOCALLOG DBG_timer
28#include "dbglocal.h"
29
30#ifndef OPEN32API
31#define OPEN32API _System
32#endif
33
34typedef struct tagTIMER
35{
36 enum {free = 0, UserTimer, SystemTimer} inUse;
37 HWND hwnd;
38 UINT id;
39 HWND PMhwnd;
40 ULONG PMid;
41 TIMERPROC proc;
42} TIMER;
43
44#define NB_TIMERS 34
45#define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
46
47#define SYS_TIMER_RATE 54925
48
49static TIMER TimersArray[NB_TIMERS];
50
51static CRITICAL_SECTION_OS2 timercritsect = {0};
52
53inline void EnterCriticalSection (void)
54{
55 if (timercritsect.hmtxLock == 0)
56 DosInitializeCriticalSection(&timercritsect, NULL);
57
58 DosEnterCriticalSection(&timercritsect);
59}
60
61inline void LeaveCriticalSection (void)
62{
63 DosLeaveCriticalSection(&timercritsect);
64}
65
66BOOL TIMER_GetTimerInfo(HWND PMhwnd,ULONG PMid,PBOOL sys,PULONG id, PULONG proc)
67{
68 int i;
69 TIMER *pTimer;
70
71 EnterCriticalSection ();
72 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
73 if (pTimer->inUse && (pTimer->PMhwnd == PMhwnd) && (pTimer->PMid == PMid))
74 break;
75 LeaveCriticalSection();
76
77 if (i == NB_TIMERS) /* no matching timer found */
78 return (FALSE); /* forward message */
79
80 *sys = pTimer->inUse == TIMER::SystemTimer;
81 *id = pTimer->id;
82 *proc = (ULONG)pTimer->proc;
83
84 return TRUE;
85}
86
87/***********************************************************************
88 * TIMER_IsTimerValid
89 */
90BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, ULONG proc )
91{
92 int i;
93 TIMER *pTimer;
94 BOOL ret = FALSE;
95
96 EnterCriticalSection ();
97
98 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
99 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) && (pTimer->proc == (TIMERPROC)proc))
100 {
101 ret = TRUE;
102 break;
103 }
104
105 LeaveCriticalSection();
106 return ret;
107}
108
109
110BOOL TIMER_HandleTimer (PQMSG pMsg)
111{
112 int i;
113 TIMER *pTimer;
114 HWND PMhwnd = pMsg->hwnd;
115 ULONG PMid = (ULONG)(pMsg->mp1);
116
117 EnterCriticalSection ();
118 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
119 if (pTimer->inUse && (pTimer->PMhwnd == PMhwnd) && (pTimer->PMid == PMid))
120 break;
121 LeaveCriticalSection();
122
123 if (i == NB_TIMERS) /* no matching timer found */
124 return (FALSE); /* forward message */
125
126 pMsg->mp2 = MPFROMLONG (TRUE); /* mark for Win32 */
127 if (!pTimer->proc)
128 return (FALSE); /* forward message */
129
130 if (!WinInSendMsg (GetThreadHAB())) {
131 dprintf2(("TIMER_HandleTimer %x %x %x", pTimer->hwnd, pTimer->id, pMsg->time));
132 pTimer->proc (pTimer->hwnd, (pTimer->inUse == TIMER::SystemTimer) ? WM_SYSTIMER_W:WM_TIMER_W, pTimer->id, pMsg->time);
133 }
134 return (TRUE);
135}
136
137static UINT TIMER_SetTimer (HWND hwnd, UINT id, UINT timeout, TIMERPROC proc, BOOL sys)
138{
139 int i;
140 TIMER *pTimer;
141 HWND hwndOS2;
142 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
143
144 if (hwnd && !wnd) {
145 dprintf(("TIMER_SetTimer invalid window handle %x", hwnd));
146 SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
147 return 0;
148 }
149
150 hwndOS2 = hwnd ? wnd->getOS2WindowHandle() : 0;
151 if(wnd) RELEASE_WNDOBJ(wnd);
152 wnd = NULL;
153
154 EnterCriticalSection ();
155
156 /* Check if there's already a timer with the same hwnd and id */
157
158 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
159 if (pTimer->inUse && (pTimer->hwnd == hwnd) && (pTimer->id == id) && ((sys && pTimer->inUse == TIMER::SystemTimer) || !sys))
160 break;
161
162 if (i == NB_TIMERS) /* no matching timer found */
163 {
164 /* Find a free timer */
165
166 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
167 if (!pTimer->inUse) break;
168
169 if ((i >= NB_TIMERS) ||
170 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)))
171 {
172 LeaveCriticalSection();
173 return 0;
174 }
175
176 if (!hwnd) id = i + 1;
177
178 /* Add the timer */
179
180 pTimer->inUse = sys ? TIMER::SystemTimer : TIMER::UserTimer;
181 pTimer->hwnd = hwnd;
182 pTimer->id = id;
183 pTimer->proc = proc;
184 pTimer->PMhwnd = hwnd ? hwndOS2 : NULLHANDLE;
185 pTimer->PMid = WinStartTimer (GetThreadHAB(), pTimer->PMhwnd,
186 i + 1, timeout);
187
188 if (!pTimer->PMid) id = pTimer->id = 0;
189 } else {
190 WinStartTimer (GetThreadHAB(), pTimer->PMhwnd, pTimer->PMid, timeout);
191 }
192
193 LeaveCriticalSection();
194
195 if (!id) return TRUE;
196 else return id;
197}
198
199static BOOL TIMER_KillTimer (HWND hwnd, UINT id, BOOL sys)
200{
201 int i;
202 TIMER * pTimer;
203
204 EnterCriticalSection();
205
206 /* Find the timer */
207
208 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
209 if (pTimer->inUse &&
210 (pTimer->hwnd == hwnd) && (pTimer->id == id) && ((sys && pTimer->inUse == TIMER::SystemTimer) || !sys)) break;
211
212 if ((i >= NB_TIMERS) ||
213 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ||
214 (!sys && (pTimer->inUse != TIMER::UserTimer)) ||
215 (sys && (pTimer->inUse != TIMER::SystemTimer)) )
216 {
217 LeaveCriticalSection();
218 return FALSE;
219 }
220
221 /* Delete the timer */
222
223 WinStopTimer (GetThreadHAB(), pTimer->PMhwnd, pTimer->PMid);
224
225 pTimer->inUse = TIMER::free;
226 pTimer->PMhwnd = 0;
227 pTimer->PMid = 0;
228
229 LeaveCriticalSection();
230
231 return TRUE;
232}
233
234VOID TIMER_KillTimerFromWindow(HWND hwnd)
235{
236 int i;
237 TIMER * pTimer;
238
239 if (!IsWindow(hwnd)) return;
240
241 EnterCriticalSection();
242
243 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
244 if (pTimer->inUse && pTimer->hwnd == hwnd)
245 {
246 pTimer->inUse = TIMER::free;
247 pTimer->PMhwnd = 0;
248 pTimer->PMid = 0;
249 }
250
251 LeaveCriticalSection();
252}
253
254/***********************************************************************
255 * SetTimer32 (USER32.511)
256 */
257UINT WIN32API SetTimer (HWND hwnd, UINT id, UINT timeout, TIMERPROC proc)
258{
259 UINT rc;
260
261 dprintf(("USER32: SetTimer %x %d %d %08lx", hwnd, id, timeout, (LONG)proc));
262
263 rc = TIMER_SetTimer (hwnd, id, timeout, proc, FALSE);
264 return (rc);
265}
266
267/***********************************************************************
268 * SetSystemTimer32 (USER32.509)
269 */
270UINT WIN32API SetSystemTimer (HWND hwnd, UINT id, UINT timeout, TIMERPROC proc)
271{
272 UINT rc;
273
274 dprintf(("USER32: SetSystemTimer %04x %d %d %08lx", hwnd, id, timeout, (LONG)proc));
275
276 rc = TIMER_SetTimer (hwnd, id, timeout, proc, TRUE);
277 return (rc);
278}
279
280/***********************************************************************
281 * KillTimer32 (USER32.354)
282 */
283BOOL WIN32API KillTimer (HWND hwnd, UINT id)
284{
285 BOOL rc;
286
287 dprintf(("USER32: KillTimer %x %d", hwnd, id));
288
289 rc = TIMER_KillTimer (hwnd, id, FALSE);
290 return (rc);
291}
292
293/***********************************************************************
294 * KillSystemTimer32 (USER32.353)
295 */
296BOOL WIN32API KillSystemTimer (HWND hwnd, UINT id)
297{
298 BOOL rc;
299
300 dprintf(("USER32: KillSystemTimer %x %d", hwnd, id));
301
302 rc = TIMER_KillTimer (hwnd, id, TRUE);
303 return (rc);
304}
305
Note: See TracBrowser for help on using the repository browser.