imm32: Use thread data from target HWND.

This commit is contained in:
Aric Stewart 2015-02-25 11:45:22 -06:00 committed by Alexandre Julliard
parent f3967902c5
commit 455ca1adb0
2 changed files with 43 additions and 17 deletions

View File

@ -246,6 +246,21 @@ static IMMThreadData* IMM_GetThreadData(DWORD id)
return data; return data;
} }
static IMMThreadData* IMM_GetThreadDataForWindow(HWND hwnd)
{
DWORD process;
DWORD thread = 0;
if (hwnd)
{
thread = GetWindowThreadProcessId(hwnd, &process);
if (process != GetCurrentProcessId())
return NULL;
}
return IMM_GetThreadData(thread);
}
static BOOL IMM_IsDefaultContext(HIMC imc) static BOOL IMM_IsDefaultContext(HIMC imc)
{ {
InputContextData *data = get_imc_data(imc); InputContextData *data = get_imc_data(imc);
@ -478,21 +493,21 @@ static InputContextData* get_imc_data(HIMC hIMC)
return data; return data;
} }
static IMMThreadData* IMM_GetInitializedThreadData(void) static IMMThreadData* IMM_GetInitializedThreadData(HWND hWnd)
{ {
IMMThreadData* thread_data = IMM_GetThreadData(0); IMMThreadData* thread_data = IMM_GetThreadDataForWindow(hWnd);
if (!thread_data) if (!thread_data)
return NULL; return NULL;
if (!thread_data->defaultContext) if (!thread_data->defaultContext && thread_data->threadID == GetCurrentThreadId())
{ {
HIMC defaultContext; HIMC defaultContext;
LeaveCriticalSection(&threaddata_cs); LeaveCriticalSection(&threaddata_cs);
defaultContext = ImmCreateContext(); defaultContext = ImmCreateContext();
if (defaultContext) if (defaultContext)
((InputContextData*)defaultContext)->threadDefault = TRUE; ((InputContextData*)defaultContext)->threadDefault = TRUE;
thread_data = IMM_GetThreadData(0); thread_data = IMM_GetThreadDataForWindow(hWnd);
if (!thread_data) if (!thread_data)
{ {
IMM_DestroyContext(defaultContext); IMM_DestroyContext(defaultContext);
@ -528,7 +543,7 @@ HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC)
if (hIMC && data->IMC.hWnd == hWnd) if (hIMC && data->IMC.hWnd == hWnd)
return hIMC; return hIMC;
thread_data = IMM_GetInitializedThreadData(); thread_data = IMM_GetInitializedThreadData(hWnd);
if (!thread_data) if (!thread_data)
return NULL; return NULL;
@ -603,7 +618,7 @@ BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags)
TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags); TRACE("(%p, %p, 0x%x):\n", hWnd, hIMC, dwFlags);
thread_data = IMM_GetInitializedThreadData(); thread_data = IMM_GetInitializedThreadData(hWnd);
if (!thread_data) if (!thread_data)
return FALSE; return FALSE;
@ -1470,7 +1485,7 @@ HIMC WINAPI ImmGetContext(HWND hWnd)
return NULL; return NULL;
} }
thread_data = IMM_GetInitializedThreadData(); thread_data = IMM_GetInitializedThreadData(hWnd);
if (!thread_data) if (!thread_data)
return NULL; return NULL;
@ -1595,18 +1610,21 @@ BOOL WINAPI ImmGetConversionStatus(
HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd) HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
{ {
HWND ret, new = NULL; HWND ret, new = NULL;
IMMThreadData* thread_data = IMM_GetThreadData(0); IMMThreadData* thread_data = IMM_GetThreadDataForWindow(hWnd);
if (!thread_data) if (!thread_data)
return NULL; return NULL;
if (thread_data->hwndDefault == NULL) if (thread_data->hwndDefault == NULL && thread_data->threadID == GetCurrentThreadId())
{ {
/* Do not create the window inside of a critical section */ /* Do not create the window inside of a critical section */
LeaveCriticalSection(&threaddata_cs); LeaveCriticalSection(&threaddata_cs);
new = CreateWindowExW( WS_EX_TOOLWINDOW, new = CreateWindowExW( WS_EX_TOOLWINDOW,
szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0); szwIME, NULL, WS_POPUP, 0, 0, 1, 1, 0, 0, 0, 0);
thread_data = IMM_GetThreadData(0); thread_data = IMM_GetThreadDataForWindow(hWnd);
if (!thread_data) if (!thread_data)
{
DestroyWindow(new);
return NULL; return NULL;
}
/* See if anyone beat us */ /* See if anyone beat us */
if (thread_data->hwndDefault == NULL) if (thread_data->hwndDefault == NULL)
{ {
@ -1622,6 +1640,7 @@ HWND WINAPI ImmGetDefaultIMEWnd(HWND hWnd)
{ {
DestroyWindow(new); DestroyWindow(new);
} }
TRACE("Default is %p\n",ret);
return ret; return ret;
} }

View File

@ -425,15 +425,17 @@ static DWORD WINAPI ImmGetContextThreadFunc( LPVOID lpParam)
HWND hwnd2; HWND hwnd2;
COMPOSITIONFORM cf; COMPOSITIONFORM cf;
POINT pt; POINT pt;
MSG msg;
igc_threadinfo *info= (igc_threadinfo*)lpParam; igc_threadinfo *info= (igc_threadinfo*)lpParam;
info->hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test", info->hwnd = CreateWindowExA(WS_EX_CLIENTEDGE, wndcls, "Wine imm32.dll test",
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL); 240, 120, NULL, NULL, GetModuleHandleW(NULL), NULL);
h1 = ImmGetContext(hwnd); h1 = ImmGetContext(hwnd);
todo_wine ok(info->himc == h1, "hwnd context changed in new thread\n"); ok(info->himc == h1, "hwnd context changed in new thread\n");
h2 = ImmGetContext(info->hwnd); h2 = ImmGetContext(info->hwnd);
todo_wine ok(h2 != h1, "new hwnd in new thread should have different context\n"); ok(h2 != h1, "new hwnd in new thread should have different context\n");
info->himc = h2; info->himc = h2;
ImmReleaseContext(hwnd,h1); ImmReleaseContext(hwnd,h1);
@ -452,7 +454,12 @@ static DWORD WINAPI ImmGetContextThreadFunc( LPVOID lpParam)
ImmSetStatusWindowPos(h1, &pt); ImmSetStatusWindowPos(h1, &pt);
SetEvent(info->event); SetEvent(info->event);
Sleep(INFINITE);
while(GetMessageW(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 1; return 1;
} }
@ -477,8 +484,8 @@ static void test_ImmThreads(void)
otherHimc = ImmGetContext(threadinfo.hwnd); otherHimc = ImmGetContext(threadinfo.hwnd);
todo_wine ok(himc != otherHimc, "Windows from other threads should have different himc\n"); ok(himc != otherHimc, "Windows from other threads should have different himc\n");
todo_wine ok(otherHimc == threadinfo.himc, "Context from other thread should not change in main thread\n"); ok(otherHimc == threadinfo.himc, "Context from other thread should not change in main thread\n");
if (0) /* FIXME: Causes wine to hang */ if (0) /* FIXME: Causes wine to hang */
{ {
@ -566,7 +573,7 @@ static void test_ImmThreads(void)
ok (rc == 1, "ImmGetCandidateWindow should succeed\n"); ok (rc == 1, "ImmGetCandidateWindow should succeed\n");
rc = ImmGetCandidateWindow(otherHimc, 0, &cdf); rc = ImmGetCandidateWindow(otherHimc, 0, &cdf);
todo_wine ok (rc == 0, "ImmGetCandidateWindow should fail\n"); ok (rc == 0, "ImmGetCandidateWindow should fail\n");
rc = ImmSetCandidateWindow(otherHimc, &cdf); rc = ImmSetCandidateWindow(otherHimc, &cdf);
todo_wine ok (rc == 0, "ImmSetCandidateWindow should fail\n"); todo_wine ok (rc == 0, "ImmSetCandidateWindow should fail\n");
@ -577,7 +584,7 @@ static void test_ImmThreads(void)
TerminateThread(hThread, 1); TerminateThread(hThread, 1);
himc = ImmGetContext(GetDesktopWindow()); himc = ImmGetContext(GetDesktopWindow());
todo_wine ok(himc == NULL, "Should not be able to get himc from other process window\n"); ok(himc == NULL, "Should not be able to get himc from other process window\n");
} }
static void test_ImmIsUIMessage(void) static void test_ImmIsUIMessage(void)