Aric Stewart : imm32: Properly separate the IME UI window and the thread default IME window.

Alexandre Julliard julliard at winehq.org
Thu Sep 27 15:39:09 CDT 2012


Module: wine
Branch: master
Commit: 5f5f20d6cf7c38f59171b760870d58b8fdf53132
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=5f5f20d6cf7c38f59171b760870d58b8fdf53132

Author: Aric Stewart <aric at codeweavers.com>
Date:   Thu Sep 27 09:42:54 2012 -0500

imm32: Properly separate the IME UI window and the thread default IME window.

---

 dlls/imm32/imm.c             |   86 ++++++++++++++++++++++++++++++++++++------
 dlls/imm32/tests/imm32.c     |   38 ++++++++++++++++++
 dlls/winex11.drv/Makefile.in |    4 +-
 3 files changed, 114 insertions(+), 14 deletions(-)

diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c
index 7394101..cf76df1 100644
--- a/dlls/imm32/imm.c
+++ b/dlls/imm32/imm.c
@@ -50,6 +50,7 @@ typedef struct _tagImmHkl{
     IMEINFO     imeInfo;
     WCHAR       imeClassName[17]; /* 16 character max */
     ULONG       uSelected;
+    HWND        UIWnd;
 
     /* Function Pointers */
     MAKE_FUNCPTR(ImeInquire);
@@ -77,7 +78,6 @@ typedef struct tagInputContextData
         INPUTCONTEXT    IMC;
 
         ImmHkl          *immKbd;
-        HWND            imeWnd;
         UINT            lastVK;
 } InputContextData;
 
@@ -110,6 +110,8 @@ static const WCHAR szImeFileW[] = {'I','m','e',' ','F','i','l','e',0};
 static const WCHAR szLayoutTextW[] = {'L','a','y','o','u','t',' ','T','e','x','t',0};
 static const WCHAR szImeRegFmt[] = {'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\','C','o','n','t','r','o','l','\\','K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','s','\\','%','0','8','l','x',0};
 
+static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+                                        LPARAM lParam);
 
 #define is_himc_ime_unicode(p)  (p->immKbd->imeInfo.fdwProperty & IME_PROP_UNICODE)
 #define is_kbd_ime_unicode(p)  (p->imeInfo.fdwProperty & IME_PROP_UNICODE)
@@ -357,6 +359,8 @@ static void IMM_FreeAllImmHkl(void)
             ptr->pImeDestroy(1);
             FreeLibrary(ptr->hIME);
         }
+        if (ptr->UIWnd)
+            DestroyWindow(ptr->UIWnd);
         HeapFree(GetProcessHeap(),0,ptr);
     }
 }
@@ -372,6 +376,22 @@ static void IMM_RegisterMessages(void)
     WM_MSIME_DOCUMENTFEED = RegisterWindowMessageA("MSIMEDocumentFeed");
 }
 
+static void IMM_RegisterIMEClass(HINSTANCE hInstDLL)
+{
+    static const WCHAR szwIME[] = {'I','M','E',0};
+    WNDCLASSW wndClass;
+
+    ZeroMemory(&wndClass, sizeof(WNDCLASSW));
+
+    wndClass.style = CS_GLOBALCLASS;
+    wndClass.lpfnWndProc = (WNDPROC) DefIME_WindowProc;
+    wndClass.cbWndExtra = 2 * sizeof(LONG_PTR);
+    wndClass.hCursor = LoadCursorW(NULL, (LPWSTR)IDC_ARROW);
+    wndClass.lpszClassName = szwIME;
+
+    RegisterClassW(&wndClass);
+}
+
 BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
 {
     TRACE("%p, %x, %p\n",hInstDLL,fdwReason,lpReserved);
@@ -382,6 +402,7 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpReserved)
             tlsIndex = TlsAlloc();
             if (tlsIndex == TLS_OUT_OF_INDEXES)
                 return FALSE;
+            IMM_RegisterIMEClass(hInstDLL);
             break;
         case DLL_THREAD_ATTACH:
             break;
@@ -678,10 +699,6 @@ static BOOL IMM_DestroyContext(HIMC hIMC)
         data->immKbd->pImeSelect(hIMC, FALSE);
         SendMessageW(data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)GetKeyboardLayout(0));
 
-        if (IMM_GetThreadData()->hwndDefault == data->imeWnd)
-            IMM_GetThreadData()->hwndDefault = NULL;
-        DestroyWindow(data->imeWnd);
-
         ImmDestroyIMCC(data->IMC.hCompStr);
         ImmDestroyIMCC(data->IMC.hCandInfo);
         ImmDestroyIMCC(data->IMC.hGuideLine);
@@ -1490,6 +1507,10 @@ BOOL WINAPI ImmGetConversionStatus(
  */
 HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
 {
+    static const WCHAR szwIME[] = {'I','M','E',0};
+    if (IMM_GetThreadData()->hwndDefault == NULL)
+        IMM_GetThreadData()->hwndDefault = CreateWindowExW( WS_EX_TOOLWINDOW,
+                    szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
     TRACE("Default is %p\n",IMM_GetThreadData()->hwndDefault);
     return IMM_GetThreadData()->hwndDefault;
 }
@@ -2262,16 +2283,16 @@ BOOL WINAPI ImmSetCompositionWindow(
 
     data->IMC.cfCompForm = *lpCompForm;
 
-    if (IsWindowVisible(IMM_GetThreadData()->hwndDefault))
+    if (IsWindowVisible(data->immKbd->UIWnd))
     {
         reshow = TRUE;
-        ShowWindow(IMM_GetThreadData()->hwndDefault,SW_HIDE);
+        ShowWindow(data->immKbd->UIWnd,SW_HIDE);
     }
 
     /* FIXME: this is a partial stub */
 
     if (reshow)
-        ShowWindow(IMM_GetThreadData()->hwndDefault,SW_SHOWNOACTIVATE);
+        ShowWindow(data->immKbd->UIWnd,SW_SHOWNOACTIVATE);
 
     ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0);
     return TRUE;
@@ -2321,14 +2342,13 @@ BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
     if (!data)
         return FALSE;
 
-    if (data->imeWnd == NULL)
+    if (data->immKbd->UIWnd == NULL)
     {
         /* create the ime window */
-        data->imeWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
+        data->immKbd->UIWnd = CreateWindowExW( WS_EX_TOOLWINDOW,
                     data->immKbd->imeClassName, NULL, WS_POPUP, 0, 0, 1, 1, 0,
                     0, data->immKbd->hIME, 0);
-        SetWindowLongPtrW(data->imeWnd, IMMGWL_IMC, (LONG_PTR)data);
-        IMM_GetThreadData()->hwndDefault = data->imeWnd;
+        SetWindowLongPtrW(data->immKbd->UIWnd, IMMGWL_IMC, (LONG_PTR)data);
     }
 
     if (!fOpen != !data->IMC.fOpen)
@@ -2855,3 +2875,45 @@ BOOL WINAPI ImmGetHotKey(DWORD hotkey, UINT *modifiers, UINT *key, HKL hkl)
     FIXME("%x, %p, %p, %p: stub\n", hotkey, modifiers, key, hkl);
     return FALSE;
 }
+
+
+/*
+ * Window Proc for the Default IME window class
+ */
+static LRESULT WINAPI DefIME_WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
+                                        LPARAM lParam)
+{
+    switch (uMsg)
+    {
+        case WM_CREATE:
+        case WM_NCCREATE:
+            return TRUE;
+        case WM_IME_COMPOSITION:
+        case WM_IME_STARTCOMPOSITION:
+        case WM_IME_ENDCOMPOSITION:
+        case WM_IME_SELECT:
+        case WM_IME_CONTROL:
+        case WM_IME_NOTIFY:
+        {
+           ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
+           if (immHkl->UIWnd)
+               PostMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
+            return TRUE;
+        }
+        default:
+            if ((uMsg == WM_MSIME_RECONVERTOPTIONS) ||
+                (uMsg ==WM_MSIME_SERVICE) ||
+                (uMsg == WM_MSIME_MOUSE) ||
+                (uMsg == WM_MSIME_RECONVERTREQUEST) ||
+                (uMsg == WM_MSIME_RECONVERT) ||
+                (uMsg == WM_MSIME_QUERYPOSITION) ||
+                (uMsg == WM_MSIME_DOCUMENTFEED))
+            {
+               ImmHkl *immHkl = IMM_GetImmHkl(GetKeyboardLayout(0));
+               if (immHkl->UIWnd)
+                   PostMessageW(immHkl->UIWnd,uMsg,wParam,lParam);
+                return TRUE;
+            }
+            return FALSE;
+    }
+}
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c
index 7fa8551..6eb8a41 100644
--- a/dlls/imm32/tests/imm32.c
+++ b/dlls/imm32/tests/imm32.c
@@ -618,6 +618,43 @@ static void test_ImmGetDescription(void)
     UnloadKeyboardLayout(hkl);
 }
 
+static void test_ImmDefaultHwnd(void)
+{
+    HIMC imc1, imc2, imc3;
+    HWND def1, def3;
+    HWND hwnd;
+
+    hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, "EDIT", "Wine imm32.dll test",
+                          WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
+                          240, 120, NULL, NULL, GetModuleHandle(0), NULL);
+
+    ShowWindow(hwnd, SW_SHOWNORMAL);
+
+    imc1 = ImmGetContext(hwnd);
+    if (!imc1)
+    {
+        win_skip("IME support not implemented\n");
+        return;
+    }
+
+    def1 = ImmGetDefaultIMEWnd(hwnd);
+
+    imc2 = ImmCreateContext();
+    ImmSetOpenStatus(imc2, TRUE);
+
+    imc3 = ImmGetContext(hwnd);
+    def3 = ImmGetDefaultIMEWnd(hwnd);
+
+    ok(def3 == def1, "Default IME window should not change\n");
+    ok(imc1 == imc3, "IME context should not change\n");
+    ImmSetOpenStatus(imc2, FALSE);
+
+    ImmReleaseContext(hwnd, imc1);
+    ImmReleaseContext(hwnd, imc3);
+    ImmDestroyContext(imc2);
+    DestroyWindow(hwnd);
+}
+
 START_TEST(imm32) {
     if (init())
     {
@@ -630,6 +667,7 @@ START_TEST(imm32) {
         test_ImmIsUIMessage();
         test_ImmGetContext();
         test_ImmGetDescription();
+        test_ImmDefaultHwnd();
     }
     cleanup();
 }
diff --git a/dlls/winex11.drv/Makefile.in b/dlls/winex11.drv/Makefile.in
index 2bc49f5..96c9a7b 100644
--- a/dlls/winex11.drv/Makefile.in
+++ b/dlls/winex11.drv/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = winex11.drv
-IMPORTS   = uuid user32 gdi32 advapi32 imm32
-DELAYIMPORTS = comctl32 ole32 shell32
+IMPORTS   = uuid user32 gdi32 advapi32
+DELAYIMPORTS = comctl32 ole32 shell32 imm32
 EXTRAINCL = @X_CFLAGS@
 EXTRALIBS = @X_LIBS@ @X_PRE_LIBS@ @XLIB@ @X_EXTRA_LIBS@
 




More information about the wine-cvs mailing list