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

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

PF: Eat first WM_MOUSEMOVE while menu tracking like windows does; SvL: Use our fast critical sections instead of OS/2 mutex semaphores in the timer code

File size: 7.0 KB
Line 
1/* $Id: timer.cpp,v 1.15 2003-05-16 09:21:00 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
34#define WM_TIMER_W 0x0113
35#define WM_SYSTIMER_W 0x0118
36typedef VOID (CALLBACK *TIMERPROC)(HWND hwnd, UINT msg, UINT id, DWORD dwTime);
37
38typedef struct tagTIMER
39{
40 enum {free = 0, UserTimer, SystemTimer} inUse;
41 HWND hwnd;
42 UINT id;
43 HWND PMhwnd;
44 ULONG PMid;
45 TIMERPROC proc;
46} TIMER;
47
48#define NB_TIMERS 34
49#define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
50
51#define SYS_TIMER_RATE 54925
52
53static TIMER TimersArray[NB_TIMERS];
54
55static CRITICAL_SECTION_OS2 timercritsect = {0};
56
57inline void EnterCriticalSection (void)
58{
59 if (timercritsect.hmtxLock == 0)
60 DosInitializeCriticalSection(&timercritsect, NULL);
61
62 DosEnterCriticalSection(&timercritsect);
63}
64
65inline void LeaveCriticalSection (void)
66{
67 DosLeaveCriticalSection(&timercritsect);
68}
69
70BOOL TIMER_GetTimerInfo(HWND PMhwnd,ULONG PMid,PBOOL sys,PULONG id)
71{
72 int i;
73 TIMER *pTimer;
74
75 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
76 if (pTimer->inUse && (pTimer->PMhwnd == PMhwnd) && (pTimer->PMid == PMid))
77 break;
78
79 if (i == NB_TIMERS) /* no matching timer found */
80 return (FALSE); /* forward message */
81
82 *sys = pTimer->inUse == TIMER::SystemTimer;
83 *id = pTimer->id;
84
85 return TRUE;
86}
87
88BOOL TIMER_HandleTimer (PQMSG pMsg)
89{
90 int i;
91 TIMER *pTimer;
92 HWND PMhwnd = pMsg->hwnd;
93 ULONG PMid = (ULONG)(pMsg->mp1);
94
95 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
96 if (pTimer->inUse && (pTimer->PMhwnd == PMhwnd) && (pTimer->PMid == PMid))
97 break;
98
99 if (i == NB_TIMERS) /* no matching timer found */
100 return (FALSE); /* forward message */
101
102 pMsg->mp2 = MPFROMLONG (TRUE); /* mark for Win32 */
103 if (!pTimer->proc)
104 return (FALSE); /* forward message */
105
106 if (!WinInSendMsg (GetThreadHAB())) {
107 dprintf2(("TIMER_HandleTimer %x %x %x", pTimer->hwnd, pTimer->id, pMsg->time));
108 pTimer->proc (pTimer->hwnd, (pTimer->inUse == TIMER::SystemTimer) ? WM_SYSTIMER_W:WM_TIMER_W, pTimer->id, pMsg->time);
109 }
110 return (TRUE);
111}
112
113static UINT TIMER_SetTimer (HWND hwnd, UINT id, UINT timeout, TIMERPROC proc, BOOL sys)
114{
115 int i;
116 TIMER *pTimer;
117 HWND hwndOS2;
118 Win32BaseWindow *wnd = Win32BaseWindow::GetWindowFromHandle(hwnd);
119
120 if (hwnd && !wnd) {
121 dprintf(("TIMER_SetTimer invalid window handle %x", hwnd));
122 SetLastError(ERROR_INVALID_WINDOW_HANDLE_W);
123 return 0;
124 }
125
126 hwndOS2 = hwnd ? wnd->getOS2WindowHandle() : 0;
127 if(wnd) RELEASE_WNDOBJ(wnd);
128 wnd = NULL;
129
130 EnterCriticalSection ();
131
132 /* Check if there's already a timer with the same hwnd and id */
133
134 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
135 if (pTimer->inUse && (pTimer->hwnd == hwnd) && (pTimer->id == id) && ((sys && pTimer->inUse == TIMER::SystemTimer) || !sys))
136 break;
137
138 if (i == NB_TIMERS) /* no matching timer found */
139 {
140 /* Find a free timer */
141
142 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
143 if (!pTimer->inUse) break;
144
145 if ((i >= NB_TIMERS) ||
146 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)))
147 {
148 LeaveCriticalSection();
149 return 0;
150 }
151
152 if (!hwnd) id = i + 1;
153
154 /* Add the timer */
155
156 pTimer->inUse = sys ? TIMER::SystemTimer : TIMER::UserTimer;
157 pTimer->hwnd = hwnd;
158 pTimer->id = id;
159 pTimer->proc = proc;
160 pTimer->PMhwnd = hwnd ? hwndOS2 : NULLHANDLE;
161 pTimer->PMid = WinStartTimer (GetThreadHAB(), pTimer->PMhwnd,
162 i + 1, timeout);
163
164 if (!pTimer->PMid) id = pTimer->id = 0;
165 } else {
166 WinStartTimer (GetThreadHAB(), pTimer->PMhwnd, pTimer->PMid, timeout);
167 }
168
169 LeaveCriticalSection();
170
171 if (!id) return TRUE;
172 else return id;
173}
174
175static BOOL TIMER_KillTimer (HWND hwnd, UINT id, BOOL sys)
176{
177 int i;
178 TIMER * pTimer;
179
180 EnterCriticalSection();
181
182 /* Find the timer */
183
184 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
185 if (pTimer->inUse &&
186 (pTimer->hwnd == hwnd) && (pTimer->id == id) && ((sys && pTimer->inUse == TIMER::SystemTimer) || !sys)) break;
187
188 if ((i >= NB_TIMERS) ||
189 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ||
190 (!sys && (pTimer->inUse != TIMER::UserTimer)) ||
191 (sys && (pTimer->inUse != TIMER::SystemTimer)) )
192 {
193 LeaveCriticalSection();
194 return FALSE;
195 }
196
197 /* Delete the timer */
198
199 WinStopTimer (GetThreadHAB(), pTimer->PMhwnd, pTimer->PMid);
200
201 pTimer->inUse = TIMER::free;
202 pTimer->PMhwnd = 0;
203 pTimer->PMid = 0;
204
205 LeaveCriticalSection();
206
207 return TRUE;
208}
209
210VOID TIMER_KillTimerFromWindow(HWND hwnd)
211{
212 int i;
213 TIMER * pTimer;
214
215 if (!IsWindow(hwnd)) return;
216
217 EnterCriticalSection();
218
219 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
220 if (pTimer->inUse && pTimer->hwnd == hwnd)
221 {
222 pTimer->inUse = TIMER::free;
223 pTimer->PMhwnd = 0;
224 pTimer->PMid = 0;
225 }
226
227 LeaveCriticalSection();
228}
229
230/***********************************************************************
231 * SetTimer32 (USER32.511)
232 */
233UINT WIN32API SetTimer (HWND hwnd, UINT id, UINT timeout, TIMERPROC proc)
234{
235 UINT rc;
236
237 dprintf(("USER32: SetTimer %x %d %d %08lx", hwnd, id, timeout, (LONG)proc));
238
239 rc = TIMER_SetTimer (hwnd, id, timeout, proc, FALSE);
240 return (rc);
241}
242
243/***********************************************************************
244 * SetSystemTimer32 (USER32.509)
245 */
246UINT WIN32API SetSystemTimer (HWND hwnd, UINT id, UINT timeout, TIMERPROC proc)
247{
248 UINT rc;
249
250 dprintf(("USER32: SetSystemTimer %04x %d %d %08lx", hwnd, id, timeout, (LONG)proc));
251
252 rc = TIMER_SetTimer (hwnd, id, timeout, proc, TRUE);
253 return (rc);
254}
255
256/***********************************************************************
257 * KillTimer32 (USER32.354)
258 */
259BOOL WIN32API KillTimer (HWND hwnd, UINT id)
260{
261 BOOL rc;
262
263 dprintf(("USER32: KillTimer %x %d", hwnd, id));
264
265 rc = TIMER_KillTimer (hwnd, id, FALSE);
266 return (rc);
267}
268
269/***********************************************************************
270 * KillSystemTimer32 (USER32.353)
271 */
272BOOL WIN32API KillSystemTimer (HWND hwnd, UINT id)
273{
274 BOOL rc;
275
276 dprintf(("USER32: KillSystemTimer %x %d", hwnd, id));
277
278 rc = TIMER_KillTimer (hwnd, id, TRUE);
279 return (rc);
280}
281
Note: See TracBrowser for help on using the repository browser.