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