From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/tests/imm32.c | 42 +++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-)
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index e8116081f52..38093031627 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -2527,7 +2527,7 @@ static struct ime_call ime_calls[1024]; static ULONG ime_call_count;
#define ok_call( a, b ) ok_call_( __FILE__, __LINE__, a, b ) -static void ok_call_( const char *file, int line, const struct ime_call *expected, const struct ime_call *received ) +static int ok_call_( const char *file, int line, const struct ime_call *expected, const struct ime_call *received ) { int ret;
@@ -2554,13 +2554,13 @@ done: case IME_SELECT: todo_wine_if( expected->todo ) ok_(file, line)( !ret, "got hkl %p, himc %p, IME_SELECT select %u\n", received->hkl, received->himc, received->select ); - return; + return ret; case IME_NOTIFY: todo_wine_if( expected->todo ) ok_(file, line)( !ret, "got hkl %p, himc %p, IME_NOTIFY action %#x, index %#x, value %#x\n", received->hkl, received->himc, received->notify.action, received->notify.index, received->notify.value ); - return; + return ret; }
switch (expected->func) @@ -2576,21 +2576,28 @@ done: expected->notify.value ); break; } + + return 0; }
#define ok_seq( a ) ok_seq_( __FILE__, __LINE__, a, #a ) static void ok_seq_( const char *file, int line, const struct ime_call *expected, const char *context ) { const struct ime_call *received = ime_calls; - UINT i = 0; + UINT i = 0, ret;
while (expected->func || received->func) { winetest_push_context( "%u%s%s", i++, !expected->func ? " (spurious)" : "", !received->func ? " (missing)" : "" ); - ok_call_( file, line, expected, received ); - if (expected->func) expected++; - if (received->func) received++; + ret = ok_call_( file, line, expected, received ); + if (ret && expected->todo && !strcmp( winetest_platform, "wine" )) + expected++; + else + { + if (expected->func) expected++; + if (received->func) received++; + } winetest_pop_context(); }
@@ -3811,7 +3818,6 @@ static void test_ImmActivateLayout(void) { .hkl = default_hkl, .himc = default_himc, .func = IME_SELECT, .select = 0, - .todo = TRUE, }, {0}, }; @@ -3824,6 +3830,20 @@ static void test_ImmActivateLayout(void) }, {0}, }; + const struct ime_call deactivate_with_window_seq[] = + { + { + .hkl = expect_ime, .himc = default_himc, + .func = IME_NOTIFY, .notify = {.action = NI_COMPOSITIONSTR, .index = CPS_CANCEL, .value = 0}, + .todo = TRUE, + }, + { + .hkl = default_hkl, .himc = default_himc, + .func = IME_SELECT, .select = 0, + .todo = TRUE, + }, + {0}, + }; HKL hkl, old_hkl = GetKeyboardLayout( 0 ); UINT ret;
@@ -3896,7 +3916,7 @@ static void test_ImmActivateLayout(void) ok_eq( hkl, GetKeyboardLayout( 0 ), HKL, "%p" );
ok_eq( hkl, ActivateKeyboardLayout( old_hkl, 0 ), HKL, "%p" ); - ok_seq( deactivate_seq ); + ok_seq( deactivate_with_window_seq );
ok_eq( old_hkl, GetKeyboardLayout( 0 ), HKL, "%p" );
@@ -3968,12 +3988,12 @@ static void test_ImmCreateInputContext(void) { .hkl = default_hkl, .himc = default_himc, .func = IME_SELECT, .select = 0, - .todo = TRUE, .flaky_himc = TRUE, + .flaky_himc = TRUE, }, { .hkl = default_hkl, .himc = 0/*himc[0]*/, .func = IME_SELECT, .select = 0, - .todo = TRUE, .flaky_himc = TRUE, + .flaky_himc = TRUE, }, {0}, };
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/imm.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index 2c3af063ac5..e3c7b3d579b 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -3025,27 +3025,24 @@ BOOL WINAPI ImmTranslateMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lKeyD * ImmProcessKey(IMM32.@) * ( Undocumented, called from user32.dll ) */ -BOOL WINAPI ImmProcessKey(HWND hwnd, HKL hKL, UINT vKey, LPARAM lKeyData, DWORD unknown) +BOOL WINAPI ImmProcessKey( HWND hwnd, HKL hkl, UINT vkey, LPARAM lparam, DWORD unknown ) { - struct imc *data; - HIMC imc = ImmGetContext(hwnd); + struct imc *imc; BYTE state[256]; + BOOL ret;
- TRACE("%p %p %x %x %lx\n",hwnd, hKL, vKey, (UINT)lKeyData, unknown); + TRACE( "hwnd %p, hkl %p, vkey %#x, lparam %#Ix, unknown %#lx\n", hwnd, hkl, vkey, lparam, unknown );
- if (!(data = get_imc_data( imc ))) return FALSE; - imc_select_hkl( data, hKL ); - if (!data->ime) return FALSE; + if (!(imc = get_imc_data( ImmGetContext( hwnd ) ))) return FALSE; + imc_select_hkl( imc, hkl ); + if (!imc->ime) return FALSE;
- GetKeyboardState(state); - if (data->ime->pImeProcessKey( imc, vKey, lKeyData, state )) - { - data->lastVK = vKey; - return TRUE; - } + GetKeyboardState( state );
- data->lastVK = VK_PROCESSKEY; - return FALSE; + ret = imc->ime->pImeProcessKey( imc->handle, vkey, lparam, state ); + imc->lastVK = ret ? vkey : VK_PROCESSKEY; + + return ret; }
/***********************************************************************
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/imm.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index e3c7b3d579b..447fbded41d 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -3033,6 +3033,7 @@ BOOL WINAPI ImmProcessKey( HWND hwnd, HKL hkl, UINT vkey, LPARAM lparam, DWORD u
TRACE( "hwnd %p, hkl %p, vkey %#x, lparam %#Ix, unknown %#lx\n", hwnd, hkl, vkey, lparam, unknown );
+ if (hkl != GetKeyboardLayout( 0 )) return FALSE; if (!(imc = get_imc_data( ImmGetContext( hwnd ) ))) return FALSE; imc_select_hkl( imc, hkl ); if (!imc->ime) return FALSE;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/tests/imm32.c | 82 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 79 insertions(+), 3 deletions(-)
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index 38093031627..944604c2975 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -2499,6 +2499,7 @@ enum ime_function { IME_SELECT = 1, IME_NOTIFY, + IME_PROCESS_KEY, };
struct ime_call @@ -2516,6 +2517,11 @@ struct ime_call int index; int value; } notify; + struct + { + WORD vkey; + LPARAM key_data; + } process_key; };
BOOL todo; @@ -2546,6 +2552,10 @@ static int ok_call_( const char *file, int line, const struct ime_call *expected if ((ret = expected->notify.index - received->notify.index)) goto done; if ((ret = expected->notify.value - received->notify.value)) goto done; break; + case IME_PROCESS_KEY: + if ((ret = expected->process_key.vkey - received->process_key.vkey)) goto done; + if ((ret = expected->process_key.key_data - received->process_key.key_data)) goto done; + break; }
done: @@ -2561,6 +2571,11 @@ done: received->hkl, received->himc, received->notify.action, received->notify.index, received->notify.value ); return ret; + case IME_PROCESS_KEY: + todo_wine_if( expected->todo ) + ok_(file, line)( !ret, "got hkl %p, himc %p, IME_PROCESS_KEY vkey %#x, key_data %#Ix\n", + received->hkl, received->himc, received->process_key.vkey, received->process_key.key_data ); + return ret; }
switch (expected->func) @@ -2575,6 +2590,11 @@ done: expected->hkl, expected->himc, expected->notify.action, expected->notify.index, expected->notify.value ); break; + case IME_PROCESS_KEY: + todo_wine_if( expected->todo ) + ok_(file, line)( !ret, "hkl %p, himc %p, IME_PROCESS_KEY vkey %#x, key_data %#Ix\n", + expected->hkl, expected->himc, expected->process_key.vkey, expected->process_key.key_data ); + break; }
return 0; @@ -2772,11 +2792,15 @@ static BOOL WINAPI ime_ImeInquire( IMEINFO *info, WCHAR *ui_class, DWORD flags )
static BOOL WINAPI ime_ImeProcessKey( HIMC himc, UINT vkey, LPARAM key_data, BYTE *key_state ) { + struct ime_call call = + { + .hkl = GetKeyboardLayout( 0 ), .himc = himc, + .func = IME_PROCESS_KEY, .process_key = {.vkey = vkey, .key_data = key_data} + }; ime_trace( "himc %p, vkey %u, key_data %#Ix, key_state %p\n", himc, vkey, key_data, key_state ); - ok_eq( default_hkl, GetKeyboardLayout( 0 ), HKL, "%p" ); - ok( 0, "unexpected call\n" ); - return FALSE; + ime_calls[ime_call_count++] = call; + return TRUE; }
static BOOL WINAPI ime_ImeRegisterWord( const WCHAR *reading, DWORD style, const WCHAR *string ) @@ -3798,6 +3822,57 @@ cleanup: winetest_pop_context(); }
+static void test_ImmProcessKey(void) +{ + const struct ime_call process_key_seq[] = + { + { + .hkl = expect_ime, .himc = default_himc, + .func = IME_PROCESS_KEY, .process_key = {.vkey = 'A', .key_data = 0}, + }, + {0}, + }; + HKL hkl, old_hkl = GetKeyboardLayout( 0 ); + UINT_PTR ret; + + hwnd = CreateWindowW( L"static", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 100, 100, 100, 100, NULL, NULL, NULL, NULL ); + ok( !!hwnd, "CreateWindowW failed, error %lu\n", GetLastError() ); + + ok_ret( 0, ImmProcessKey( hwnd, old_hkl, 'A', 0, 0 ) ); + ok_seq( empty_sequence ); + + ime_info.fdwProperty = IME_PROP_END_UNLOAD | IME_PROP_UNICODE; + + if (!(hkl = ime_install())) return; + + ok_ret( 1, ImmActivateLayout( hkl ) ); + memset( ime_calls, 0, sizeof(ime_calls) ); + ime_call_count = 0; + + ok_ret( 0, ImmProcessKey( 0, hkl, 'A', 0, 0 ) ); + ok_seq( empty_sequence ); + + ret = ImmProcessKey( hwnd, hkl, 'A', 0, 0 ); + todo_wine + ok_ret( 2, ret ); + ok_seq( process_key_seq ); + + ok_eq( hkl, GetKeyboardLayout( 0 ), HKL, "%p" ); + ok_ret( 0, ImmProcessKey( hwnd, old_hkl, 'A', 0, 0 ) ); + todo_wine + ok_seq( empty_sequence ); + ok_eq( hkl, GetKeyboardLayout( 0 ), HKL, "%p" ); + + ok_ret( 1, ImmActivateLayout( old_hkl ) ); + ok_ret( 1, DestroyWindow( hwnd ) ); + + ime_cleanup( hkl ); + ok_ret( 1, ImmFreeLayout( hkl ) ); + memset( ime_calls, 0, sizeof(ime_calls) ); + ime_call_count = 0; +} + static void test_ImmActivateLayout(void) { const struct ime_call activate_seq[] = @@ -4127,6 +4202,7 @@ START_TEST(imm32)
test_ImmActivateLayout(); test_ImmCreateInputContext(); + test_ImmProcessKey();
if (init()) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/tests/imm32.c | 183 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 172 insertions(+), 11 deletions(-)
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index 944604c2975..111adcf290c 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -118,6 +118,17 @@ extern BOOL WINAPI ImmActivateLayout(HKL); DEFINE_EXPECT(WM_IME_SETCONTEXT_DEACTIVATE); DEFINE_EXPECT(WM_IME_SETCONTEXT_ACTIVATE);
+static void process_messages(void) +{ + MSG msg; + + while (PeekMessageA( &msg, 0, 0, 0, PM_REMOVE )) + { + TranslateMessage( &msg ); + DispatchMessageA( &msg ); + } +} + /* * msgspy - record and analyse message traces sent to a certain window */ @@ -2500,6 +2511,7 @@ enum ime_function IME_SELECT = 1, IME_NOTIFY, IME_PROCESS_KEY, + MSG_IME_UI, };
struct ime_call @@ -2522,9 +2534,16 @@ struct ime_call WORD vkey; LPARAM key_data; } process_key; + struct + { + UINT msg; + WPARAM wparam; + LPARAM lparam; + } message; };
BOOL todo; + BOOL broken; BOOL flaky_himc; };
@@ -2556,9 +2575,16 @@ static int ok_call_( const char *file, int line, const struct ime_call *expected if ((ret = expected->process_key.vkey - received->process_key.vkey)) goto done; if ((ret = expected->process_key.key_data - received->process_key.key_data)) goto done; break; + case MSG_IME_UI: + if ((ret = expected->message.msg - received->message.msg)) goto done; + if ((ret = (expected->message.wparam - received->message.wparam))) goto done; + if ((ret = (expected->message.lparam - received->message.lparam))) goto done; + break; }
done: + if (ret && broken( expected->broken )) return ret; + switch (received->func) { case IME_SELECT: @@ -2576,6 +2602,11 @@ done: ok_(file, line)( !ret, "got hkl %p, himc %p, IME_PROCESS_KEY vkey %#x, key_data %#Ix\n", received->hkl, received->himc, received->process_key.vkey, received->process_key.key_data ); return ret; + case MSG_IME_UI: + todo_wine_if( expected->todo ) + ok_(file, line)( !ret, "got hkl %p, himc %p, MSG_IME_UI msg %#x, wparam %#Ix, lparam %#Ix\n", received->hkl, + received->himc, received->message.msg, received->message.wparam, received->message.lparam ); + return ret; }
switch (expected->func) @@ -2595,6 +2626,11 @@ done: ok_(file, line)( !ret, "hkl %p, himc %p, IME_PROCESS_KEY vkey %#x, key_data %#Ix\n", expected->hkl, expected->himc, expected->process_key.vkey, expected->process_key.key_data ); break; + case MSG_IME_UI: + todo_wine_if( expected->todo ) + ok_(file, line)( !ret, "hkl %p, himc %p, MSG_IME_UI msg %#x, wparam %#Ix, lparam %#Ix\n", expected->hkl, + expected->himc, expected->message.msg, expected->message.wparam, expected->message.lparam ); + break; }
return 0; @@ -2613,6 +2649,8 @@ static void ok_seq_( const char *file, int line, const struct ime_call *expected ret = ok_call_( file, line, expected, received ); if (ret && expected->todo && !strcmp( winetest_platform, "wine" )) expected++; + else if (ret && broken(expected->broken)) + expected++; else { if (expected->func) expected++; @@ -2625,9 +2663,46 @@ static void ok_seq_( const char *file, int line, const struct ime_call *expected ime_call_count = 0; }
+static BOOL ignore_message( UINT msg ) +{ + switch (msg) + { + case WM_IME_STARTCOMPOSITION: + case WM_IME_ENDCOMPOSITION: + case WM_IME_COMPOSITION: + case WM_IME_SETCONTEXT: + case WM_IME_NOTIFY: + case WM_IME_CONTROL: + case WM_IME_COMPOSITIONFULL: + case WM_IME_SELECT: + case WM_IME_CHAR: + case 0x287: + case WM_IME_REQUEST: + case WM_IME_KEYDOWN: + case WM_IME_KEYUP: + return FALSE; + default: + return TRUE; + } +} + static LRESULT CALLBACK ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { + struct ime_call call = + { + .hkl = GetKeyboardLayout( 0 ), .himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ), + .func = MSG_IME_UI, .message = {.msg = msg, .wparam = wparam, .lparam = lparam} + }; + LONG_PTR ptr; + ime_trace( "hwnd %p, msg %#x, wparam %#Ix, lparam %#Ix\n", hwnd, msg, wparam, lparam ); + + if (ignore_message( msg )) return DefWindowProcW( hwnd, msg, wparam, lparam ); + + ptr = GetWindowLongPtrW( hwnd, IMMGWL_PRIVATE ); + ok( !ptr, "got IMMGWL_PRIVATE %#Ix\n", ptr ); + + ime_calls[ime_call_count++] = call; return DefWindowProcW( hwnd, msg, wparam, lparam ); }
@@ -2857,7 +2932,6 @@ static UINT WINAPI ime_ImeToAsciiEx( UINT vkey, UINT scan_code, BYTE *key_state, { ime_trace( "vkey %u, scan_code %u, key_state %p, msgs %p, state %u, himc %p\n", vkey, scan_code, key_state, msgs, state, himc ); - ok( 0, "unexpected call\n" ); return 0; }
@@ -3838,6 +3912,7 @@ static void test_ImmProcessKey(void) hwnd = CreateWindowW( L"static", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 100, 100, NULL, NULL, NULL, NULL ); ok( !!hwnd, "CreateWindowW failed, error %lu\n", GetLastError() ); + process_messages();
ok_ret( 0, ImmProcessKey( hwnd, old_hkl, 'A', 0, 0 ) ); ok_seq( empty_sequence ); @@ -3847,6 +3922,7 @@ static void test_ImmProcessKey(void) if (!(hkl = ime_install())) return;
ok_ret( 1, ImmActivateLayout( hkl ) ); + process_messages(); memset( ime_calls, 0, sizeof(ime_calls) ); ime_call_count = 0;
@@ -3869,6 +3945,7 @@ static void test_ImmProcessKey(void)
ime_cleanup( hkl ); ok_ret( 1, ImmFreeLayout( hkl ) ); + process_messages(); memset( ime_calls, 0, sizeof(ime_calls) ); ime_call_count = 0; } @@ -3896,30 +3973,76 @@ static void test_ImmActivateLayout(void) }, {0}, }; - const struct ime_call activate_with_window_seq[] = + struct ime_call activate_with_window_seq[] = { { .hkl = expect_ime, .himc = default_himc, .func = IME_SELECT, .select = 1, + .todo = TRUE, .flaky_himc = TRUE, + }, + { + .hkl = expect_ime, .himc = 0/*himc*/, + .func = IME_SELECT, .select = 1, + .todo = TRUE, .flaky_himc = TRUE, + }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_SELECT, .wparam = 1, .lparam = (LPARAM)expect_ime}, + .todo = TRUE, + }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_NOTIFY, .wparam = IMN_OPENSTATUSWINDOW}, + .todo = TRUE, + }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_NOTIFY, .wparam = IMN_SETCONVERSIONMODE}, + .todo = TRUE, .broken = (default_hkl == (HKL)0x04120412), + }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_NOTIFY, .wparam = IMN_SETSENTENCEMODE}, .todo = TRUE, }, {0}, }; - const struct ime_call deactivate_with_window_seq[] = + struct ime_call deactivate_with_window_seq[] = { { .hkl = expect_ime, .himc = default_himc, .func = IME_NOTIFY, .notify = {.action = NI_COMPOSITIONSTR, .index = CPS_CANCEL, .value = 0}, + .todo = TRUE, .flaky_himc = TRUE, + }, + { + .hkl = expect_ime, .himc = 0/*himc*/, + .func = IME_NOTIFY, .notify = {.action = NI_COMPOSITIONSTR, .index = CPS_CANCEL, .value = 0}, + .todo = TRUE, .flaky_himc = TRUE, + }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_NOTIFY, .wparam = IMN_CLOSESTATUSWINDOW}, + .todo = TRUE, + }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_SELECT, .wparam = 0, .lparam = (LPARAM)expect_ime}, .todo = TRUE, }, { .hkl = default_hkl, .himc = default_himc, .func = IME_SELECT, .select = 0, - .todo = TRUE, + .todo = TRUE, .flaky_himc = TRUE, + }, + { + .hkl = default_hkl, .himc = 0/*himc*/, + .func = IME_SELECT, .select = 0, + .todo = TRUE, .flaky_himc = TRUE, }, {0}, }; HKL hkl, old_hkl = GetKeyboardLayout( 0 ); + HIMC himc; UINT ret;
SET_ENABLE( ImeInquire, TRUE ); @@ -3980,34 +4103,48 @@ static void test_ImmActivateLayout(void) hwnd = CreateWindowW( L"static", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 100, 100, NULL, NULL, NULL, NULL ); ok( !!hwnd, "CreateWindowW failed, error %lu\n", GetLastError() ); + process_messages(); + ok_seq( empty_sequence ); + + himc = ImmCreateContext(); + ok( !!himc, "got himc %p\n", himc ); ok_seq( empty_sequence );
SET_EXPECT( ImeInquire ); ok_eq( old_hkl, ActivateKeyboardLayout( hkl, 0 ), HKL, "%p" ); todo_wine CHECK_CALLED( ImeInquire ); + activate_with_window_seq[1].himc = himc; ok_seq( activate_with_window_seq );
ok_eq( hkl, GetKeyboardLayout( 0 ), HKL, "%p" );
+ /* FIXME: ignore spurious VK_CONTROL ImeProcessKey / ImeToAsciiEx calls */ + process_messages(); + memset( ime_calls, 0, sizeof(ime_calls) ); + ime_call_count = 0; + ok_eq( hkl, ActivateKeyboardLayout( old_hkl, 0 ), HKL, "%p" ); + deactivate_with_window_seq[1].himc = himc; + deactivate_with_window_seq[5].himc = himc; ok_seq( deactivate_with_window_seq );
ok_eq( old_hkl, GetKeyboardLayout( 0 ), HKL, "%p" );
- ime_cleanup( hkl ); + ok_ret( 1, ImmDestroyContext( himc ) ); ok_seq( empty_sequence );
- /* ImmActivateLayout leaks the IME, we need to free it manually */ - SET_EXPECT( ImeDestroy ); - ret = ImmFreeLayout( hkl ); - ok( ret, "ImmFreeLayout returned %u\n", ret ); + ime_cleanup( hkl ); + ok_ret( 1, ImmFreeLayout( hkl ) ); todo_wine CHECK_CALLED( ImeDestroy ); ok_seq( empty_sequence );
ok_ret( 1, DestroyWindow( hwnd ) ); + process_messages(); + memset( ime_calls, 0, sizeof(ime_calls) ); + ime_call_count = 0;
cleanup: @@ -4029,6 +4166,16 @@ static void test_ImmCreateInputContext(void) .func = IME_SELECT, .select = 1, .flaky_himc = TRUE, }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_SELECT, .wparam = 1, .lparam = (LPARAM)expect_ime}, + .todo = TRUE, + }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_NOTIFY, .wparam = IMN_OPENSTATUSWINDOW}, + .todo = TRUE, + }, {0}, }; struct ime_call select1_seq[] = @@ -4060,6 +4207,16 @@ static void test_ImmCreateInputContext(void) .func = IME_NOTIFY, .notify = {.action = NI_COMPOSITIONSTR, .index = CPS_CANCEL, .value = 0}, .todo = TRUE, .flaky_himc = TRUE, }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_NOTIFY, .wparam = IMN_CLOSESTATUSWINDOW}, + .todo = TRUE, + }, + { + .hkl = expect_ime, .himc = default_himc, + .func = MSG_IME_UI, .message = {.msg = WM_IME_SELECT, .wparam = 0, .lparam = (LPARAM)expect_ime}, + .todo = TRUE, + }, { .hkl = default_hkl, .himc = default_himc, .func = IME_SELECT, .select = 0, @@ -4095,6 +4252,7 @@ static void test_ImmCreateInputContext(void) hwnd = CreateWindowW( L"static", NULL, WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 100, 100, NULL, NULL, NULL, NULL ); ok( !!hwnd, "CreateWindowW failed, error %lu\n", GetLastError() ); + process_messages();
ctx = ImmLockIMC( default_himc ); ok( !!ctx, "ImmLockIMC failed, error %lu\n", GetLastError() ); @@ -4153,18 +4311,21 @@ static void test_ImmCreateInputContext(void)
ok_ret( 1, ImmActivateLayout( old_hkl ) ); deactivate_seq[1].himc = himc[0]; - deactivate_seq[3].himc = himc[0]; + deactivate_seq[5].himc = himc[0]; ok_seq( deactivate_seq );
ok_eq( old_hkl, GetKeyboardLayout( 0 ), HKL, "%p" );
- ok_ret( 1, ImmFreeLayout( hkl ) ); ime_cleanup( hkl ); + ok_ret( 1, ImmFreeLayout( hkl ) ); ok_seq( empty_sequence );
cleanup: ok_ret( 1, ImmDestroyContext( himc[0] ) ); ok_ret( 1, DestroyWindow( hwnd ) ); + process_messages(); + memset( ime_calls, 0, sizeof(ime_calls) ); + ime_call_count = 0;
ime_info.dwPrivateDataSize = 0; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/tests/imm32.c | 109 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-)
diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index 111adcf290c..5a1f3000b12 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -2915,8 +2915,7 @@ static BOOL WINAPI ime_ImeSelect( HIMC himc, BOOL select ) static BOOL WINAPI ime_ImeSetActiveContext( HIMC himc, BOOL flag ) { ime_trace( "himc %p, flag %#x\n", himc, flag ); - ok( 0, "unexpected call\n" ); - return FALSE; + return TRUE; }
static BOOL WINAPI ime_ImeSetCompositionString( HIMC himc, DWORD index, const void *comp, DWORD comp_len, @@ -3950,6 +3949,84 @@ static void test_ImmProcessKey(void) ime_call_count = 0; }
+struct ime_windows +{ + HWND ime_hwnd; + HWND ime_ui_hwnd; +}; + +static BOOL CALLBACK enum_thread_ime_windows( HWND hwnd, LPARAM lparam ) +{ + struct ime_windows *params = (void *)lparam; + WCHAR buffer[256]; + UINT ret; + + ime_trace( "hwnd %p, lparam %#Ix\n", hwnd, lparam ); + + ret = RealGetWindowClassW( hwnd, buffer, ARRAY_SIZE(buffer) ); + ok( ret, "RealGetWindowClassW returned %#x\n", ret ); + + if (!wcscmp( buffer, L"IME" )) + { + ok( !params->ime_hwnd, "Found extra IME window %p\n", hwnd ); + params->ime_hwnd = hwnd; + } + if (!wcscmp( buffer, ime_ui_class.lpszClassName )) + { + ok( !params->ime_ui_hwnd, "Found extra IME UI window %p\n", hwnd ); + params->ime_ui_hwnd = hwnd; + } + + return TRUE; +} + +struct test_activate_layout_params +{ + HKL hkl; + struct ime_windows *ime_windows; +}; + +static DWORD CALLBACK test_activate_layout_thread( void *arg ) +{ + struct test_activate_layout_params *params = arg; + struct ime_windows *ime_windows = params->ime_windows; + HKL hkl = GetKeyboardLayout( 0 ); + HWND hwnd; + + todo_wine ok( hkl == params->hkl || broken(hkl == default_hkl) /* win7 */, "got HKL %p\n", hkl ); + + hwnd = CreateWindowW( L"static", NULL, WS_VISIBLE | WS_POPUP, + 100, 100, 100, 100, 0, NULL, NULL, NULL ); + ok( !!hwnd, "CreateWindow failed, error %lu\n", GetLastError() ); + process_messages(); + + if (hkl == default_hkl) + { + ok_eq( default_hkl, ActivateKeyboardLayout( params->hkl, 0 ), HKL, "%p" ); + ok_eq( params->hkl, GetKeyboardLayout( 0 ), HKL, "%p" ); + } + + ok_ret( 1, EnumThreadWindows( GetCurrentThreadId(), enum_thread_ime_windows, (LPARAM)ime_windows ) ); + ok( !!ime_windows->ime_hwnd, "missing IME window\n" ); + todo_wine ok( !!ime_windows->ime_ui_hwnd, "missing IME UI window\n" ); + todo_wine ok_ret( (UINT_PTR)ime_windows->ime_hwnd, (UINT_PTR)GetParent( ime_windows->ime_ui_hwnd ) ); + + if (hkl == default_hkl) + { + ok_eq( params->hkl, ActivateKeyboardLayout( default_hkl, 0 ), HKL, "%p" ); + ok_eq( default_hkl, GetKeyboardLayout( 0 ), HKL, "%p" ); + } + + ShowWindow( hwnd, SW_HIDE ); + process_messages(); + + DestroyWindow( hwnd ); + memset( ime_calls, 0, sizeof(ime_calls) ); + ime_call_count = 0; + + return 0; +} + static void test_ImmActivateLayout(void) { const struct ime_call activate_seq[] = @@ -4042,6 +4119,9 @@ static void test_ImmActivateLayout(void) {0}, }; HKL hkl, old_hkl = GetKeyboardLayout( 0 ); + struct ime_windows ime_windows = {0}, other_ime_windows = {0}; + struct test_activate_layout_params thread_params = {.ime_windows = &other_ime_windows}; + HANDLE thread; HIMC himc; UINT ret;
@@ -4131,6 +4211,31 @@ static void test_ImmActivateLayout(void)
ok_eq( old_hkl, GetKeyboardLayout( 0 ), HKL, "%p" );
+ + ok_eq( old_hkl, ActivateKeyboardLayout( hkl, 0 ), HKL, "%p" ); + ok_eq( hkl, GetKeyboardLayout( 0 ), HKL, "%p" ); + + ok_ret( 1, EnumThreadWindows( GetCurrentThreadId(), enum_thread_ime_windows, (LPARAM)&ime_windows ) ); + ok( !!ime_windows.ime_hwnd, "missing IME window\n" ); + todo_wine ok( !!ime_windows.ime_ui_hwnd, "missing IME UI window\n" ); + todo_wine ok_ret( (UINT_PTR)ime_windows.ime_hwnd, (UINT_PTR)GetParent( ime_windows.ime_ui_hwnd ) ); + + thread_params.hkl = hkl; + thread = CreateThread( NULL, 0, test_activate_layout_thread, &thread_params, 0, NULL ); + ok( !!thread, "CreateThread failed, error %lu\n", GetLastError() ); + ok_ret( 0, WaitForSingleObject( thread, 30000 ) ); + ok_ret( 1, CloseHandle( thread ) ); + + ok_ne( other_ime_windows.ime_hwnd, ime_windows.ime_hwnd, HWND, "%p" ); + todo_wine ok_ne( other_ime_windows.ime_ui_hwnd, ime_windows.ime_ui_hwnd, HWND, "%p" ); + + ok_eq( hkl, ActivateKeyboardLayout( old_hkl, 0 ), HKL, "%p" ); + ok_eq( old_hkl, GetKeyboardLayout( 0 ), HKL, "%p" ); + process_messages(); + memset( ime_calls, 0, sizeof(ime_calls) ); + ime_call_count = 0; + + ok_ret( 1, ImmDestroyContext( himc ) ); ok_seq( empty_sequence );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/imm.c | 5 +++++ dlls/imm32/tests/imm32.c | 16 ++++++++++------ dlls/win32u/input.c | 8 +++++++- include/ntuser.h | 2 ++ 4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index 447fbded41d..62fc855826b 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -3152,6 +3152,11 @@ static LRESULT ime_internal_msg( WPARAM wparam, LPARAM lparam) ImmSetActiveContext(hwnd, himc, wparam == IME_INTERNAL_ACTIVATE); ImmReleaseContext(hwnd, himc); break; + case IME_INTERNAL_HKL_ACTIVATE: + ImmEnumInputContext( 0, enum_activate_layout, 0 ); + break; + case IME_INTERNAL_HKL_DEACTIVATE: + break; default: FIXME("wparam = %Ix\n", wparam); break; diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index 5a1f3000b12..d42e1ee8af7 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -4055,12 +4055,12 @@ static void test_ImmActivateLayout(void) { .hkl = expect_ime, .himc = default_himc, .func = IME_SELECT, .select = 1, - .todo = TRUE, .flaky_himc = TRUE, + .flaky_himc = TRUE, }, { .hkl = expect_ime, .himc = 0/*himc*/, .func = IME_SELECT, .select = 1, - .todo = TRUE, .flaky_himc = TRUE, + .flaky_himc = TRUE, }, { .hkl = expect_ime, .himc = default_himc, @@ -4109,12 +4109,12 @@ static void test_ImmActivateLayout(void) { .hkl = default_hkl, .himc = default_himc, .func = IME_SELECT, .select = 0, - .todo = TRUE, .flaky_himc = TRUE, + .flaky_himc = TRUE, }, { .hkl = default_hkl, .himc = 0/*himc*/, .func = IME_SELECT, .select = 0, - .todo = TRUE, .flaky_himc = TRUE, + .flaky_himc = TRUE, }, {0}, }; @@ -4192,7 +4192,6 @@ static void test_ImmActivateLayout(void)
SET_EXPECT( ImeInquire ); ok_eq( old_hkl, ActivateKeyboardLayout( hkl, 0 ), HKL, "%p" ); - todo_wine CHECK_CALLED( ImeInquire ); activate_with_window_seq[1].himc = himc; ok_seq( activate_with_window_seq ); @@ -4204,7 +4203,9 @@ static void test_ImmActivateLayout(void) memset( ime_calls, 0, sizeof(ime_calls) ); ime_call_count = 0;
+ todo_ImeDestroy = TRUE; /* Wine doesn't leak the IME */ ok_eq( hkl, ActivateKeyboardLayout( old_hkl, 0 ), HKL, "%p" ); + todo_ImeDestroy = FALSE; deactivate_with_window_seq[1].himc = himc; deactivate_with_window_seq[5].himc = himc; ok_seq( deactivate_with_window_seq ); @@ -4212,7 +4213,9 @@ static void test_ImmActivateLayout(void) ok_eq( old_hkl, GetKeyboardLayout( 0 ), HKL, "%p" );
+ todo_ImeInquire = TRUE; ok_eq( old_hkl, ActivateKeyboardLayout( hkl, 0 ), HKL, "%p" ); + todo_ImeInquire = FALSE; ok_eq( hkl, GetKeyboardLayout( 0 ), HKL, "%p" );
ok_ret( 1, EnumThreadWindows( GetCurrentThreadId(), enum_thread_ime_windows, (LPARAM)&ime_windows ) ); @@ -4229,7 +4232,9 @@ static void test_ImmActivateLayout(void) ok_ne( other_ime_windows.ime_hwnd, ime_windows.ime_hwnd, HWND, "%p" ); todo_wine ok_ne( other_ime_windows.ime_ui_hwnd, ime_windows.ime_ui_hwnd, HWND, "%p" );
+ todo_ImeDestroy = TRUE; /* Wine doesn't leak the IME */ ok_eq( hkl, ActivateKeyboardLayout( old_hkl, 0 ), HKL, "%p" ); + todo_ImeDestroy = FALSE; ok_eq( old_hkl, GetKeyboardLayout( 0 ), HKL, "%p" ); process_messages(); memset( ime_calls, 0, sizeof(ime_calls) ); @@ -4242,7 +4247,6 @@ static void test_ImmActivateLayout(void) SET_EXPECT( ImeDestroy ); ime_cleanup( hkl ); ok_ret( 1, ImmFreeLayout( hkl ) ); - todo_wine CHECK_CALLED( ImeDestroy ); ok_seq( empty_sequence );
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 34f6727d66e..f806294cb20 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -1219,12 +1219,14 @@ HKL WINAPI NtUserActivateKeyboardLayout( HKL layout, UINT flags ) return 0;
old_layout = info->kbd_layout; - info->kbd_layout = layout; if (old_layout != layout) { + HWND ime_hwnd = get_default_ime_window( 0 ); const NLS_LOCALE_DATA *data; CHARSETINFO cs = {0};
+ if (ime_hwnd) send_message( ime_hwnd, WM_IME_INTERNAL, IME_INTERNAL_HKL_DEACTIVATE, HandleToUlong(old_layout) ); + if (HIWORD(layout) & 0x8000) FIXME( "Aliased keyboard layout not yet implemented\n" ); else if (!(data = get_locale_data( HIWORD(layout) ))) @@ -1232,7 +1234,11 @@ HKL WINAPI NtUserActivateKeyboardLayout( HKL layout, UINT flags ) else translate_charset_info( ULongToPtr(data->idefaultansicodepage), &cs, TCI_SRCCODEPAGE );
+ info->kbd_layout = layout; info->kbd_layout_id = 0; + + if (ime_hwnd) send_message( ime_hwnd, WM_IME_INTERNAL, IME_INTERNAL_HKL_ACTIVATE, HandleToUlong(layout) ); + if ((focus = get_focus()) && get_window_thread( focus, NULL ) == GetCurrentThreadId()) send_message( focus, WM_INPUTLANGCHANGE, cs.ciCharset, (LPARAM)layout ); } diff --git a/include/ntuser.h b/include/ntuser.h index 629f6353fa3..14e1f3757d4 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -487,6 +487,8 @@ enum wine_internal_message #define WM_IME_INTERNAL 0x287 #define IME_INTERNAL_ACTIVATE 0x17 #define IME_INTERNAL_DEACTIVATE 0x18 +#define IME_INTERNAL_HKL_ACTIVATE 0x19 +#define IME_INTERNAL_HKL_DEACTIVATE 0x20
#define WM_SYSTIMER 0x0118
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/imm.c | 61 +++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 26 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index 62fc855826b..d68930bade3 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -62,7 +62,6 @@ struct ime
IMEINFO info; WCHAR ui_class[17]; - HWND ui_hwnd;
BOOL (WINAPI *pImeInquire)(IMEINFO *, void *, DWORD); BOOL (WINAPI *pImeConfigure)(HKL, HWND, DWORD, void *); @@ -93,6 +92,8 @@ struct imc
struct ime *ime; UINT lastVK; + + HWND ui_hwnd; /* IME UI window, on the default input context */ };
#define WINE_IMC_VALID_MAGIC 0x56434D49 @@ -569,6 +570,8 @@ static void imc_select_hkl( struct imc *imc, HKL hkl ) if (imc->ime) { if (imc->ime->hkl == hkl) return; + if (imc->ui_hwnd) DestroyWindow( imc->ui_hwnd ); + imc->ui_hwnd = NULL; imc->ime->pImeSelect( imc->handle, FALSE ); ime_release( imc->ime ); ImmDestroyIMCC( imc->IMC.hPrivate ); @@ -614,6 +617,7 @@ static BOOL free_input_context_data( HIMC hIMC )
TRACE( "Destroying %p\n", hIMC );
+ if (data->ui_hwnd) DestroyWindow( data->ui_hwnd ); data->ime->pImeSelect( hIMC, FALSE ); SendMessageW( data->IMC.hWnd, WM_IME_SELECT, FALSE, (LPARAM)data->ime );
@@ -648,7 +652,6 @@ static void IMM_FreeAllImmHkl(void) ime->pImeDestroy( 1 ); FreeLibrary( ime->module );
- if (ime->ui_hwnd) DestroyWindow( ime->ui_hwnd ); free( ime ); } } @@ -923,6 +926,29 @@ static struct imc *get_imc_data( HIMC handle ) return create_input_context(handle); }
+static struct imc *default_input_context(void) +{ + UINT *himc = &NtUserGetThreadInfo()->default_imc; + if (!*himc) *himc = (UINT_PTR)NtUserCreateInputContext( 0 ); + return get_imc_data( (HIMC)(UINT_PTR)*himc ); +} + +static HWND get_ime_ui_window(void) +{ + struct imc *imc = default_input_context(); + + imc_select_hkl( imc, GetKeyboardLayout( 0 ) ); + if (!imc->ime) return 0; + + if (!imc->ui_hwnd) + { + imc->ui_hwnd = CreateWindowExW( WS_EX_TOOLWINDOW, imc->ime->ui_class, NULL, + WS_POPUP, 0, 0, 1, 1, 0, 0, imc->ime->module, 0 ); + SetWindowLongPtrW( imc->ui_hwnd, IMMGWL_IMC, (LONG_PTR)imc->handle ); + } + return imc->ui_hwnd; +} + /*********************************************************************** * ImmCreateContext (IMM32.@) */ @@ -2490,6 +2516,7 @@ BOOL WINAPI ImmSetCompositionWindow( { BOOL reshow = FALSE; struct imc *data = get_imc_data( hIMC ); + HWND ui_hwnd;
TRACE("(%p, %p)\n", hIMC, lpCompForm); if (lpCompForm) @@ -2507,15 +2534,15 @@ BOOL WINAPI ImmSetCompositionWindow(
data->IMC.cfCompForm = *lpCompForm;
- if (IsWindowVisible( data->ime->ui_hwnd )) + if ((ui_hwnd = get_ime_ui_window()) && IsWindowVisible( ui_hwnd )) { reshow = TRUE; - ShowWindow( data->ime->ui_hwnd, SW_HIDE ); + ShowWindow( ui_hwnd, SW_HIDE ); }
/* FIXME: this is a partial stub */
- if (reshow) ShowWindow( data->ime->ui_hwnd, SW_SHOWNOACTIVATE ); + if (ui_hwnd && reshow) ShowWindow( ui_hwnd, SW_SHOWNOACTIVATE );
ImmInternalSendIMENotify(data, IMN_SETCOMPOSITIONWINDOW, 0); return TRUE; @@ -2564,6 +2591,7 @@ BOOL WINAPI ImmSetConversionStatus( BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen) { struct imc *data = get_imc_data( hIMC ); + HWND ui_hwnd;
TRACE("%p %d\n", hIMC, fOpen);
@@ -2575,14 +2603,7 @@ BOOL WINAPI ImmSetOpenStatus(HIMC hIMC, BOOL fOpen)
if (NtUserQueryInputContext( hIMC, NtUserInputContextThreadId ) != GetCurrentThreadId()) return FALSE;
- if (data->ime->ui_hwnd == NULL) - { - /* create the ime window */ - data->ime->ui_hwnd = CreateWindowExW( WS_EX_TOOLWINDOW, data->ime->ui_class, NULL, - WS_POPUP, 0, 0, 1, 1, 0, 0, data->ime->module, 0 ); - SetWindowLongPtrW( data->ime->ui_hwnd, IMMGWL_IMC, (LONG_PTR)data ); - } - else if (fOpen) SetWindowLongPtrW( data->ime->ui_hwnd, IMMGWL_IMC, (LONG_PTR)data ); + if ((ui_hwnd = get_ime_ui_window())) SetWindowLongPtrW( ui_hwnd, IMMGWL_IMC, (LONG_PTR)data );
if (!fOpen != !data->IMC.fOpen) { @@ -3099,18 +3120,6 @@ BOOL WINAPI ImmDisableLegacyIME(void) return TRUE; }
-static HWND get_ui_window(HKL hkl) -{ - struct ime *ime; - HWND hwnd; - - if (!(ime = ime_acquire( hkl ))) return 0; - hwnd = ime->ui_hwnd; - ime_release( ime ); - - return hwnd; -} - static BOOL is_ime_ui_msg(UINT msg) { switch (msg) @@ -3205,7 +3214,7 @@ LRESULT WINAPI __wine_ime_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
if (is_ime_ui_msg(msg)) { - if ((ui_hwnd = get_ui_window(NtUserGetKeyboardLayout(0)))) + if ((ui_hwnd = get_ime_ui_window())) { if (ansi) return SendMessageA(ui_hwnd, msg, wparam, lparam);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/imm.c | 5 ++++- dlls/imm32/tests/imm32.c | 6 +++--- 2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index d68930bade3..ed903cb8d00 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -3150,21 +3150,24 @@ static BOOL is_ime_ui_msg(UINT msg)
static LRESULT ime_internal_msg( WPARAM wparam, LPARAM lparam) { - HWND hwnd = (HWND)lparam; + HWND hwnd; HIMC himc;
switch (wparam) { case IME_INTERNAL_ACTIVATE: case IME_INTERNAL_DEACTIVATE: + hwnd = (HWND)lparam; himc = ImmGetContext(hwnd); ImmSetActiveContext(hwnd, himc, wparam == IME_INTERNAL_ACTIVATE); ImmReleaseContext(hwnd, himc); break; case IME_INTERNAL_HKL_ACTIVATE: ImmEnumInputContext( 0, enum_activate_layout, 0 ); + hwnd = get_ime_ui_window(); break; case IME_INTERNAL_HKL_DEACTIVATE: + hwnd = get_ime_ui_window(); break; default: FIXME("wparam = %Ix\n", wparam); diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index d42e1ee8af7..247d3c3114c 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -4008,7 +4008,7 @@ static DWORD CALLBACK test_activate_layout_thread( void *arg )
ok_ret( 1, EnumThreadWindows( GetCurrentThreadId(), enum_thread_ime_windows, (LPARAM)ime_windows ) ); ok( !!ime_windows->ime_hwnd, "missing IME window\n" ); - todo_wine ok( !!ime_windows->ime_ui_hwnd, "missing IME UI window\n" ); + ok( !!ime_windows->ime_ui_hwnd, "missing IME UI window\n" ); todo_wine ok_ret( (UINT_PTR)ime_windows->ime_hwnd, (UINT_PTR)GetParent( ime_windows->ime_ui_hwnd ) );
if (hkl == default_hkl) @@ -4220,7 +4220,7 @@ static void test_ImmActivateLayout(void)
ok_ret( 1, EnumThreadWindows( GetCurrentThreadId(), enum_thread_ime_windows, (LPARAM)&ime_windows ) ); ok( !!ime_windows.ime_hwnd, "missing IME window\n" ); - todo_wine ok( !!ime_windows.ime_ui_hwnd, "missing IME UI window\n" ); + ok( !!ime_windows.ime_ui_hwnd, "missing IME UI window\n" ); todo_wine ok_ret( (UINT_PTR)ime_windows.ime_hwnd, (UINT_PTR)GetParent( ime_windows.ime_ui_hwnd ) );
thread_params.hkl = hkl; @@ -4230,7 +4230,7 @@ static void test_ImmActivateLayout(void) ok_ret( 1, CloseHandle( thread ) );
ok_ne( other_ime_windows.ime_hwnd, ime_windows.ime_hwnd, HWND, "%p" ); - todo_wine ok_ne( other_ime_windows.ime_ui_hwnd, ime_windows.ime_ui_hwnd, HWND, "%p" ); + ok_ne( other_ime_windows.ime_ui_hwnd, ime_windows.ime_ui_hwnd, HWND, "%p" );
todo_ImeDestroy = TRUE; /* Wine doesn't leak the IME */ ok_eq( hkl, ActivateKeyboardLayout( old_hkl, 0 ), HKL, "%p" );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/imm.c | 4 ++-- dlls/imm32/tests/imm32.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index ed903cb8d00..4cbdceeb9d9 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -942,8 +942,8 @@ static HWND get_ime_ui_window(void)
if (!imc->ui_hwnd) { - imc->ui_hwnd = CreateWindowExW( WS_EX_TOOLWINDOW, imc->ime->ui_class, NULL, - WS_POPUP, 0, 0, 1, 1, 0, 0, imc->ime->module, 0 ); + imc->ui_hwnd = CreateWindowExW( WS_EX_TOOLWINDOW, imc->ime->ui_class, NULL, WS_POPUP, 0, 0, 1, 1, + ImmGetDefaultIMEWnd( 0 ), 0, imc->ime->module, 0 ); SetWindowLongPtrW( imc->ui_hwnd, IMMGWL_IMC, (LONG_PTR)imc->handle ); } return imc->ui_hwnd; diff --git a/dlls/imm32/tests/imm32.c b/dlls/imm32/tests/imm32.c index 247d3c3114c..231e0b5cf85 100644 --- a/dlls/imm32/tests/imm32.c +++ b/dlls/imm32/tests/imm32.c @@ -4009,7 +4009,7 @@ static DWORD CALLBACK test_activate_layout_thread( void *arg ) ok_ret( 1, EnumThreadWindows( GetCurrentThreadId(), enum_thread_ime_windows, (LPARAM)ime_windows ) ); ok( !!ime_windows->ime_hwnd, "missing IME window\n" ); ok( !!ime_windows->ime_ui_hwnd, "missing IME UI window\n" ); - todo_wine ok_ret( (UINT_PTR)ime_windows->ime_hwnd, (UINT_PTR)GetParent( ime_windows->ime_ui_hwnd ) ); + ok_ret( (UINT_PTR)ime_windows->ime_hwnd, (UINT_PTR)GetParent( ime_windows->ime_ui_hwnd ) );
if (hkl == default_hkl) { @@ -4221,7 +4221,7 @@ static void test_ImmActivateLayout(void) ok_ret( 1, EnumThreadWindows( GetCurrentThreadId(), enum_thread_ime_windows, (LPARAM)&ime_windows ) ); ok( !!ime_windows.ime_hwnd, "missing IME window\n" ); ok( !!ime_windows.ime_ui_hwnd, "missing IME UI window\n" ); - todo_wine ok_ret( (UINT_PTR)ime_windows.ime_hwnd, (UINT_PTR)GetParent( ime_windows.ime_ui_hwnd ) ); + ok_ret( (UINT_PTR)ime_windows.ime_hwnd, (UINT_PTR)GetParent( ime_windows.ime_ui_hwnd ) );
thread_params.hkl = hkl; thread = CreateThread( NULL, 0, test_activate_layout_thread, &thread_params, 0, NULL );
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=131250
Your paranoid android.
=== w11pro64 (32 bit report) ===
imm32: imm32.c:814: Test failed: expected WM_IME_SETCONTEXT_ACTIVATE imm32.c:300: Test failed: unexpected call WM_IME_SETCONTEXT_ACTIVATE imm32.c:893: Test failed: expected WM_IME_SETCONTEXT_ACTIVATE imm32.c:300: Test failed: unexpected call WM_IME_SETCONTEXT_ACTIVATE
=== w1064v1809 (64 bit report) ===
imm32: imm32.c:4245: Test failed: 0 (spurious): got hkl FFFFFFFFE020047F, himc 00000000000102AA, IME_SELECT select 0 imm32.c:4251: Test failed: 0 (spurious): got hkl FFFFFFFFE020047F, himc 0000000000060070, IME_NOTIFY action 0x15, index 0x4, value 0 imm32.c:4251: Test failed: 1 (spurious): got hkl FFFFFFFFE020047F, himc 0000000000060070, MSG_IME_UI msg 0x282, wparam 0x1, lparam 0 imm32.c:4251: Test failed: 2 (spurious): got hkl FFFFFFFFE020047F, himc 0000000000060070, MSG_IME_UI msg 0x285, wparam 0, lparam 0xffffffffe020047f imm32.c:4251: Test failed: 3 (spurious): got hkl 0000000004090409, himc 0000000000060070, IME_SELECT select 0
=== w1064_adm (64 bit report) ===
imm32: 1c60:imm32: unhandled exception c0000005 at 00007FF806DFBB75
=== w10pro64_ar (64 bit report) ===
imm32: imm32.c:4245: Test failed: 0 (spurious): got hkl FFFFFFFFE020047F, himc 0000000000010332, IME_SELECT select 0 imm32.c:4251: Test failed: 0 (spurious): got hkl FFFFFFFFE020047F, himc 000000000008008C, IME_NOTIFY action 0x15, index 0x4, value 0 imm32.c:4251: Test failed: 1 (spurious): got hkl FFFFFFFFE020047F, himc 000000000008008C, MSG_IME_UI msg 0x282, wparam 0x1, lparam 0 imm32.c:4251: Test failed: 2 (spurious): got hkl FFFFFFFFE020047F, himc 000000000008008C, MSG_IME_UI msg 0x285, wparam 0, lparam 0xffffffffe020047f imm32.c:4251: Test failed: 3 (spurious): got hkl 0000000004010C01, himc 000000000008008C, IME_SELECT select 0
=== w11pro64_amd (64 bit report) ===
imm32: imm32.c:814: Test failed: expected WM_IME_SETCONTEXT_ACTIVATE imm32.c:300: Test failed: unexpected call WM_IME_SETCONTEXT_ACTIVATE imm32.c:893: Test failed: expected WM_IME_SETCONTEXT_ACTIVATE imm32.c:300: Test failed: unexpected call WM_IME_SETCONTEXT_ACTIVATE
On Wed Mar 29 10:50:51 2023 +0000, **** wrote:
Marvin replied on the mailing list:
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details: The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=131250 Your paranoid android. === w11pro64 (32 bit report) === imm32: imm32.c:814: Test failed: expected WM_IME_SETCONTEXT_ACTIVATE imm32.c:300: Test failed: unexpected call WM_IME_SETCONTEXT_ACTIVATE imm32.c:893: Test failed: expected WM_IME_SETCONTEXT_ACTIVATE imm32.c:300: Test failed: unexpected call WM_IME_SETCONTEXT_ACTIVATE === w1064v1809 (64 bit report) === imm32: imm32.c:4245: Test failed: 0 (spurious): got hkl FFFFFFFFE020047F, himc 00000000000102AA, IME_SELECT select 0 imm32.c:4251: Test failed: 0 (spurious): got hkl FFFFFFFFE020047F, himc 0000000000060070, IME_NOTIFY action 0x15, index 0x4, value 0 imm32.c:4251: Test failed: 1 (spurious): got hkl FFFFFFFFE020047F, himc 0000000000060070, MSG_IME_UI msg 0x282, wparam 0x1, lparam 0 imm32.c:4251: Test failed: 2 (spurious): got hkl FFFFFFFFE020047F, himc 0000000000060070, MSG_IME_UI msg 0x285, wparam 0, lparam 0xffffffffe020047f imm32.c:4251: Test failed: 3 (spurious): got hkl 0000000004090409, himc 0000000000060070, IME_SELECT select 0 === w1064_adm (64 bit report) === imm32: 1c60:imm32: unhandled exception c0000005 at 00007FF806DFBB75 === w10pro64_ar (64 bit report) === imm32: imm32.c:4245: Test failed: 0 (spurious): got hkl FFFFFFFFE020047F, himc 0000000000010332, IME_SELECT select 0 imm32.c:4251: Test failed: 0 (spurious): got hkl FFFFFFFFE020047F, himc 000000000008008C, IME_NOTIFY action 0x15, index 0x4, value 0 imm32.c:4251: Test failed: 1 (spurious): got hkl FFFFFFFFE020047F, himc 000000000008008C, MSG_IME_UI msg 0x282, wparam 0x1, lparam 0 imm32.c:4251: Test failed: 2 (spurious): got hkl FFFFFFFFE020047F, himc 000000000008008C, MSG_IME_UI msg 0x285, wparam 0, lparam 0xffffffffe020047f imm32.c:4251: Test failed: 3 (spurious): got hkl 0000000004010C01, himc 000000000008008C, IME_SELECT select 0 === w11pro64_amd (64 bit report) === imm32: imm32.c:814: Test failed: expected WM_IME_SETCONTEXT_ACTIVATE imm32.c:300: Test failed: unexpected call WM_IME_SETCONTEXT_ACTIVATE imm32.c:893: Test failed: expected WM_IME_SETCONTEXT_ACTIVATE imm32.c:300: Test failed: unexpected call WM_IME_SETCONTEXT_ACTIVATE
I'll try to reduce the spurious failures.