Piotr Caban : imm32: Add ImmSetActiveContext implementation.
Alexandre Julliard
julliard at winehq.org
Fri Oct 15 15:40:06 CDT 2021
Module: wine
Branch: master
Commit: 80ac0b9af4302a3d7be4868b7507740abbe5e0d7
URL: https://source.winehq.org/git/wine.git/?a=commit;h=80ac0b9af4302a3d7be4868b7507740abbe5e0d7
Author: Piotr Caban <piotr at codeweavers.com>
Date: Fri Oct 15 15:26:50 2021 +0200
imm32: Add ImmSetActiveContext implementation.
Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at 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");
More information about the wine-cvs
mailing list