Author: jimtabor Date: Mon Aug 22 21:07:39 2011 New Revision: 53386
URL: http://svn.reactos.org/svn/reactos?rev=53386&view=rev Log: [WineTest:User32] - Up msg to 1.3.26.
Modified: trunk/rostests/winetests/user32/msg.c
Modified: trunk/rostests/winetests/user32/msg.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/user32/msg.c?rev... ============================================================================== --- trunk/rostests/winetests/user32/msg.c [iso-8859-1] (original) +++ trunk/rostests/winetests/user32/msg.c [iso-8859-1] Mon Aug 22 21:07:39 2011 @@ -20,8 +20,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#define _WIN32_WINNT 0x0600 /* For WM_CHANGEUISTATE,QS_RAWINPUT,WM_DWMxxxx */ -#define WINVER 0x0600 /* for WM_GETTITLEBARINFOEX */ +//#define _WIN32_WINNT 0x0600 /* For WM_CHANGEUISTATE,QS_RAWINPUT,WM_DWMxxxx */ +//#define WINVER 0x0600 /* for WM_GETTITLEBARINFOEX */
#include <assert.h> #include <stdarg.h> @@ -79,6 +79,7 @@
static BOOL test_DestroyWindow_flag; static HWINEVENTHOOK hEvent_hook; +static HHOOK hKBD_hook; static HHOOK hCBT_hook; static DWORD cbt_hook_thread_id;
@@ -105,7 +106,8 @@ beginpaint=0x40, optional=0x80, hook=0x100, - winevent_hook=0x200 + winevent_hook=0x200, + kbd_hook=0x400 } msg_flags_t;
struct message { @@ -293,7 +295,7 @@ { WM_NCACTIVATE, sent|wparam|defwinproc, 0 }, /* in the 2nd MDI child */ { WM_MDIACTIVATE, sent|defwinproc }, /* in the 2nd MDI child */ { HCBT_MINMAX, hook|lparam, 0, SW_MAXIMIZE }, - /* Preparing for maximize and maximaze the 1st MDI child */ + /* Preparing for maximize and maximize the 1st MDI child */ { WM_GETMINMAXINFO, sent|defwinproc }, /* in the 1st MDI child */ { WM_WINDOWPOSCHANGING, sent|wparam|defwinproc, SWP_FRAMECHANGED|SWP_STATECHANGED }, /* in the 1st MDI child */ { WM_NCCALCSIZE, sent|wparam|defwinproc, 1 }, /* in the 1st MDI child */ @@ -1717,6 +1719,8 @@ static HWINEVENTHOOK (WINAPI *pSetWinEventHook)(DWORD, DWORD, HMODULE, WINEVENTPROC, DWORD, DWORD, DWORD); static BOOL (WINAPI *pTrackMouseEvent)(TRACKMOUSEEVENT*); static BOOL (WINAPI *pUnhookWinEvent)(HWINEVENTHOOK); +static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO); +static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD); /* kernel32 functions */ static BOOL (WINAPI *pGetCPInfoExA)(UINT, DWORD, LPCPINFOEXA);
@@ -1738,6 +1742,8 @@ GET_PROC(user32, SetWinEventHook) GET_PROC(user32, TrackMouseEvent) GET_PROC(user32, UnhookWinEvent) + GET_PROC(user32, GetMonitorInfoA) + GET_PROC(user32, MonitorFromPoint)
GET_PROC(kernel32, GetCPInfoExA)
@@ -1938,6 +1944,11 @@ else if (expected->flags & winevent_hook) { trace_(file, line)( " %u: expected: winevent %04x - actual: %s\n", + count, expected->message, actual->output ); + } + else if (expected->flags & kbd_hook) + { + trace_(file, line)( " %u: expected: kbd %04x - actual: %s\n", count, expected->message, actual->output ); } else @@ -2014,7 +2025,8 @@
while (expected->message && actual->message) { - if (expected->message == actual->message) + if (expected->message == actual->message && + !((expected->flags ^ actual->flags) & (hook|winevent_hook|kbd_hook))) { if (expected->flags & wparam) { @@ -2108,13 +2120,19 @@ context, count, expected->message); if ((expected->flags & winevent_hook) != (actual->flags & winevent_hook)) dump++;
+ ok_( file, line) ((expected->flags & kbd_hook) == (actual->flags & kbd_hook), + "%s: %u: the msg 0x%04x should have been sent by a keyboard hook\n", + context, count, expected->message); + if ((expected->flags & kbd_hook) != (actual->flags & kbd_hook)) dump++; + expected++; actual++; } /* silently drop hook messages if there is no support for them */ else if ((expected->flags & optional) || ((expected->flags & hook) && !hCBT_hook) || - ((expected->flags & winevent_hook) && !hEvent_hook)) + ((expected->flags & winevent_hook) && !hEvent_hook) || + ((expected->flags & kbd_hook) && !hKBD_hook)) expected++; else if (todo) { @@ -3363,7 +3381,7 @@ RECT rc; HMENU hMenu = CreateMenu();
- assert(mdi_RegisterWindowClasses()); + if (!mdi_RegisterWindowClasses()) assert(0);
flush_sequence();
@@ -6157,6 +6175,16 @@ flush_events(); ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE );
+ trace("testing UpdateWindow(NULL)\n"); + SetLastError(0xdeadbeef); + ok(!UpdateWindow(NULL), "UpdateWindow(NULL) should fail\n"); + ok(GetLastError() == ERROR_INVALID_WINDOW_HANDLE || + broken( GetLastError() == 0xdeadbeef ) /* win9x */, + "wrong error code %d\n", GetLastError()); + check_update_rgn( hwnd, 0 ); + flush_events(); + ok_sequence( WmEmptySeq, "WmEmptySeq", FALSE ); + /* now with frame */ SetRectRgn( hrgn, -5, -5, 20, 20 );
@@ -6701,7 +6729,7 @@ CloseHandle(wnd_event.start_event);
SetLastError(0xdeadbeef); - ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeded\n"); + ok(!DestroyWindow(wnd_event.hwnd), "DestroyWindow succeeded\n"); ok(GetLastError() == ERROR_ACCESS_DENIED || GetLastError() == 0xdeadbeef, "wrong error code %d\n", GetLastError());
@@ -6723,7 +6751,7 @@ SetLastError(0xdeadbeef); len = DispatchMessageA(&msg); ok((!len && GetLastError() == ERROR_MESSAGE_SYNC_ONLY) || broken(len), /* nt4 */ - "DispatchMessageA(WM_GETTEXT) succeded on another thread window: ret %d, error %d\n", len, GetLastError()); + "DispatchMessageA(WM_GETTEXT) succeeded on another thread window: ret %d, error %d\n", len, GetLastError());
/* the following test causes an exception in user.exe under win9x */ msg.hwnd = wnd_event.hwnd; @@ -7686,6 +7714,49 @@ return DefWindowProcA(hWnd,msg,wParam,lParam); }
+static LRESULT WINAPI HotkeyMsgCheckProcA(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static LONG defwndproc_counter = 0; + LRESULT ret; + struct recvd_message msg; + DWORD queue_status; + + if (ignore_message( message )) return 0; + + if ((message >= WM_KEYFIRST && message <= WM_KEYLAST) || + message == WM_HOTKEY || message >= WM_APP) + { + msg.hwnd = hwnd; + msg.message = message; + msg.flags = sent|wparam|lparam; + if (defwndproc_counter) msg.flags |= defwinproc; + msg.wParam = wParam; + msg.lParam = lParam; + msg.descr = "HotkeyMsgCheckProcA"; + add_message(&msg); + } + + defwndproc_counter++; + ret = DefWindowProcA(hwnd, message, wParam, lParam); + defwndproc_counter--; + + if (message == WM_APP) + { + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); + queue_status = GetQueueStatus(QS_POSTMESSAGE); + ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); + PostMessageA(hwnd, WM_APP+1, 0, 0); + } + else if (message == WM_APP+1) + { + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); + } + + return ret; +} + static BOOL RegisterWindowClasses(void) { WNDCLASSA cls; @@ -7701,6 +7772,10 @@ cls.hbrBackground = GetStockObject(WHITE_BRUSH); cls.lpszMenuName = NULL; cls.lpszClassName = "TestWindowClass"; + if(!RegisterClassA(&cls)) return FALSE; + + cls.lpfnWndProc = HotkeyMsgCheckProcA; + cls.lpszClassName = "HotkeyWindowClass"; if(!RegisterClassA(&cls)) return FALSE;
cls.lpfnWndProc = ShowWindowProcA; @@ -10012,6 +10087,50 @@ flush_events(); }
+static INT_PTR CALLBACK wm_quit_dlg_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) +{ + struct recvd_message msg; + + if (ignore_message( message )) return 0; + + msg.hwnd = hwnd; + msg.message = message; + msg.flags = sent|wparam|lparam; + msg.wParam = wp; + msg.lParam = lp; + msg.descr = "dialog"; + add_message(&msg); + + switch (message) + { + case WM_INITDIALOG: + PostMessage(hwnd, WM_QUIT, 0x1234, 0x5678); + PostMessage(hwnd, WM_USER, 0xdead, 0xbeef); + return 0; + + case WM_GETDLGCODE: + return 0; + + case WM_USER: + EndDialog(hwnd, 0); + break; + } + + return 1; +} + +static const struct message WmQuitDialogSeq[] = { + { HCBT_CREATEWND, hook }, + { WM_SETFONT, sent }, + { WM_INITDIALOG, sent }, + { WM_CHANGEUISTATE, sent|optional }, + { HCBT_DESTROYWND, hook }, + { 0x0090, sent|optional }, /* Vista */ + { WM_DESTROY, sent }, + { WM_NCDESTROY, sent }, + { 0 } +}; + static void test_quit_message(void) { MSG msg; @@ -10062,6 +10181,18 @@ ret = GetMessage(&msg, NULL, 0, 0); ok(ret > 0, "GetMessage failed with error %d\n", GetLastError()); ok(msg.message == WM_USER, "Received message 0x%04x instead of WM_USER\n", msg.message); + + flush_events(); + flush_sequence(); + ret = DialogBoxParam(GetModuleHandle(0), "TEST_EMPTY_DIALOG", 0, wm_quit_dlg_proc, 0); + ok(ret == 1, "expected 1, got %d\n", ret); + ok_sequence(WmQuitDialogSeq, "WmQuitDialogSeq", FALSE); + memset(&msg, 0xab, sizeof(msg)); + ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); + ok(ret, "PeekMessage failed\n"); + ok(msg.message == WM_QUIT, "Received message 0x%04x instead of WM_QUIT\n", msg.message); + ok(msg.wParam == 0x1234, "wParam was 0x%lx instead of 0x1234\n", msg.wParam); + ok(msg.lParam == 0, "lParam was 0x%lx instead of 0\n", msg.lParam); }
static const struct message WmMouseHoverSeq[] = { @@ -10631,71 +10762,132 @@ LPARAM ret; /* ShowWindow return value */ DWORD style; /* window style after the command */ const struct message *msg; /* message sequence the command produces */ + INT wp_cmd, wp_flags; /* window placement after the command */ + POINT wp_min, wp_max; /* window placement after the command */ BOOL todo_msg; /* message sequence doesn't match what Wine does */ } sw[] = { -/* 1 */ { SW_SHOWNORMAL, FALSE, WS_VISIBLE, WmShowNormal, FALSE }, -/* 2 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 3 */ { SW_HIDE, TRUE, 0, WmHide_1, FALSE }, -/* 4 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 5 */ { SW_SHOWMINIMIZED, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinimized_1, FALSE }, -/* 6 */ { SW_SHOWMINIMIZED, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_1, FALSE }, -/* 7 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_1, FALSE }, -/* 8 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE }, -/* 9 */ { SW_SHOWMAXIMIZED, FALSE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_1, FALSE }, -/* 10 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, FALSE }, -/* 11 */ { SW_HIDE, TRUE, WS_MAXIMIZE, WmHide_1, FALSE }, -/* 12 */ { SW_HIDE, FALSE, WS_MAXIMIZE, WmEmptySeq, FALSE }, -/* 13 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_1, FALSE }, -/* 14 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 15 */ { SW_HIDE, TRUE, 0, WmHide_2, FALSE }, -/* 16 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 17 */ { SW_SHOW, FALSE, WS_VISIBLE, WmShow, FALSE }, -/* 18 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 19 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, FALSE }, -/* 20 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, FALSE }, -/* 21 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE }, -/* 22 */ { SW_SHOWMINNOACTIVE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinNoActivate, TRUE }, -/* 23 */ { SW_SHOWMINNOACTIVE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_4, FALSE }, -/* 24 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE }, -/* 25 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE }, -/* 26 */ { SW_SHOWNA, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_1, FALSE }, -/* 27 */ { SW_SHOWNA, TRUE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_2, FALSE }, -/* 28 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE }, -/* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, FALSE }, -/* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, FALSE }, -/* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, FALSE }, -/* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, FALSE }, /* what does this mean?! */ -/* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, FALSE }, -/* 36 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 37 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_2, FALSE }, -/* 38 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 39 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, FALSE }, -/* 40 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_2, FALSE }, -/* 41 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, FALSE }, -/* 42 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_2, FALSE }, -/* 43 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, FALSE }, -/* 44 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, FALSE }, -/* 45 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, FALSE }, -/* 46 */ { SW_RESTORE, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmRestore_3, FALSE }, -/* 47 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmRestore_4, FALSE }, -/* 48 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_3, FALSE }, -/* 49 */ { SW_SHOW, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmEmptySeq, FALSE }, -/* 50 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, FALSE }, -/* 51 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, FALSE }, -/* 52 */ { SW_HIDE, TRUE, 0, WmHide_1, FALSE }, -/* 53 */ { SW_HIDE, FALSE, 0, WmEmptySeq, FALSE }, -/* 54 */ { SW_MINIMIZE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_3, FALSE }, -/* 55 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, FALSE }, -/* 56 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_2, FALSE }, -/* 57 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, FALSE } +/* 1 */ { SW_SHOWNORMAL, FALSE, WS_VISIBLE, WmShowNormal, + SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, +/* 2 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, +/* 3 */ { SW_HIDE, TRUE, 0, WmHide_1, + SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, +/* 4 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-1,-1}, {-1,-1}, FALSE }, +/* 5 */ { SW_SHOWMINIMIZED, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinimized_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 6 */ { SW_SHOWMINIMIZED, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 7 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 8 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 9 */ { SW_SHOWMAXIMIZED, FALSE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_1, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 10 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 11 */ { SW_HIDE, TRUE, WS_MAXIMIZE, WmHide_1, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 12 */ { SW_HIDE, FALSE, WS_MAXIMIZE, WmEmptySeq, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 13 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_1, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 14 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 15 */ { SW_HIDE, TRUE, 0, WmHide_2, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 16 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 17 */ { SW_SHOW, FALSE, WS_VISIBLE, WmShow, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 18 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 19 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 20 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 21 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 22 */ { SW_SHOWMINNOACTIVE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowMinNoActivate, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, TRUE }, +/* 23 */ { SW_SHOWMINNOACTIVE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_4, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 24 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 25 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 26 */ { SW_SHOWNA, FALSE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_1, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 27 */ { SW_SHOWNA, TRUE, WS_VISIBLE|WS_MINIMIZE, WmShowNA_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 28 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 29 */ { SW_HIDE, FALSE, WS_MINIMIZE, WmEmptySeq, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 30 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_1, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 31 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 32 */ { SW_HIDE, TRUE, 0, WmHide_3, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 33 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 34 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, /* what does this mean?! */ + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 35 */ { SW_NORMALNA, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 36 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 37 */ { SW_RESTORE, FALSE, WS_VISIBLE, WmRestore_2, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 38 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 39 */ { SW_SHOWNOACTIVATE, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 40 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 41 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 42 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_2, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 43 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmMinMax_2, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 44 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_1, + SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 45 */ { SW_MINIMIZE, TRUE, WS_VISIBLE|WS_MINIMIZE, WmMinMax_3, + SW_SHOWMINIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 46 */ { SW_RESTORE, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmRestore_3, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 47 */ { SW_RESTORE, TRUE, WS_VISIBLE, WmRestore_4, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 48 */ { SW_SHOWMAXIMIZED, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmShowMaximized_3, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 49 */ { SW_SHOW, TRUE, WS_VISIBLE|WS_MAXIMIZE, WmEmptySeq, + SW_SHOWMAXIMIZED, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 50 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 51 */ { SW_SHOWNORMAL, TRUE, WS_VISIBLE, WmRestore_5, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 52 */ { SW_HIDE, TRUE, 0, WmHide_1, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 53 */ { SW_HIDE, FALSE, 0, WmEmptySeq, + SW_SHOWNORMAL, WPF_RESTORETOMAXIMIZED, {-32000,-32000}, {-1,-1}, FALSE }, +/* 54 */ { SW_MINIMIZE, FALSE, WS_VISIBLE|WS_MINIMIZE, WmMinimize_3, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 55 */ { SW_HIDE, TRUE, WS_MINIMIZE, WmHide_2, + SW_SHOWMINIMIZED, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 56 */ { SW_SHOWNOACTIVATE, FALSE, WS_VISIBLE, WmShowNoActivate_2, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE }, +/* 57 */ { SW_SHOW, TRUE, WS_VISIBLE, WmEmptySeq, + SW_SHOWNORMAL, 0, {-32000,-32000}, {-1,-1}, FALSE } }; HWND hwnd; DWORD style; LPARAM ret; INT i; + WINDOWPLACEMENT wp; + RECT win_rc, work_rc = {0, 0, 0, 0};
#define WS_BASE (WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_MAXIMIZEBOX|WS_POPUP|WS_CLIPSIBLINGS) hwnd = CreateWindowEx(0, "ShowWindowClass", NULL, WS_BASE, @@ -10708,6 +10900,52 @@
flush_events(); flush_sequence(); + + if (pGetMonitorInfoA && pMonitorFromPoint) + { + HMONITOR hmon; + MONITORINFO mi; + POINT pt = {0, 0}; + + SetLastError(0xdeadbeef); + hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); + ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError()); + + mi.cbSize = sizeof(mi); + SetLastError(0xdeadbeef); + ret = pGetMonitorInfoA(hmon, &mi); + ok(ret, "GetMonitorInfo error %u\n", GetLastError()); + trace("monitor (%d,%d-%d,%d), work (%d,%d-%d,%d)\n", + mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom, + mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom); + work_rc = mi.rcWork; + } + + GetWindowRect(hwnd, &win_rc); + OffsetRect(&win_rc, -work_rc.left, -work_rc.top); + + wp.length = sizeof(wp); + SetLastError(0xdeadbeaf); + ret = GetWindowPlacement(hwnd, &wp); + ok(ret, "GetWindowPlacement error %u\n", GetLastError()); + ok(wp.flags == 0, "expected 0, got %#x\n", wp.flags); + ok(wp.showCmd == SW_SHOWNORMAL, "expected SW_SHOWNORMAL, got %d\n", wp.showCmd); + ok(wp.ptMinPosition.x == -1 && wp.ptMinPosition.y == -1, + "expected -1,-1 got %d,%d\n", wp.ptMinPosition.x, wp.ptMinPosition.y); + ok(wp.ptMaxPosition.x == -1 && wp.ptMaxPosition.y == -1, + "expected -1,-1 got %d,%d\n", wp.ptMaxPosition.x, wp.ptMaxPosition.y); + if (work_rc.left || work_rc.top) todo_wine /* FIXME: remove once Wine is fixed */ + ok(EqualRect(&win_rc, &wp.rcNormalPosition), + "expected %d,%d-%d,%d got %d,%d-%d,%d\n", + win_rc.left, win_rc.top, win_rc.right, win_rc.bottom, + wp.rcNormalPosition.left, wp.rcNormalPosition.top, + wp.rcNormalPosition.right, wp.rcNormalPosition.bottom); + else + ok(EqualRect(&win_rc, &wp.rcNormalPosition), + "expected %d,%d-%d,%d got %d,%d-%d,%d\n", + win_rc.left, win_rc.top, win_rc.right, win_rc.bottom, + wp.rcNormalPosition.left, wp.rcNormalPosition.top, + wp.rcNormalPosition.right, wp.rcNormalPosition.bottom);
for (i = 0; i < sizeof(sw)/sizeof(sw[0]); i++) { @@ -10732,6 +10970,47 @@
sprintf(comment, "%d: ShowWindow(%s)", i+1, sw_cmd_name[idx]); ok_sequence(sw[i].msg, comment, sw[i].todo_msg); + + wp.length = sizeof(wp); + SetLastError(0xdeadbeaf); + ret = GetWindowPlacement(hwnd, &wp); + ok(ret, "GetWindowPlacement error %u\n", GetLastError()); + ok(wp.flags == sw[i].wp_flags, "expected %#x, got %#x\n", sw[i].wp_flags, wp.flags); + ok(wp.showCmd == sw[i].wp_cmd, "expected %d, got %d\n", sw[i].wp_cmd, wp.showCmd); + + /* NT moves the minimized window to -32000,-32000, win9x to 3000,3000 */ + if ((wp.ptMinPosition.x + work_rc.left == -32000 && wp.ptMinPosition.y + work_rc.top == -32000) || + (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000)) + { + ok((wp.ptMinPosition.x + work_rc.left == sw[i].wp_min.x && wp.ptMinPosition.y + work_rc.top == sw[i].wp_min.y) || + (wp.ptMinPosition.x + work_rc.left == 3000 && wp.ptMinPosition.y + work_rc.top == 3000), + "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); + } + else + { + if (wp.ptMinPosition.x != sw[i].wp_min.x || wp.ptMinPosition.y != sw[i].wp_min.y) + todo_wine + ok(wp.ptMinPosition.x == sw[i].wp_min.x && wp.ptMinPosition.y == sw[i].wp_min.y, + "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); + else + ok(wp.ptMinPosition.x == sw[i].wp_min.x && wp.ptMinPosition.y == sw[i].wp_min.y, + "expected %d,%d got %d,%d\n", sw[i].wp_min.x, sw[i].wp_min.y, wp.ptMinPosition.x, wp.ptMinPosition.y); + } + + if (wp.ptMaxPosition.x != sw[i].wp_max.x || wp.ptMaxPosition.y != sw[i].wp_max.y) + todo_wine + ok(wp.ptMaxPosition.x == sw[i].wp_max.x && wp.ptMaxPosition.y == sw[i].wp_max.y, + "expected %d,%d got %d,%d\n", sw[i].wp_max.x, sw[i].wp_max.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y); + else + ok(wp.ptMaxPosition.x == sw[i].wp_max.x && wp.ptMaxPosition.y == sw[i].wp_max.y, + "expected %d,%d got %d,%d\n", sw[i].wp_max.x, sw[i].wp_max.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y); + +if (0) /* FIXME: Wine behaves completely different here */ + ok(EqualRect(&win_rc, &wp.rcNormalPosition), + "expected %d,%d-%d,%d got %d,%d-%d,%d\n", + win_rc.left, win_rc.top, win_rc.right, win_rc.bottom, + wp.rcNormalPosition.left, wp.rcNormalPosition.top, + wp.rcNormalPosition.right, wp.rcNormalPosition.bottom);
flush_events(); flush_sequence(); @@ -11419,6 +11698,7 @@ ok( !PeekMessageA( &msg, hwnd, 0, 0, PM_REMOVE ), "got message %x\n", msg.message );
DestroyWindow(hwnd); + DestroyWindow(hwnd2); }
#define ID_LISTBOX 0x000f @@ -11746,6 +12026,33 @@ { 0 } };
+static const struct message wm_single_menu_item[] = +{ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, VK_MENU, 0x20000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0x20000001 }, + { WM_SYSKEYDOWN, sent|wparam|lparam, 'Q', 0x20000001 }, + { WM_SYSCHAR, sent|wparam|lparam, 'q', 0x20000001 }, + { HCBT_SYSCOMMAND, hook|wparam|lparam, SC_KEYMENU, 'q' }, + { WM_ENTERMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_INITMENU, sent|lparam, 0, 0 }, + { WM_MENUSELECT, sent|wparam|optional, MAKEWPARAM(300,MF_HILITE) }, + { WM_MENUSELECT, sent|wparam|lparam, MAKEWPARAM(0,0xffff), 0 }, + { WM_EXITMENULOOP, sent|wparam|lparam, 0, 0 }, + { WM_MENUCOMMAND, sent }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 'Q', 0xe0000001 }, + { WM_SYSKEYUP, sent|wparam|lparam, 'Q', 0xe0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_MENU, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_MENU, 0xc0000001 }, + + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 1 }, + { WM_KEYDOWN, sent|wparam|lparam, VK_ESCAPE, 1 }, + { WM_CHAR, sent|wparam|lparam, VK_ESCAPE, 0x00000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_ESCAPE, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_ESCAPE, 0xc0000001 }, + { 0 } +}; + static LRESULT WINAPI parent_menu_proc(HWND hwnd, UINT message, WPARAM wp, LPARAM lp) { if (message == WM_ENTERIDLE || @@ -11903,6 +12210,21 @@ DispatchMessage(&msg); } ok_sequence(wm_popup_menu_2, "submenu of a popup menu command", FALSE); + + trace("testing single menu item command\n"); + flush_sequence(); + keybd_event(VK_MENU, 0, 0, 0); + keybd_event('Q', 0, 0, 0); + keybd_event('Q', 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_MENU, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_ESCAPE, 0, 0, 0); + keybd_event(VK_ESCAPE, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + ok_sequence(wm_single_menu_item, "single menu item command", FALSE);
set_menu_style(hmenu, 0); style = get_menu_style(hmenu); @@ -12501,11 +12823,611 @@ CloseHandle( thread ); }
+static const struct message WmSetParentSeq_1[] = { + { WM_SHOWWINDOW, sent|wparam, 0 }, + { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, + { WM_CHILDACTIVATE, sent }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOSIZE|SWP_NOREDRAW|SWP_NOCLIENTSIZE }, + { WM_MOVE, sent|defwinproc|wparam, 0 }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_SHOWWINDOW, sent|wparam, 1 }, + { 0 } +}; + +static const struct message WmSetParentSeq_2[] = { + { WM_SHOWWINDOW, sent|wparam, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE }, + { EVENT_OBJECT_HIDE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_HIDEWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { HCBT_SETFOCUS, hook|optional }, + { WM_NCACTIVATE, sent|wparam|optional, 0 }, + { WM_ACTIVATE, sent|wparam|optional, 0 }, + { WM_ACTIVATEAPP, sent|wparam|optional, 0 }, + { WM_KILLFOCUS, sent|wparam, 0 }, + { EVENT_OBJECT_PARENTCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_NOSIZE }, + { HCBT_ACTIVATE, hook|optional }, + { EVENT_SYSTEM_FOREGROUND, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGING, sent|wparam|optional, SWP_NOSIZE|SWP_NOMOVE }, + { WM_NCACTIVATE, sent|wparam|optional, 1 }, + { WM_ACTIVATE, sent|wparam|optional, 1 }, + { HCBT_SETFOCUS, hook|optional }, + { EVENT_OBJECT_FOCUS, winevent_hook|wparam|lparam, OBJID_CLIENT, 0 }, + { WM_SETFOCUS, sent|optional|defwinproc }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_NOREDRAW|SWP_NOSIZE|SWP_NOCLIENTSIZE }, + { WM_MOVE, sent|defwinproc|wparam, 0 }, + { EVENT_OBJECT_LOCATIONCHANGE, winevent_hook|wparam|lparam, 0, 0 }, + { WM_SHOWWINDOW, sent|wparam, 1 }, + { WM_WINDOWPOSCHANGING, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE }, + { EVENT_OBJECT_SHOW, winevent_hook|wparam|lparam, 0, 0 }, + { WM_WINDOWPOSCHANGED, sent|wparam, SWP_SHOWWINDOW|SWP_NOSIZE|SWP_NOMOVE|SWP_NOCLIENTSIZE|SWP_NOCLIENTMOVE }, + { 0 } +}; + + +static void test_SetParent(void) +{ + HWND parent1, parent2, child, popup; + RECT rc, rc_old; + + parent1 = CreateWindowEx(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, + 100, 100, 200, 200, 0, 0, 0, NULL); + ok(parent1 != 0, "Failed to create parent1 window\n"); + + parent2 = CreateWindowEx(0, "TestParentClass", NULL, WS_OVERLAPPEDWINDOW, + 400, 100, 200, 200, 0, 0, 0, NULL); + ok(parent2 != 0, "Failed to create parent2 window\n"); + + /* WS_CHILD window */ + child = CreateWindowEx(0, "TestWindowClass", NULL, WS_CHILD | WS_VISIBLE, + 10, 10, 150, 150, parent1, 0, 0, NULL); + ok(child != 0, "Failed to create child window\n"); + + GetWindowRect(parent1, &rc); + trace("parent1 (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + GetWindowRect(child, &rc_old); + MapWindowPoints(0, parent1, (POINT *)&rc_old, 2); + trace("child (%d,%d)-(%d,%d)\n", rc_old.left, rc_old.top, rc_old.right, rc_old.bottom); + + flush_sequence(); + + SetParent(child, parent2); + flush_events(); + ok_sequence(WmSetParentSeq_1, "SetParent() visible WS_CHILD", TRUE); + + ok(GetWindowLongA(child, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); + ok(!IsWindowVisible(child), "IsWindowVisible() should return FALSE\n"); + + GetWindowRect(parent2, &rc); + trace("parent2 (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + GetWindowRect(child, &rc); + MapWindowPoints(0, parent2, (POINT *)&rc, 2); + trace("child (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + + ok(EqualRect(&rc_old, &rc), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n", + rc_old.left, rc_old.top, rc_old.right, rc_old.bottom, + rc.left, rc.top, rc.right, rc.bottom ); + + /* WS_POPUP window */ + popup = CreateWindowEx(0, "TestWindowClass", NULL, WS_POPUP | WS_VISIBLE, + 20, 20, 100, 100, 0, 0, 0, NULL); + ok(popup != 0, "Failed to create popup window\n"); + + GetWindowRect(popup, &rc_old); + trace("popup (%d,%d)-(%d,%d)\n", rc_old.left, rc_old.top, rc_old.right, rc_old.bottom); + + flush_sequence(); + + SetParent(popup, child); + flush_events(); + ok_sequence(WmSetParentSeq_2, "SetParent() visible WS_POPUP", TRUE); + + ok(GetWindowLongA(popup, GWL_STYLE) & WS_VISIBLE, "WS_VISIBLE should be set\n"); + ok(!IsWindowVisible(popup), "IsWindowVisible() should return FALSE\n"); + + GetWindowRect(child, &rc); + trace("parent2 (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + GetWindowRect(popup, &rc); + MapWindowPoints(0, child, (POINT *)&rc, 2); + trace("popup (%d,%d)-(%d,%d)\n", rc.left, rc.top, rc.right, rc.bottom); + + ok(EqualRect(&rc_old, &rc), "rects do not match (%d,%d-%d,%d) / (%d,%d-%d,%d)\n", + rc_old.left, rc_old.top, rc_old.right, rc_old.bottom, + rc.left, rc.top, rc.right, rc.bottom ); + + DestroyWindow(popup); + DestroyWindow(child); + DestroyWindow(parent1); + DestroyWindow(parent2); + + flush_sequence(); +} + +static const struct message WmKeyReleaseOnly[] = { + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x80000001 }, + { WM_KEYUP, sent|wparam|lparam, 0x41, 0x80000001 }, + { 0 } +}; +static const struct message WmKeyPressNormal[] = { + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x1 }, + { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x1 }, + { 0 } +}; +static const struct message WmKeyPressRepeat[] = { + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0x40000001 }, + { WM_KEYDOWN, sent|wparam|lparam, 0x41, 0x40000001 }, + { 0 } +}; +static const struct message WmKeyReleaseNormal[] = { + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, 0x41, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, 0x41, 0xc0000001 }, + { 0 } +}; + +static void test_keyflags(void) +{ + HWND test_window; + SHORT key_state; + BYTE keyboard_state[256]; + MSG msg; + + test_window = CreateWindowEx(0, "TestWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + + flush_sequence(); + + /* keyup without a keydown */ + keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyReleaseOnly, "key release only", TRUE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + /* keydown */ + keybd_event(0x41, 0, 0, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyPressNormal, "key press only", FALSE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + /* keydown repeat */ + keybd_event(0x41, 0, 0, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyPressRepeat, "key press repeat", FALSE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + /* keyup */ + keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyReleaseNormal, "key release repeat", FALSE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + /* set the key state in this thread */ + GetKeyboardState(keyboard_state); + keyboard_state[0x41] = 0x80; + SetKeyboardState(keyboard_state); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + /* keydown */ + keybd_event(0x41, 0, 0, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyPressRepeat, "key press after setkeyboardstate", TRUE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + /* clear the key state in this thread */ + GetKeyboardState(keyboard_state); + keyboard_state[0x41] = 0; + SetKeyboardState(keyboard_state); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + /* keyup */ + keybd_event(0x41, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmKeyReleaseOnly, "key release after setkeyboardstate", TRUE); + + key_state = GetAsyncKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + key_state = GetKeyState(0x41); + ok((key_state & 0x8000) == 0, "unexpected key state %x\n", key_state); + + DestroyWindow(test_window); + flush_sequence(); +} + +static const struct message WmHotkeyPressLWIN[] = { + { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, + { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, + { 0 } +}; +static const struct message WmHotkeyPress[] = { + { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, + { WM_HOTKEY, sent|wparam, 5 }, + { 0 } +}; +static const struct message WmHotkeyRelease[] = { + { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, + { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 0x80000001 }, + { WM_KEYUP, sent|lparam, 0, 0x80000001 }, + { 0 } +}; +static const struct message WmHotkeyReleaseLWIN[] = { + { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, + { 0 } +}; +static const struct message WmHotkeyCombined[] = { + { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, + { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, + { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, + { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, + { WM_APP, sent, 0, 0 }, + { WM_HOTKEY, sent|wparam, 5 }, + { WM_APP+1, sent, 0, 0 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, + { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, + { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, + { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, + { 0 } +}; +static const struct message WmHotkeyPrevious[] = { + { WM_KEYDOWN, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED }, + { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, + { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, + { WM_KEYUP, kbd_hook|wparam|lparam, VK_LWIN, LLKHF_INJECTED|LLKHF_UP }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 1 }, + { WM_KEYDOWN, sent|wparam|lparam, VK_LWIN, 1 }, + { HCBT_KEYSKIPPED, hook|lparam|optional, 0, 1 }, + { WM_KEYDOWN, sent|lparam, 0, 1 }, + { HCBT_KEYSKIPPED, hook|optional|lparam, 0, 0xc0000001 }, + { WM_KEYUP, sent|lparam, 0, 0xc0000001 }, + { HCBT_KEYSKIPPED, hook|wparam|lparam|optional, VK_LWIN, 0xc0000001 }, + { WM_KEYUP, sent|wparam|lparam, VK_LWIN, 0xc0000001 }, + { 0 } +}; +static const struct message WmHotkeyNew[] = { + { WM_KEYDOWN, kbd_hook|lparam, 0, LLKHF_INJECTED }, + { WM_KEYUP, kbd_hook|lparam, 0, LLKHF_INJECTED|LLKHF_UP }, + { WM_HOTKEY, sent|wparam, 5 }, + { HCBT_KEYSKIPPED, hook|optional, 0, 0x80000001 }, + { WM_KEYUP, sent, 0, 0x80000001 }, /* lparam not checked so the sequence isn't a todo */ + { 0 } +}; + +static int hotkey_letter; + +static LRESULT CALLBACK KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + struct recvd_message msg; + + if (nCode == HC_ACTION) + { + KBDLLHOOKSTRUCT *kdbhookstruct = (KBDLLHOOKSTRUCT*)lParam; + + msg.hwnd = 0; + msg.message = wParam; + msg.flags = kbd_hook|wparam|lparam; + msg.wParam = kdbhookstruct->vkCode; + msg.lParam = kdbhookstruct->flags; + msg.descr = "KeyboardHookProc"; + add_message(&msg); + + if (wParam == WM_KEYUP || wParam == WM_KEYDOWN) + { + ok(kdbhookstruct->vkCode == VK_LWIN || kdbhookstruct->vkCode == hotkey_letter, + "unexpected keycode %x\n", kdbhookstruct->vkCode); + } + } + + return CallNextHookEx(hKBD_hook, nCode, wParam, lParam); +} + +static void test_hotkey(void) +{ + HWND test_window, taskbar_window; + BOOL ret; + MSG msg; + DWORD queue_status; + SHORT key_state; + + SetLastError(0xdeadbeef); + ret = UnregisterHotKey(NULL, 0); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + if (ret == TRUE) + { + skip("hotkeys not supported\n"); + return; + } + + test_window = CreateWindowEx(0, "HotkeyWindowClass", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 200, 200, 0, 0, 0, NULL); + + flush_sequence(); + + SetLastError(0xdeadbeef); + ret = UnregisterHotKey(test_window, 0); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Search for a Windows Key + letter combination that hasn't been registered */ + for (hotkey_letter = 0x41; hotkey_letter <= 0x51; hotkey_letter ++) + { + SetLastError(0xdeadbeef); + ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); + + if (ret == TRUE) + { + break; + } + else + { + ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + } + } + + if (hotkey_letter == 0x52) + { + ok(0, "Couldn't find any free Windows Key + letter combination\n"); + goto end; + } + + hKBD_hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookProc, GetModuleHandle(NULL), 0); + if (!hKBD_hook) win_skip("WH_KEYBOARD_LL is not supported\n"); + + /* Same key combination, different id */ + SetLastError(0xdeadbeef); + ret = RegisterHotKey(test_window, 4, MOD_WIN, hotkey_letter); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Same key combination, different window */ + SetLastError(0xdeadbeef); + ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Register the same hotkey twice */ + SetLastError(0xdeadbeef); + ret = RegisterHotKey(test_window, 5, MOD_WIN, hotkey_letter); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_ALREADY_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Window on another thread */ + taskbar_window = FindWindowA("Shell_TrayWnd", NULL); + if (!taskbar_window) + { + skip("no taskbar?\n"); + } + else + { + SetLastError(0xdeadbeef); + ret = RegisterHotKey(taskbar_window, 5, 0, hotkey_letter); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_WINDOW_OF_OTHER_THREAD || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + } + + /* Inject the appropriate key sequence */ + keybd_event(VK_LWIN, 0, 0, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmHotkeyPressLWIN, "window hotkey press LWIN", FALSE); + + keybd_event(hotkey_letter, 0, 0, 0); + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_HOTKEY) + { + ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); + ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); + } + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyPress, "window hotkey press", FALSE); + + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == 0, "expected QS_HOTKEY << 16 cleared, got %x\n", queue_status); + + key_state = GetAsyncKeyState(hotkey_letter); + ok((key_state & 0x8000) == 0x8000, "unexpected key state %x\n", key_state); + + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmHotkeyRelease, "window hotkey release", TRUE); + + keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmHotkeyReleaseLWIN, "window hotkey release LWIN", FALSE); + + /* normal posted WM_HOTKEY messages set QS_HOTKEY */ + PostMessage(test_window, WM_HOTKEY, 0, 0); + queue_status = GetQueueStatus(QS_HOTKEY); + ok((queue_status & (QS_HOTKEY << 16)) == QS_HOTKEY << 16, "expected QS_HOTKEY << 16 set, got %x\n", queue_status); + queue_status = GetQueueStatus(QS_POSTMESSAGE); + ok((queue_status & (QS_POSTMESSAGE << 16)) == QS_POSTMESSAGE << 16, "expected QS_POSTMESSAGE << 16 set, got %x\n", queue_status); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + flush_sequence(); + + /* Send and process all messages at once */ + PostMessage(test_window, WM_APP, 0, 0); + keybd_event(VK_LWIN, 0, 0, 0); + keybd_event(hotkey_letter, 0, 0, 0); + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_HOTKEY) + { + ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); + ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); + } + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyCombined, "window hotkey combined", FALSE); + + /* Register same hwnd/id with different key combination */ + ret = RegisterHotKey(test_window, 5, 0, hotkey_letter); + ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); + + /* Previous key combination does not work */ + keybd_event(VK_LWIN, 0, 0, 0); + keybd_event(hotkey_letter, 0, 0, 0); + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + DispatchMessage(&msg); + ok_sequence(WmHotkeyPrevious, "window hotkey previous", FALSE); + + /* New key combination works */ + keybd_event(hotkey_letter, 0, 0, 0); + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_HOTKEY) + { + ok(msg.hwnd == test_window, "unexpected hwnd %p\n", msg.hwnd); + ok(msg.lParam == MAKELPARAM(0, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); + } + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyNew, "window hotkey new", FALSE); + + /* Unregister hotkey properly */ + ret = UnregisterHotKey(test_window, 5); + ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); + + /* Unregister hotkey again */ + SetLastError(0xdeadbeef); + ret = UnregisterHotKey(test_window, 5); + ok(ret == FALSE, "expected FALSE, got %i\n", ret); + ok(GetLastError() == ERROR_HOTKEY_NOT_REGISTERED || broken(GetLastError() == 0xdeadbeef), + "unexpected error %d\n", GetLastError()); + + /* Register thread hotkey */ + ret = RegisterHotKey(NULL, 5, MOD_WIN, hotkey_letter); + ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); + + /* Inject the appropriate key sequence */ + keybd_event(VK_LWIN, 0, 0, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyPressLWIN, "thread hotkey press LWIN", FALSE); + + keybd_event(hotkey_letter, 0, 0, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_HOTKEY) + { + struct recvd_message message; + ok(msg.hwnd == NULL, "unexpected hwnd %p\n", msg.hwnd); + ok(msg.lParam == MAKELPARAM(MOD_WIN, hotkey_letter), "unexpected WM_HOTKEY lparam %lx\n", msg.lParam); + message.message = msg.message; + message.flags = sent|wparam|lparam; + message.wParam = msg.wParam; + message.lParam = msg.lParam; + message.descr = "test_hotkey thread message"; + add_message(&message); + } + else + ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyPress, "thread hotkey press", FALSE); + + keybd_event(hotkey_letter, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyRelease, "thread hotkey release", TRUE); + + keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + ok(msg.hwnd != NULL, "unexpected thread message %x\n", msg.message); + DispatchMessage(&msg); + } + ok_sequence(WmHotkeyReleaseLWIN, "thread hotkey release LWIN", FALSE); + + /* Unregister thread hotkey */ + ret = UnregisterHotKey(NULL, 5); + ok(ret == TRUE, "expected TRUE, got %i, err=%d\n", ret, GetLastError()); + + if (hKBD_hook) UnhookWindowsHookEx(hKBD_hook); + hKBD_hook = NULL; + +end: + UnregisterHotKey(NULL, 5); + UnregisterHotKey(test_window, 5); + DestroyWindow(test_window); + flush_sequence(); +} + START_TEST(msg) { char **test_argv; BOOL ret; BOOL (WINAPI *pIsWinEventHookInstalled)(DWORD)= 0;/*GetProcAddress(user32, "IsWinEventHookInstalled");*/ + HMODULE hModuleImm32; + BOOL (WINAPI *pImmDisableIME)(DWORD);
int argc = winetest_get_mainargs( &test_argv ); if (argc >= 3) @@ -12518,6 +13440,15 @@ }
init_procs(); + + hModuleImm32 = LoadLibrary("imm32.dll"); + if (hModuleImm32) { + pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME"); + if (pImmDisableIME) + pImmDisableIME(0); + } + pImmDisableIME = NULL; + FreeLibrary(hModuleImm32);
if (!RegisterWindowClasses()) assert(0);
@@ -12553,6 +13484,7 @@ hEvent_hook = 0; #endif
+ test_SetParent(); test_PostMessage(); test_ShowWindow(); test_PeekMessage(); @@ -12597,6 +13529,8 @@ test_paintingloop(); test_defwinproc(); test_clipboard_viewers(); + test_keyflags(); + test_hotkey(); /* keep it the last test, under Windows it tends to break the tests * which rely on active/foreground windows being correct. */