user32: SetTimer and SetSystemTimer should respect the timeout limits.
This commit is contained in:
parent
9ddd30d11c
commit
057b0d8bca
|
@ -56,8 +56,6 @@ WINE_DECLARE_DEBUG_CHANNEL(key);
|
|||
|
||||
#define MAX_PACK_COUNT 4
|
||||
|
||||
#define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
|
||||
|
||||
/* the various structures that can be sent in messages, in platform-independent layout */
|
||||
struct packed_CREATESTRUCTW
|
||||
{
|
||||
|
@ -4385,12 +4383,16 @@ UINT_PTR WINAPI SetTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC proc )
|
|||
|
||||
if (proc) winproc = WINPROC_AllocProc( (WNDPROC)proc, FALSE );
|
||||
|
||||
/* MSDN states that the minimum timeout should be USER_TIMER_MINIMUM (10.0 ms), but testing
|
||||
* indicates that the true minimum is closer to 15.6 ms. */
|
||||
timeout = min( max( 15, timeout ), USER_TIMER_MAXIMUM );
|
||||
|
||||
SERVER_START_REQ( set_win_timer )
|
||||
{
|
||||
req->win = wine_server_user_handle( hwnd );
|
||||
req->msg = WM_TIMER;
|
||||
req->id = id;
|
||||
req->rate = max( timeout, SYS_TIMER_RATE );
|
||||
req->rate = timeout;
|
||||
req->lparam = (ULONG_PTR)winproc;
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
|
@ -4416,12 +4418,16 @@ UINT_PTR WINAPI SetSystemTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC
|
|||
|
||||
if (proc) winproc = WINPROC_AllocProc( (WNDPROC)proc, FALSE );
|
||||
|
||||
/* MSDN states that the minimum timeout should be USER_TIMER_MINIMUM (10.0 ms), but testing
|
||||
* indicates that the true minimum is closer to 15.6 ms. */
|
||||
timeout = min( max( 15, timeout ), USER_TIMER_MAXIMUM );
|
||||
|
||||
SERVER_START_REQ( set_win_timer )
|
||||
{
|
||||
req->win = wine_server_user_handle( hwnd );
|
||||
req->msg = WM_SYSTIMER;
|
||||
req->id = id;
|
||||
req->rate = max( timeout, SYS_TIMER_RATE );
|
||||
req->rate = timeout;
|
||||
req->lparam = (ULONG_PTR)winproc;
|
||||
if (!wine_server_call_err( req ))
|
||||
{
|
||||
|
|
|
@ -1722,6 +1722,8 @@ static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK);
|
|||
static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
|
||||
static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
|
||||
static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,DWORD);
|
||||
static UINT_PTR (WINAPI *pSetSystemTimer)(HWND, UINT_PTR, UINT, TIMERPROC);
|
||||
static UINT_PTR (WINAPI *pKillSystemTimer)(HWND, UINT_PTR);
|
||||
/* kernel32 functions */
|
||||
static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA);
|
||||
|
||||
|
@ -1746,6 +1748,8 @@ static void init_procs(void)
|
|||
GET_PROC(user32, GetMonitorInfoA)
|
||||
GET_PROC(user32, MonitorFromPoint)
|
||||
GET_PROC(user32, UpdateLayeredWindow)
|
||||
GET_PROC(user32, SetSystemTimer)
|
||||
GET_PROC(user32, KillSystemTimer)
|
||||
|
||||
GET_PROC(kernel32, GetCPInfoExA)
|
||||
|
||||
|
@ -8157,6 +8161,14 @@ static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime)
|
|||
}
|
||||
|
||||
#define TIMER_ID 0x19
|
||||
#define TIMER_COUNT_EXPECTED 64
|
||||
#define TIMER_COUNT_TOLERANCE 9
|
||||
|
||||
static int count = 0;
|
||||
static void CALLBACK callback_count(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
static DWORD WINAPI timer_thread_proc(LPVOID x)
|
||||
{
|
||||
|
@ -8176,7 +8188,9 @@ static DWORD WINAPI timer_thread_proc(LPVOID x)
|
|||
static void test_timers(void)
|
||||
{
|
||||
struct timer_info info;
|
||||
DWORD start;
|
||||
DWORD id;
|
||||
MSG msg;
|
||||
|
||||
info.hWnd = CreateWindow ("TestWindowClass", NULL,
|
||||
WS_OVERLAPPEDWINDOW ,
|
||||
|
@ -8198,23 +8212,53 @@ static void test_timers(void)
|
|||
|
||||
ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
|
||||
|
||||
ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
|
||||
}
|
||||
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
|
||||
* but testing indicates that the minimum timeout is actually about 15.6 ms. Since there is
|
||||
* some measurement error between test runs we're allowing for ±8 counts (~2 ms).
|
||||
*/
|
||||
count = 0;
|
||||
id = SetTimer(info.hWnd, TIMER_ID, 0, callback_count);
|
||||
ok(id != 0, "did not get id from SetTimer.\n");
|
||||
ok(id==TIMER_ID, "SetTimer timer ID different\n");
|
||||
start = GetTickCount();
|
||||
while (GetTickCount()-start < 1001 && GetMessage(&msg, info.hWnd, 0, 0))
|
||||
DispatchMessage(&msg);
|
||||
ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE
|
||||
|| broken(abs(count-43) < TIMER_COUNT_TOLERANCE) /* w2k3 */,
|
||||
"did not get expected count for minimum timeout (%d != ~%d).\n",
|
||||
count, TIMER_COUNT_EXPECTED);
|
||||
ok(KillTimer(info.hWnd, id), "KillTimer failed\n");
|
||||
/* Perform the same check on SetSystemTimer (only available on w2k3 and older) */
|
||||
if (pSetSystemTimer)
|
||||
{
|
||||
int syscount = 0;
|
||||
|
||||
static int count = 0;
|
||||
static VOID CALLBACK callback_count(
|
||||
HWND hwnd,
|
||||
UINT uMsg,
|
||||
UINT_PTR idEvent,
|
||||
DWORD dwTime
|
||||
)
|
||||
{
|
||||
count++;
|
||||
count = 0;
|
||||
id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count);
|
||||
ok(id != 0, "did not get id from SetSystemTimer.\n");
|
||||
ok(id==TIMER_ID, "SetTimer timer ID different\n");
|
||||
start = GetTickCount();
|
||||
while (GetTickCount()-start < 1001 && GetMessage(&msg, info.hWnd, 0, 0))
|
||||
{
|
||||
if (msg.message == WM_SYSTIMER)
|
||||
syscount++;
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
ok(abs(syscount-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE,
|
||||
"did not get expected count for minimum timeout (%d != ~%d).\n",
|
||||
syscount, TIMER_COUNT_EXPECTED);
|
||||
todo_wine ok(count == 0, "did not get expected count for callback timeout (%d != 0).\n",
|
||||
count);
|
||||
ok(pKillSystemTimer(info.hWnd, id), "KillSystemTimer failed\n");
|
||||
}
|
||||
|
||||
ok(DestroyWindow(info.hWnd), "failed to destroy window\n");
|
||||
}
|
||||
|
||||
static void test_timers_no_wnd(void)
|
||||
{
|
||||
UINT_PTR id, id2;
|
||||
DWORD start;
|
||||
MSG msg;
|
||||
|
||||
count = 0;
|
||||
|
@ -8232,6 +8276,22 @@ static void test_timers_no_wnd(void)
|
|||
Sleep(250);
|
||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
|
||||
ok(count == 1, "killing replaced timer did not work (%i).\n", count);
|
||||
|
||||
/* Check the minimum allowed timeout for a timer. MSDN indicates that it should be 10.0 ms,
|
||||
* but testing indicates that the minimum timeout is actually about 15.6 ms. Since there is
|
||||
* some measurement error between test runs we're allowing for ±8 counts (~2 ms).
|
||||
*/
|
||||
count = 0;
|
||||
id = SetTimer(NULL, 0, 0, callback_count);
|
||||
ok(id != 0, "did not get id from SetTimer.\n");
|
||||
start = GetTickCount();
|
||||
while (GetTickCount()-start < 1001 && GetMessage(&msg, NULL, 0, 0))
|
||||
DispatchMessage(&msg);
|
||||
ok(abs(count-TIMER_COUNT_EXPECTED) < TIMER_COUNT_TOLERANCE,
|
||||
"did not get expected count for minimum timeout (%d != ~%d).\n",
|
||||
count, TIMER_COUNT_EXPECTED);
|
||||
KillTimer(NULL, id);
|
||||
/* Note: SetSystemTimer doesn't support a NULL window, see test_timers */
|
||||
}
|
||||
|
||||
/* Various win events with arbitrary parameters */
|
||||
|
|
|
@ -2521,6 +2521,10 @@ typedef struct tagMINIMIZEDMETRICS {
|
|||
#define PM_QS_PAINT (QS_PAINT << 16)
|
||||
#define PM_QS_SENDMESSAGE (QS_SENDMESSAGE << 16)
|
||||
|
||||
/* SetTimer() limits */
|
||||
#define USER_TIMER_MINIMUM 0x0000000A
|
||||
#define USER_TIMER_MAXIMUM 0x7FFFFFFF
|
||||
|
||||
/* AnimateWindow() flags */
|
||||
#define AW_SLIDE 0x00040000
|
||||
#define AW_ACTIVATE 0x00020000
|
||||
|
|
Loading…
Reference in New Issue