From 5f5f20d6cf7c38f59171b760870d58b8fdf53132 Mon Sep 17 00:00:00 2001 From: Aric Stewart Date: Thu, 27 Sep 2012 09:42:54 -0500 Subject: [PATCH] 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 73941016bb8..cf76df1c28b 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 7fa85511845..6eb8a413e0e 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 2bc49f5f677..96c9a7b2fe5 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@ -- 2.11.4.GIT