Author: akhaldi Date: Thu Aug 18 10:08:05 2016 New Revision: 72282
URL: http://svn.reactos.org/svn/reactos?rev=72282&view=rev Log: [IMM32_WINETEST] Sync with Wine Staging 1.9.16. CORE-11866
Modified: trunk/rostests/winetests/imm32/imm32.c
Modified: trunk/rostests/winetests/imm32/imm32.c URL: http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/imm32/imm32.c?re... ============================================================================== --- trunk/rostests/winetests/imm32/imm32.c [iso-8859-1] (original) +++ trunk/rostests/winetests/imm32/imm32.c [iso-8859-1] Thu Aug 18 10:08:05 2016 @@ -44,7 +44,7 @@ HWND hwnd; HHOOK get_msg_hook; HHOOK call_wnd_proc_hook; - imm_msgs msgs[32]; + imm_msgs msgs[64]; unsigned int i_msg; } msg_spy;
@@ -58,6 +58,12 @@ HARDWAREINPUT hi; } u; } TEST_INPUT; + +typedef struct _tagTRANSMSG { + UINT message; + WPARAM wParam; + LPARAM lParam; +} TRANSMSG, *LPTRANSMSG;
static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
@@ -166,19 +172,72 @@ * messages being sent to this window in response. */ static const char wndcls[] = "winetest_imm32_wndcls"; +static enum { PHASE_UNKNOWN, FIRST_WINDOW, SECOND_WINDOW, + CREATE_CANCEL, NCCREATE_CANCEL, IME_DISABLED } test_phase; static HWND hwnd;
+static HWND get_ime_window(void); + static LRESULT WINAPI wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { + HWND default_ime_wnd; switch (msg) { case WM_IME_SETCONTEXT: + return TRUE; case WM_NCCREATE: + default_ime_wnd = get_ime_window(); + switch(test_phase) { + case FIRST_WINDOW: + case IME_DISABLED: + ok(!default_ime_wnd, "expected no IME windows\n"); + break; + case SECOND_WINDOW: + ok(default_ime_wnd != NULL, "expected IME window existence\n"); + break; + default: + break; /* do nothing */ + } + if (test_phase == NCCREATE_CANCEL) + return FALSE; + return TRUE; + case WM_NCCALCSIZE: + default_ime_wnd = get_ime_window(); + switch(test_phase) { + case FIRST_WINDOW: + case SECOND_WINDOW: + case CREATE_CANCEL: + todo_wine_if(test_phase == FIRST_WINDOW || test_phase == CREATE_CANCEL) + ok(default_ime_wnd != NULL, "expected IME window existence\n"); + break; + case IME_DISABLED: + ok(!default_ime_wnd, "expected no IME windows\n"); + break; + default: + break; /* do nothing */ + } + break; case WM_CREATE: + default_ime_wnd = get_ime_window(); + switch(test_phase) { + case FIRST_WINDOW: + case SECOND_WINDOW: + case CREATE_CANCEL: + todo_wine_if(test_phase == FIRST_WINDOW || test_phase == CREATE_CANCEL) + ok(default_ime_wnd != NULL, "expected IME window existence\n"); + break; + case IME_DISABLED: + ok(!default_ime_wnd, "expected no IME windows\n"); + break; + default: + break; /* do nothing */ + } + if (test_phase == CREATE_CANCEL) + return -1; return TRUE; }
- return DefWindowProcA(hwnd,msg,wParam,lParam); + return DefWindowProcA(hWnd,msg,wParam,lParam); }
static BOOL init(void) { @@ -633,8 +692,11 @@ ImmReleaseContext(threadinfo.hwnd,otherHimc); ImmReleaseContext(hwnd,himc);
- DestroyWindow(threadinfo.hwnd); - TerminateThread(hThread, 1); + SendMessageA(threadinfo.hwnd, WM_CLOSE, 0, 0); + rc = PostThreadMessageA(dwThreadId, WM_QUIT, 1, 0); + ok(rc == 1, "PostThreadMessage should succeed\n"); + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread);
himc = ImmGetContext(GetDesktopWindow()); ok(himc == NULL, "Should not be able to get himc from other process window\n"); @@ -836,11 +898,175 @@ WaitForSingleObject(thread, INFINITE); ok(thread_ime_wnd != def1, "thread_ime_wnd == def1\n"); ok(!IsWindow(thread_ime_wnd), "thread_ime_wnd was not destroyed\n"); + CloseHandle(thread);
ImmReleaseContext(hwnd, imc1); ImmReleaseContext(hwnd, imc3); ImmDestroyContext(imc2); DestroyWindow(hwnd); +} + +static BOOL CALLBACK is_ime_window_proc(HWND hWnd, LPARAM param) +{ + static const WCHAR imeW[] = {'I','M','E',0}; + WCHAR class_nameW[16]; + HWND *ime_window = (HWND *)param; + if (GetClassNameW(hWnd, class_nameW, sizeof(class_nameW)/sizeof(class_nameW[0])) && + !lstrcmpW(class_nameW, imeW)) { + *ime_window = hWnd; + return FALSE; + } + return TRUE; +} + +static HWND get_ime_window(void) +{ + HWND ime_window = NULL; + EnumThreadWindows(GetCurrentThreadId(), is_ime_window_proc, (LPARAM)&ime_window); + return ime_window; +} + +struct testcase_ime_window { + BOOL visible; + BOOL top_level_window; +}; + +static DWORD WINAPI test_default_ime_window_cb(void *arg) +{ + struct testcase_ime_window *testcase = (struct testcase_ime_window *)arg; + DWORD visible = testcase->visible ? WS_VISIBLE : 0; + HWND hwnd1, hwnd2, default_ime_wnd, ime_wnd; + + ok(!get_ime_window(), "Expected no IME windows\n"); + if (testcase->top_level_window) { + test_phase = FIRST_WINDOW; + hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test", + WS_OVERLAPPEDWINDOW | visible, + CW_USEDEFAULT, CW_USEDEFAULT, + 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL); + } + else { + hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test", + WS_CHILD | visible, + CW_USEDEFAULT, CW_USEDEFAULT, + 240, 24, hwnd, NULL, GetModuleHandleW(NULL), NULL); + } + ime_wnd = get_ime_window(); + todo_wine ok(ime_wnd != NULL, "Expected IME window existence\n"); + default_ime_wnd = ImmGetDefaultIMEWnd(hwnd1); + todo_wine ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd); + + test_phase = SECOND_WINDOW; + hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test", + WS_OVERLAPPEDWINDOW | visible, + CW_USEDEFAULT, CW_USEDEFAULT, + 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL); + DestroyWindow(hwnd2); + todo_wine ok(IsWindow(ime_wnd) || + broken(!testcase->visible /* Vista */) || + broken(!testcase->top_level_window /* Vista */) , + "Expected IME window existence\n"); + DestroyWindow(hwnd1); + ok(!IsWindow(ime_wnd), "Expected no IME windows\n"); + return 1; +} + +static DWORD WINAPI test_default_ime_window_cancel_cb(void *arg) +{ + struct testcase_ime_window *testcase = (struct testcase_ime_window *)arg; + DWORD visible = testcase->visible ? WS_VISIBLE : 0; + HWND hwnd1, hwnd2, default_ime_wnd, ime_wnd; + + ok(!get_ime_window(), "Expected no IME windows\n"); + test_phase = NCCREATE_CANCEL; + hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test", + WS_OVERLAPPEDWINDOW | visible, + CW_USEDEFAULT, CW_USEDEFAULT, + 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL); + ok(hwnd1 == NULL, "creation succeeded, got %p\n", hwnd1); + ok(!get_ime_window(), "Expected no IME windows\n"); + + test_phase = CREATE_CANCEL; + hwnd1 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test", + WS_OVERLAPPEDWINDOW | visible, + CW_USEDEFAULT, CW_USEDEFAULT, + 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL); + ok(hwnd1 == NULL, "creation succeeded, got %p\n", hwnd1); + ok(!get_ime_window(), "Expected no IME windows\n"); + + test_phase = FIRST_WINDOW; + hwnd2 = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test", + WS_OVERLAPPEDWINDOW | visible, + CW_USEDEFAULT, CW_USEDEFAULT, + 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL); + ime_wnd = get_ime_window(); + todo_wine ok(ime_wnd != NULL, "Expected IME window existence\n"); + default_ime_wnd = ImmGetDefaultIMEWnd(hwnd2); + todo_wine ok(ime_wnd == default_ime_wnd, "Expected %p, got %p\n", ime_wnd, default_ime_wnd); + + DestroyWindow(hwnd2); + ok(!IsWindow(ime_wnd), "Expected no IME windows\n"); + return 1; +} + +static DWORD WINAPI test_default_ime_disabled_cb(void *arg) +{ + HWND hWnd, default_ime_wnd; + + ok(!get_ime_window(), "Expected no IME windows\n"); + ImmDisableIME(GetCurrentThreadId()); + test_phase = IME_DISABLED; + hWnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test", + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, CW_USEDEFAULT, + 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL); + default_ime_wnd = ImmGetDefaultIMEWnd(hWnd); + ok(!default_ime_wnd, "Expected no IME windows\n"); + DestroyWindow(hWnd); + return 1; +} + +static void test_default_ime_window_creation(void) +{ + HANDLE thread; + size_t i; + struct testcase_ime_window testcases[] = { + /* visible, top-level window */ + { TRUE, TRUE }, + { FALSE, TRUE }, + { TRUE, FALSE }, + { FALSE, FALSE } + }; + + for (i = 0; i < sizeof(testcases)/sizeof(testcases[0]); i++) + { + thread = CreateThread(NULL, 0, test_default_ime_window_cb, &testcases[i], 0, NULL); + ok(thread != NULL, "CreateThread failed with error %u\n", GetLastError()); + while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) == WAIT_OBJECT_0 + 1) + { + MSG msg; + while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage(&msg); + DispatchMessageA(&msg); + } + } + CloseHandle(thread); + + if (testcases[i].top_level_window) + { + thread = CreateThread(NULL, 0, test_default_ime_window_cancel_cb, &testcases[i], 0, NULL); + ok(thread != NULL, "CreateThread failed with error %u\n", GetLastError()); + WaitForSingleObject(thread, INFINITE); + CloseHandle(thread); + } + } + + thread = CreateThread(NULL, 0, test_default_ime_disabled_cb, NULL, 0, NULL); + WaitForSingleObject(thread, INFINITE); + CloseHandle(thread); + + test_phase = PHASE_UNKNOWN; }
static void test_ImmGetIMCLockCount(void) @@ -1015,6 +1241,9 @@ HIMC imc; UINT idx = 0;
+ LPINPUTCONTEXT lpIMC; + LPTRANSMSG lpTransMsg; + HWND hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, GetModuleHandleA(NULL), NULL); @@ -1032,6 +1261,64 @@ if (msg) ok(!msg->post, "Message should not be posted\n"); } while (msg); msg_spy_flush_msgs(); + + lpIMC = ImmLockIMC(imc); + lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(TRANSMSG)); + lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf); + lpTransMsg += lpIMC->dwNumMsgBuf; + lpTransMsg->message = WM_IME_STARTCOMPOSITION; + lpTransMsg->wParam = 0; + lpTransMsg->lParam = 0; + ImmUnlockIMCC(lpIMC->hMsgBuf); + lpIMC->dwNumMsgBuf++; + ImmUnlockIMC(imc); + ImmGenerateMessage(imc); + idx = 0; + do + { + msg = msg_spy_find_next_msg(WM_IME_STARTCOMPOSITION, &idx); + if (msg) ok(!msg->post, "Message should not be posted\n"); + } while (msg); + msg_spy_flush_msgs(); + + lpIMC = ImmLockIMC(imc); + lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(TRANSMSG)); + lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf); + lpTransMsg += lpIMC->dwNumMsgBuf; + lpTransMsg->message = WM_IME_COMPOSITION; + lpTransMsg->wParam = 0; + lpTransMsg->lParam = 0; + ImmUnlockIMCC(lpIMC->hMsgBuf); + lpIMC->dwNumMsgBuf++; + ImmUnlockIMC(imc); + ImmGenerateMessage(imc); + idx = 0; + do + { + msg = msg_spy_find_next_msg(WM_IME_COMPOSITION, &idx); + if (msg) ok(!msg->post, "Message should not be posted\n"); + } while (msg); + msg_spy_flush_msgs(); + + lpIMC = ImmLockIMC(imc); + lpIMC->hMsgBuf = ImmReSizeIMCC(lpIMC->hMsgBuf, (lpIMC->dwNumMsgBuf + 1) * sizeof(TRANSMSG)); + lpTransMsg = ImmLockIMCC(lpIMC->hMsgBuf); + lpTransMsg += lpIMC->dwNumMsgBuf; + lpTransMsg->message = WM_IME_ENDCOMPOSITION; + lpTransMsg->wParam = 0; + lpTransMsg->lParam = 0; + ImmUnlockIMCC(lpIMC->hMsgBuf); + lpIMC->dwNumMsgBuf++; + ImmUnlockIMC(imc); + ImmGenerateMessage(imc); + idx = 0; + do + { + msg = msg_spy_find_next_msg(WM_IME_ENDCOMPOSITION, &idx); + if (msg) ok(!msg->post, "Message should not be posted\n"); + } while (msg); + msg_spy_flush_msgs(); + ImmSetOpenStatus(imc, FALSE); ImmReleaseContext(hwnd, imc); DestroyWindow(hwnd); @@ -1523,6 +1810,7 @@ test_ImmGetContext(); test_ImmGetDescription(); test_ImmDefaultHwnd(); + test_default_ime_window_creation(); test_ImmGetIMCLockCount(); test_ImmGetIMCCLockCount(); test_ImmDestroyContext();