mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 15:52:11 +00:00
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 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 */
|
/* the various structures that can be sent in messages, in platform-independent layout */
|
||||||
struct packed_CREATESTRUCTW
|
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 );
|
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 )
|
SERVER_START_REQ( set_win_timer )
|
||||||
{
|
{
|
||||||
req->win = wine_server_user_handle( hwnd );
|
req->win = wine_server_user_handle( hwnd );
|
||||||
req->msg = WM_TIMER;
|
req->msg = WM_TIMER;
|
||||||
req->id = id;
|
req->id = id;
|
||||||
req->rate = max( timeout, SYS_TIMER_RATE );
|
req->rate = timeout;
|
||||||
req->lparam = (ULONG_PTR)winproc;
|
req->lparam = (ULONG_PTR)winproc;
|
||||||
if (!wine_server_call_err( req ))
|
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 );
|
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 )
|
SERVER_START_REQ( set_win_timer )
|
||||||
{
|
{
|
||||||
req->win = wine_server_user_handle( hwnd );
|
req->win = wine_server_user_handle( hwnd );
|
||||||
req->msg = WM_SYSTIMER;
|
req->msg = WM_SYSTIMER;
|
||||||
req->id = id;
|
req->id = id;
|
||||||
req->rate = max( timeout, SYS_TIMER_RATE );
|
req->rate = timeout;
|
||||||
req->lparam = (ULONG_PTR)winproc;
|
req->lparam = (ULONG_PTR)winproc;
|
||||||
if (!wine_server_call_err( req ))
|
if (!wine_server_call_err( req ))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1722,6 +1722,8 @@ static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK);
|
||||||
static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
|
static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
|
||||||
static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
|
static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
|
||||||
static BOOL (WINAPI *pUpdateLayeredWindow)(HWND,HDC,POINT*,SIZE*,HDC,POINT*,COLORREF,BLENDFUNCTION*,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 */
|
/* kernel32 functions */
|
||||||
static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA);
|
static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA);
|
||||||
|
|
||||||
|
@ -1746,6 +1748,8 @@ static void init_procs(void)
|
||||||
GET_PROC(user32, GetMonitorInfoA)
|
GET_PROC(user32, GetMonitorInfoA)
|
||||||
GET_PROC(user32, MonitorFromPoint)
|
GET_PROC(user32, MonitorFromPoint)
|
||||||
GET_PROC(user32, UpdateLayeredWindow)
|
GET_PROC(user32, UpdateLayeredWindow)
|
||||||
|
GET_PROC(user32, SetSystemTimer)
|
||||||
|
GET_PROC(user32, KillSystemTimer)
|
||||||
|
|
||||||
GET_PROC(kernel32, GetCPInfoExA)
|
GET_PROC(kernel32, GetCPInfoExA)
|
||||||
|
|
||||||
|
@ -8156,7 +8160,15 @@ static VOID CALLBACK tfunc(HWND hwnd, UINT uMsg, UINT_PTR id, DWORD dwTime)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TIMER_ID 0x19
|
#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)
|
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)
|
static void test_timers(void)
|
||||||
{
|
{
|
||||||
struct timer_info info;
|
struct timer_info info;
|
||||||
|
DWORD start;
|
||||||
DWORD id;
|
DWORD id;
|
||||||
|
MSG msg;
|
||||||
|
|
||||||
info.hWnd = CreateWindow ("TestWindowClass", NULL,
|
info.hWnd = CreateWindow ("TestWindowClass", NULL,
|
||||||
WS_OVERLAPPEDWINDOW ,
|
WS_OVERLAPPEDWINDOW ,
|
||||||
|
@ -8198,23 +8212,53 @@ static void test_timers(void)
|
||||||
|
|
||||||
ok( KillTimer(info.hWnd, TIMER_ID), "KillTimer failed\n");
|
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;
|
count = 0;
|
||||||
static VOID CALLBACK callback_count(
|
id = pSetSystemTimer(info.hWnd, TIMER_ID, 0, callback_count);
|
||||||
HWND hwnd,
|
ok(id != 0, "did not get id from SetSystemTimer.\n");
|
||||||
UINT uMsg,
|
ok(id==TIMER_ID, "SetTimer timer ID different\n");
|
||||||
UINT_PTR idEvent,
|
start = GetTickCount();
|
||||||
DWORD dwTime
|
while (GetTickCount()-start < 1001 && GetMessage(&msg, info.hWnd, 0, 0))
|
||||||
)
|
{
|
||||||
{
|
if (msg.message == WM_SYSTIMER)
|
||||||
count++;
|
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)
|
static void test_timers_no_wnd(void)
|
||||||
{
|
{
|
||||||
UINT_PTR id, id2;
|
UINT_PTR id, id2;
|
||||||
|
DWORD start;
|
||||||
MSG msg;
|
MSG msg;
|
||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -8232,6 +8276,22 @@ static void test_timers_no_wnd(void)
|
||||||
Sleep(250);
|
Sleep(250);
|
||||||
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) DispatchMessage(&msg);
|
||||||
ok(count == 1, "killing replaced timer did not work (%i).\n", count);
|
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 */
|
/* Various win events with arbitrary parameters */
|
||||||
|
|
|
@ -2521,6 +2521,10 @@ typedef struct tagMINIMIZEDMETRICS {
|
||||||
#define PM_QS_PAINT (QS_PAINT << 16)
|
#define PM_QS_PAINT (QS_PAINT << 16)
|
||||||
#define PM_QS_SENDMESSAGE (QS_SENDMESSAGE << 16)
|
#define PM_QS_SENDMESSAGE (QS_SENDMESSAGE << 16)
|
||||||
|
|
||||||
|
/* SetTimer() limits */
|
||||||
|
#define USER_TIMER_MINIMUM 0x0000000A
|
||||||
|
#define USER_TIMER_MAXIMUM 0x7FFFFFFF
|
||||||
|
|
||||||
/* AnimateWindow() flags */
|
/* AnimateWindow() flags */
|
||||||
#define AW_SLIDE 0x00040000
|
#define AW_SLIDE 0x00040000
|
||||||
#define AW_ACTIVATE 0x00020000
|
#define AW_ACTIVATE 0x00020000
|
||||||
|
|
Loading…
Reference in a new issue