Piotr Caban : imm32: Destroy default IME windows in ImmDisableIME.

Alexandre Julliard julliard at winehq.org
Fri Oct 15 15:40:06 CDT 2021


Module: wine
Branch: master
Commit: 684d023faad9549c642274d02c1363d5d179a417
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=684d023faad9549c642274d02c1363d5d179a417

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Fri Oct 15 15:27:24 2021 +0200

imm32: Destroy default IME windows in ImmDisableIME.

Signed-off-by: Piotr Caban <piotr at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/imm32/imm.c         | 50 +++++++++++++++++++++++++++++++++++++-------
 dlls/imm32/tests/imm32.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
index 023d816a51e..1230c2e2b95 100644
--- a/dlls/imm32/imm.c
+++ b/dlls/imm32/imm.c
@@ -992,18 +992,58 @@ BOOL WINAPI ImmDestroyContext(HIMC hIMC)
         return FALSE;
 }
 
+static HWND imm_detach_default_window(IMMThreadData *thread_data)
+{
+    HWND to_destroy;
+
+    imm_couninit_thread(thread_data, TRUE);
+    to_destroy = thread_data->hwndDefault;
+    thread_data->hwndDefault = NULL;
+    thread_data->windowRefs = 0;
+    return to_destroy;
+}
+
 /***********************************************************************
  *		ImmDisableIME (IMM32.@)
  */
 BOOL WINAPI ImmDisableIME(DWORD idThread)
 {
+    IMMThreadData *thread_data;
+    HWND to_destroy;
+
     if (idThread == (DWORD)-1)
+    {
         disable_ime = TRUE;
-    else {
-        IMMThreadData *thread_data = IMM_GetThreadData(NULL, idThread);
+
+        while (1)
+        {
+            to_destroy = 0;
+            EnterCriticalSection(&threaddata_cs);
+            LIST_FOR_EACH_ENTRY(thread_data, &ImmThreadDataList, IMMThreadData, entry)
+            {
+                if (thread_data->hwndDefault)
+                {
+                    to_destroy = imm_detach_default_window(thread_data);
+                    break;
+                }
+            }
+            LeaveCriticalSection(&threaddata_cs);
+
+            if (!to_destroy)
+                break;
+            DestroyWindow(to_destroy);
+        }
+    }
+    else
+    {
+        thread_data = IMM_GetThreadData(NULL, idThread);
         if (!thread_data) return FALSE;
         thread_data->disableIME = TRUE;
+        to_destroy = imm_detach_default_window(thread_data);
         LeaveCriticalSection(&threaddata_cs);
+
+        if (to_destroy)
+            DestroyWindow(to_destroy);
     }
     return TRUE;
 }
@@ -1878,11 +1918,7 @@ void WINAPI __wine_unregister_window(HWND hwnd)
 
     /* Destroy default IME window */
     if (thread_data->windowRefs == 0)
-    {
-        imm_couninit_thread(thread_data, TRUE);
-        to_destroy = thread_data->hwndDefault;
-        thread_data->hwndDefault = NULL;
-    }
+        to_destroy = imm_detach_default_window(thread_data);
     LeaveCriticalSection(&threaddata_cs);
 
     if (to_destroy) DestroyWindow( to_destroy );
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
index 759b564aba9..9e0e59d384d 100644
--- a/dlls/imm32/tests/imm32.c
+++ b/dlls/imm32/tests/imm32.c
@@ -2241,6 +2241,57 @@ static void test_com_initialization(void)
     test_apttype(-1);
 }
 
+static DWORD WINAPI disable_ime_thread(void *arg)
+{
+    HWND h, def;
+    MSG msg;
+    BOOL r;
+
+    h = CreateWindowA("static", "static", 0, 0, 0, 0, 0, 0, 0, 0, 0);
+    ok(h != NULL, "CreateWindow failed\n");
+    def = ImmGetDefaultIMEWnd(h);
+    ok(def != NULL, "ImmGetDefaultIMEWnd returned NULL\n");
+
+    r = ImmDisableIME(arg ? GetCurrentThreadId() : 0);
+    ok(r, "ImmDisableIME failed\n");
+
+    if (arg)
+    {
+        def = ImmGetDefaultIMEWnd(h);
+        todo_wine ok(def != NULL, "ImmGetDefaultIMEWnd returned NULL\n");
+        while(PeekMessageA(&msg, 0, 0, 0, PM_REMOVE))
+            DispatchMessageA(&msg);
+    }
+    def = ImmGetDefaultIMEWnd(h);
+    ok(!def, "ImmGetDefaultIMEWnd returned %p\n", def);
+    return 0;
+}
+
+static void test_ImmDisableIME(void)
+{
+    HANDLE thread;
+    HWND def;
+    BOOL r;
+
+    def = ImmGetDefaultIMEWnd(hwnd);
+    ok(def != NULL, "ImmGetDefaultIMEWnd(hwnd) returned NULL\n");
+
+    thread = CreateThread(NULL, 0, disable_ime_thread, 0, 0, NULL);
+    ok(thread != NULL, "CreateThread failed\n");
+    WaitForSingleObject(thread, INFINITE);
+    CloseHandle(thread);
+
+    thread = CreateThread(NULL, 0, disable_ime_thread, (void*)1, 0, NULL);
+    ok(thread != NULL, "CreateThread failed\n");
+    WaitForSingleObject(thread, INFINITE);
+    CloseHandle(thread);
+
+    r = ImmDisableIME(-1);
+    ok(r, "ImmDisableIME(-1) failed\n");
+    def = ImmGetDefaultIMEWnd(hwnd);
+    ok(!def, "ImmGetDefaultIMEWnd(hwnd) returned %p\n", def);
+}
+
 START_TEST(imm32) {
     if (!is_ime_enabled())
     {
@@ -2276,6 +2327,9 @@ START_TEST(imm32) {
         if (pSendInput)
             test_ime_processkey();
         else win_skip("SendInput is not available\n");
+
+        /* there's no way of enabling IME - keep the test last */
+        test_ImmDisableIME();
     }
     cleanup();
 }




More information about the wine-cvs mailing list