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