Module: wine Branch: master Commit: 80ac0b9af4302a3d7be4868b7507740abbe5e0d7 URL: https://source.winehq.org/git/wine.git/?a=commit;h=80ac0b9af4302a3d7be4868b7...
Author: Piotr Caban piotr@codeweavers.com Date: Fri Oct 15 15:26:50 2021 +0200
imm32: Add ImmSetActiveContext implementation.
Signed-off-by: Piotr Caban piotr@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/imm32/imm.c | 28 ++++++++++++++++++++++ dlls/imm32/imm32.spec | 2 +- dlls/imm32/tests/imm32.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index 20633041871..d933ca06c2f 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -550,6 +550,34 @@ static BOOL IMM_IsCrossThreadAccess(HWND hWnd, HIMC hIMC) return FALSE; }
+/*********************************************************************** + * ImmSetActiveContext (IMM32.@) + */ +BOOL WINAPI ImmSetActiveContext(HWND hwnd, HIMC himc, BOOL activate) +{ + InputContextData *data = get_imc_data(himc); + + TRACE("(%p, %p, %x)\n", hwnd, himc, activate); + + if (himc && !data && activate) + return FALSE; + + if (data) + { + data->IMC.hWnd = activate ? hwnd : NULL; + + if (data->immKbd->hIME && data->immKbd->pImeSetActiveContext) + data->immKbd->pImeSetActiveContext(himc, activate); + } + + if (IsWindow(hwnd)) + { + SendMessageW(hwnd, WM_IME_SETCONTEXT, activate, ISC_SHOWUIALL); + /* TODO: send WM_IME_NOTIFY */ + } + return TRUE; +} + /*********************************************************************** * ImmAssociateContext (IMM32.@) */ diff --git a/dlls/imm32/imm32.spec b/dlls/imm32/imm32.spec index 4197bb81e21..25876de873d 100644 --- a/dlls/imm32/imm32.spec +++ b/dlls/imm32/imm32.spec @@ -86,7 +86,7 @@ @ stub ImmSendIMEMessageExA @ stub ImmSendIMEMessageExW @ stub ImmSendMessageToActiveDefImeWndW -@ stub ImmSetActiveContext +@ stdcall ImmSetActiveContext(long long long) @ stub ImmSetActiveContextConsoleIME @ stdcall ImmSetCandidateWindow(long ptr) @ stdcall ImmSetCompositionFontA(long ptr) diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index cc9e0e8c01f..18d69724e58 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -26,10 +26,44 @@ #include "imm.h" #include "ddk/imm.h"
+BOOL WINAPI ImmSetActiveContext(HWND, HIMC, BOOL); + static BOOL (WINAPI *pImmAssociateContextEx)(HWND,HIMC,DWORD); static BOOL (WINAPI *pImmIsUIMessageA)(HWND,UINT,WPARAM,LPARAM); static UINT (WINAPI *pSendInput) (UINT, INPUT*, size_t);
+#define DEFINE_EXPECT(func) \ + static BOOL expect_ ## func = FALSE, called_ ## func = FALSE, enabled_ ## func = FALSE + +#define SET_EXPECT(func) \ + expect_ ## func = TRUE + +#define CHECK_EXPECT2(func) \ + do { \ + if (enabled_ ## func) {\ + ok(expect_ ##func, "unexpected call " #func "\n"); \ + called_ ## func = TRUE; \ + } \ + }while(0) + +#define CHECK_EXPECT(func) \ + do { \ + CHECK_EXPECT2(func); \ + expect_ ## func = FALSE; \ + }while(0) + +#define CHECK_CALLED(func) \ + do { \ + ok(called_ ## func, "expected " #func "\n"); \ + expect_ ## func = called_ ## func = FALSE; \ + }while(0) + +#define SET_ENABLE(func, val) \ + enabled_ ## func = (val) + +DEFINE_EXPECT(WM_IME_SETCONTEXT_DEACTIVATE); +DEFINE_EXPECT(WM_IME_SETCONTEXT_ACTIVATE); + /* * msgspy - record and analyse message traces sent to a certain window */ @@ -182,6 +216,9 @@ static LRESULT WINAPI wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) switch (msg) { case WM_IME_SETCONTEXT: + if (wParam) CHECK_EXPECT(WM_IME_SETCONTEXT_ACTIVATE); + else CHECK_EXPECT(WM_IME_SETCONTEXT_DEACTIVATE); + ok(lParam == ISC_SHOWUIALL || !lParam, "lParam = %lx\n", lParam); return TRUE; case WM_NCCREATE: default_ime_wnd = get_ime_window(); @@ -737,6 +774,19 @@ static void test_ImmThreads(void) ok(himc != otherHimc, "Windows from other threads should have different himc\n"); ok(otherHimc == threadinfo.himc, "Context from other thread should not change in main thread\n");
+ SET_ENABLE(WM_IME_SETCONTEXT_DEACTIVATE, TRUE); + SET_ENABLE(WM_IME_SETCONTEXT_ACTIVATE, TRUE); + SET_EXPECT(WM_IME_SETCONTEXT_ACTIVATE); + rc = ImmSetActiveContext(hwnd, otherHimc, TRUE); + ok(rc, "ImmSetActiveContext failed\n"); + CHECK_CALLED(WM_IME_SETCONTEXT_ACTIVATE); + SET_EXPECT(WM_IME_SETCONTEXT_DEACTIVATE); + rc = ImmSetActiveContext(hwnd, otherHimc, FALSE); + ok(rc, "ImmSetActiveContext failed\n"); + CHECK_CALLED(WM_IME_SETCONTEXT_DEACTIVATE); + SET_ENABLE(WM_IME_SETCONTEXT_DEACTIVATE, FALSE); + SET_ENABLE(WM_IME_SETCONTEXT_ACTIVATE, FALSE); + h1 = ImmAssociateContext(hwnd,otherHimc); ok(h1 == NULL, "Should fail to be able to Associate a default context from a different thread\n"); h1 = ImmGetContext(hwnd); @@ -1680,6 +1730,7 @@ static void test_InvalidIMC(void) CHAR buffer[1000]; INPUTCONTEXT *ic; LOGFONTA lf; + BOOL r;
memset(&lf, 0, sizeof(lf));
@@ -1697,6 +1748,17 @@ static void test_InvalidIMC(void) imc2 = ImmGetContext(hwnd); ok(imc1 == imc2, "imc should not changed! imc1 %p, imc2 %p\n", imc1, imc2);
+ SET_ENABLE(WM_IME_SETCONTEXT_DEACTIVATE, TRUE); + SET_ENABLE(WM_IME_SETCONTEXT_ACTIVATE, TRUE); + r = ImmSetActiveContext(hwnd, imc_destroy, TRUE); + ok(!r, "ImmSetActiveContext succeeded\n"); + SET_EXPECT(WM_IME_SETCONTEXT_DEACTIVATE); + r = ImmSetActiveContext(hwnd, imc_destroy, FALSE); + ok(r, "ImmSetActiveContext failed\n"); + CHECK_CALLED(WM_IME_SETCONTEXT_DEACTIVATE); + SET_ENABLE(WM_IME_SETCONTEXT_ACTIVATE, FALSE); + SET_ENABLE(WM_IME_SETCONTEXT_DEACTIVATE, FALSE); + /* Test associating NULL imc, which is different from an invalid imc */ oldimc = ImmAssociateContext(hwnd, imc_null); ok(oldimc != NULL, "Associating to NULL imc should success!\n");