-- v5: winex11: Use EM_REPLACESEL to set IME composition strings. winex11: Always zero terminate XIM composition string. winex11: Compute preedit text buffer sizes in WCHAR units. winex11: Use an IME UI message to set composition status. imm32: Only send GCS_CURSORPOS when cursor position changes. winex11: Use an IME UI message to set cursor pos. winex11: Use an IME UI message to get cursor pos. winex11: Use an IME UI message to set open status. win32u: Keep the builtin IME UI window in win32u struct imc. imm32: Add a struct ime field to track whether IME is builtin.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/imm.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index d29684f34a2..d7b9326bd1b 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -52,6 +52,7 @@ struct ime
HKL hkl; HMODULE module; + BOOL is_builtin; struct list entry;
IMEINFO info; @@ -470,7 +471,6 @@ BOOL WINAPI ImmFreeLayout( HKL hkl ) BOOL WINAPI ImmLoadIME( HKL hkl ) { WCHAR buffer[MAX_PATH] = {0}; - BOOL use_default_ime; struct ime *ime;
TRACE( "hkl %p\n", hkl ); @@ -482,11 +482,10 @@ BOOL WINAPI ImmLoadIME( HKL hkl ) return !!ime; }
- if (!ImmGetIMEFileNameW( hkl, buffer, MAX_PATH )) use_default_ime = TRUE; - else if (!(ime->module = LoadLibraryW( buffer ))) use_default_ime = TRUE; - else use_default_ime = FALSE; + if (!ImmGetIMEFileNameW( hkl, buffer, MAX_PATH )) ime->is_builtin = TRUE; + else if (!(ime->module = LoadLibraryW( buffer ))) ime->is_builtin = TRUE;
- if (use_default_ime) + if (ime->is_builtin) { if (*buffer) WARN( "Failed to load %s, falling back to default.\n", debugstr_w(buffer) ); if (!(ime->module = load_graphics_driver())) ime->module = LoadLibraryW( L"imm32" ); @@ -494,7 +493,7 @@ BOOL WINAPI ImmLoadIME( HKL hkl )
#define LOAD_FUNCPTR( f ) \ if (!(ime->p##f = (void *)GetProcAddress( ime->module, #f )) && \ - !(ime->p##f = use_default_ime ? (void *)f : NULL)) \ + !(ime->p##f = ime->is_builtin ? (void *)f : NULL)) \ { \ LeaveCriticalSection( &ime_cs ); \ WARN( "Can't find function %s in HKL %p IME\n", #f, hkl ); \
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/imm.c | 28 ++++++++++++++++++++++++---- dlls/win32u/imm.c | 11 +++++++++++ include/ntuser.h | 1 + 3 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/dlls/imm32/imm.c b/dlls/imm32/imm.c index d7b9326bd1b..1ce9cbdc570 100644 --- a/dlls/imm32/imm.c +++ b/dlls/imm32/imm.c @@ -622,11 +622,21 @@ static INPUTCONTEXT *ime_find_input_context( struct ime *ime, HIMC himc ) return &entry->context; }
+static BOOL CALLBACK enum_himc_set_builtin_ui( HIMC himc, LPARAM lparam ) +{ + NtUserUpdateInputContext( himc, NtUserInputContextBuiltinUI, lparam ); + return TRUE; +} + static void imc_release_ime( struct imc *imc, struct ime *ime ) { INPUTCONTEXT *ctx;
- if (imc->ui_hwnd) DestroyWindow( imc->ui_hwnd ); + if (imc->ui_hwnd) + { + ImmEnumInputContext( 0, enum_himc_set_builtin_ui, (LPARAM)0 ); + DestroyWindow( imc->ui_hwnd ); + } imc->ui_hwnd = NULL; ime->pImeSelect( imc->handle, FALSE );
@@ -1017,7 +1027,10 @@ static HWND get_ime_ui_window(void) imc->ui_hwnd = CreateWindowExW( WS_EX_TOOLWINDOW, ime->ui_class, NULL, WS_POPUP, 0, 0, 1, 1, ImmGetDefaultIMEWnd( 0 ), 0, ime->module, 0 ); SetWindowLongPtrW( imc->ui_hwnd, IMMGWL_IMC, (LONG_PTR)imc->handle ); + + if (ime->is_builtin) ImmEnumInputContext( 0, enum_himc_set_builtin_ui, (LPARAM)imc->ui_hwnd ); } + return imc->ui_hwnd; }
@@ -1026,10 +1039,17 @@ static HWND get_ime_ui_window(void) */ HIMC WINAPI ImmCreateContext(void) { - struct imc *new_context; + struct imc *imc; + struct ime *ime; + HIMC himc; + + if (!(imc = create_input_context( 0 ))) return 0; + himc = imc->handle; + + if ((imc = default_input_context()) && (ime = imc_select_ime( imc )) && ime->is_builtin) + NtUserUpdateInputContext( himc, NtUserInputContextBuiltinUI, (UINT_PTR)imc->ui_hwnd );
- if (!(new_context = create_input_context(0))) return 0; - return new_context->handle; + return himc; }
static BOOL IMM_DestroyContext(HIMC hIMC) diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c index 7dee4912e27..bf04cf82b92 100644 --- a/dlls/win32u/imm.c +++ b/dlls/win32u/imm.c @@ -40,6 +40,8 @@ struct imc struct user_object obj; DWORD thread_id; UINT_PTR client_ptr; + + HWND builtin_ui; /* IME UI window when builtin IME is used */ };
struct imm_thread_data @@ -80,6 +82,7 @@ HIMC WINAPI NtUserCreateInputContext( UINT_PTR client_ptr ) if (!(imc = malloc( sizeof(*imc) ))) return 0; imc->client_ptr = client_ptr; imc->thread_id = GetCurrentThreadId(); + imc->builtin_ui = 0; if (!(handle = alloc_user_handle( &imc->obj, NTUSER_OBJ_IMC ))) { free( imc ); @@ -127,6 +130,10 @@ BOOL WINAPI NtUserUpdateInputContext( HIMC handle, UINT attr, UINT_PTR value ) imc->client_ptr = value; break;
+ case NtUserInputContextBuiltinUI: + imc->builtin_ui = (HWND)value; + break; + default: FIXME( "unknown attr %u\n", attr ); ret = FALSE; @@ -156,6 +163,10 @@ UINT_PTR WINAPI NtUserQueryInputContext( HIMC handle, UINT attr ) ret = imc->thread_id; break;
+ case NtUserInputContextBuiltinUI: + ret = (UINT_PTR)imc->builtin_ui; + break; + default: FIXME( "unknown attr %u\n", attr ); ret = 0; diff --git a/include/ntuser.h b/include/ntuser.h index 3d43eb476e4..8da69cc1e76 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -453,6 +453,7 @@ struct draw_scroll_bar_params /* NtUserUpdateInputContext param, not compatible with Window */ enum input_context_attr { + NtUserInputContextBuiltinUI = -1, NtUserInputContextClientPtr, NtUserInputContextThreadId, };
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 3 +++ dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/ime.c | 9 --------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/x11drv_dll.h | 1 - dlls/winex11.drv/xim.c | 16 ++++++++++++---- include/ntuser.h | 3 +++ 8 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 3c4550c3cd9..35edcfe7f46 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -291,6 +291,9 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP FIXME( "hwnd %p, himc %p, msg %s, wparam %s, lparam %#Ix stub!\n", hwnd, himc, debugstr_wm_ime(msg), debugstr_imc(wparam), lparam ); return 1; + + case WM_WINE_IME_SET_OPEN_STATUS: + return ImmSetOpenStatus( himc, wparam ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index 8a957494ce9..eccfd223ac3 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -61,6 +61,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_IME_REQUEST: return "WM_IME_REQUEST"; case WM_IME_KEYDOWN: return "WM_IME_KEYDOWN"; case WM_IME_KEYUP: return "WM_IME_KEYUP"; + case WM_WINE_IME_SET_OPEN_STATUS: return "WM_WINE_IME_SET_OPEN_STATUS"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 500a4a6bc44..54093d36b6e 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -33,7 +33,6 @@ static const callback_func callback_funcs[] = x11drv_ime_get_cursor_pos, x11drv_ime_set_composition_status, x11drv_ime_set_cursor_pos, - x11drv_ime_set_open_status, x11drv_ime_update_association, };
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index 55485bfbfcf..72ada45f774 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -755,15 +755,6 @@ BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp,
/* Interfaces to XIM and other parts of winex11drv */
-NTSTATUS x11drv_ime_set_open_status( UINT open ) -{ - HIMC imc; - - imc = RealIMC(FROM_X11); - ImmSetOpenStatus(imc, open); - return 0; -} - NTSTATUS x11drv_ime_set_composition_status( UINT open ) { HIMC imc; diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index 7dc1d9f0ca7..ed5dbac6535 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -99,7 +99,6 @@ enum client_callback client_ime_get_cursor_pos, client_ime_set_composition_status, client_ime_set_cursor_pos, - client_ime_set_open_status, client_ime_update_association, client_funcs_count }; diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index 047bb430d39..80fe9ab2a3d 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -39,7 +39,6 @@ extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_get_cursor_pos( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_composition_status( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_ime_set_open_status( UINT open ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN;
extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index b7f5f696ba5..db5a3a5a74b 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -72,6 +72,14 @@ static const char *debugstr_xim_style( XIMStyle style ) return wine_dbg_sprintf( "%s", buffer ); }
+/* return the builtin IME UI window associated with a window */ +static HWND get_builtin_ime_ui( HWND hwnd ) +{ + HIMC himc; + if (!(himc = NtUserGetWindowInputContext( hwnd ))) return 0; + return (HWND)NtUserQueryInputContext( himc, NtUserInputContextBuiltinUI ); +} + static void X11DRV_ImmSetInternalString(UINT offset, UINT selLength, LPWSTR lpComp, UINT len) { /* Composition strings are edited in chunks */ @@ -131,12 +139,12 @@ static BOOL xic_preedit_state_notify( XIC xic, XPointer user, XPointer arg ) switch (state) { case XIMPreeditEnable: - x11drv_client_call( client_ime_set_open_status, TRUE ); + if (!(hwnd = get_builtin_ime_ui( hwnd ))) WARN( "No builtin IME UI, ignoring event.\n" ); + else send_message( hwnd, WM_WINE_IME_SET_OPEN_STATUS, TRUE, 0 ); break; case XIMPreeditDisable: - x11drv_client_call( client_ime_set_open_status, FALSE ); - break; - default: + if (!(hwnd = get_builtin_ime_ui( hwnd ))) WARN( "No builtin IME UI, ignoring event.\n" ); + else send_message( hwnd, WM_WINE_IME_SET_OPEN_STATUS, FALSE, 0 ); break; }
diff --git a/include/ntuser.h b/include/ntuser.h index 8da69cc1e76..7038ad86d98 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -491,6 +491,9 @@ enum wine_internal_message #define IME_INTERNAL_HKL_ACTIVATE 0x19 #define IME_INTERNAL_HKL_DEACTIVATE 0x20
+/* builtin IME UI messages */ +#define WM_WINE_IME_SET_OPEN_STATUS (WM_USER + 0) + /* internal IME private */ typedef struct ime_private {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 21 +++++++++++++++++++++ dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/ime.c | 20 -------------------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/x11drv_dll.h | 1 - dlls/winex11.drv/xim.c | 7 ++++++- include/ntuser.h | 1 + 8 files changed, 29 insertions(+), 24 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 35edcfe7f46..86834546a58 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -242,6 +242,25 @@ static void ime_ui_start_composition( HIMC himc, HWND hwnd ) ImmUnlockIMC( himc ); }
+static UINT ime_get_cursor_pos( HIMC himc ) +{ + COMPOSITIONSTRING *string; + INPUTCONTEXT *ctx; + UINT pos = 0; + + TRACE( "himc %p\n", himc ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + if ((string = ImmLockIMCC( ctx->hCompStr ))) + { + pos = string->dwCursorPos; + ImmUnlockIMCC( ctx->hCompStr ); + } + ImmUnlockIMC( himc ); + + return pos; +} + static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); @@ -294,6 +313,8 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP
case WM_WINE_IME_SET_OPEN_STATUS: return ImmSetOpenStatus( himc, wparam ); + case WM_WINE_IME_GET_CURSOR_POS: + return ime_get_cursor_pos( himc ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index eccfd223ac3..4a3afce09ba 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -62,6 +62,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_IME_KEYDOWN: return "WM_IME_KEYDOWN"; case WM_IME_KEYUP: return "WM_IME_KEYUP"; case WM_WINE_IME_SET_OPEN_STATUS: return "WM_WINE_IME_SET_OPEN_STATUS"; + case WM_WINE_IME_GET_CURSOR_POS: return "WM_WINE_IME_GET_CURSOR_POS"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 54093d36b6e..a3375e60957 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -30,7 +30,6 @@ static const callback_func callback_funcs[] = { x11drv_dnd_drop_event, x11drv_dnd_leave_event, - x11drv_ime_get_cursor_pos, x11drv_ime_set_composition_status, x11drv_ime_set_cursor_pos, x11drv_ime_update_association, diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index 72ada45f774..b92c13ff08a 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -786,26 +786,6 @@ NTSTATUS x11drv_ime_set_composition_status( UINT open ) return 0; }
-NTSTATUS x11drv_ime_get_cursor_pos( UINT arg ) -{ - LPINPUTCONTEXT lpIMC; - INT rc = 0; - LPCOMPOSITIONSTRING compstr; - - if (!hSelectedFrom) - return rc; - - lpIMC = LockRealIMC(FROM_X11); - if (lpIMC) - { - compstr = ImmLockIMCC(lpIMC->hCompStr); - rc = compstr->dwCursorPos; - ImmUnlockIMCC(lpIMC->hCompStr); - } - UnlockRealIMC(FROM_X11); - return rc; -} - NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) { LPINPUTCONTEXT lpIMC; diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index ed5dbac6535..332c4e4b3fa 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -96,7 +96,6 @@ enum client_callback { client_dnd_drop_event, client_dnd_leave_event, - client_ime_get_cursor_pos, client_ime_set_composition_status, client_ime_set_cursor_pos, client_ime_update_association, diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index 80fe9ab2a3d..2cc27abd362 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -36,7 +36,6 @@ extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) D
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_ime_get_cursor_pos( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_composition_status( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index db5a3a5a74b..072cf49457a 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -230,8 +230,13 @@ static int xic_preedit_caret( XIC xic, XPointer user, XPointer arg ) TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
if (!params) return 0; + if (!(hwnd = get_builtin_ime_ui( hwnd ))) + { + WARN( "No builtin IME UI, ignoring event.\n" ); + return 0; + }
- pos = x11drv_client_call( client_ime_get_cursor_pos, 0 ); + pos = send_message( hwnd, WM_WINE_IME_GET_CURSOR_POS, 0, 0 ); switch (params->direction) { case XIMForwardChar: diff --git a/include/ntuser.h b/include/ntuser.h index 7038ad86d98..fed74155c4a 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -493,6 +493,7 @@ enum wine_internal_message
/* builtin IME UI messages */ #define WM_WINE_IME_SET_OPEN_STATUS (WM_USER + 0) +#define WM_WINE_IME_GET_CURSOR_POS (WM_USER + 1)
/* internal IME private */ typedef struct ime_private
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 40 +++++++++++++++++++++++++++++++++++ dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/ime.c | 26 ----------------------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/x11drv_dll.h | 1 - dlls/winex11.drv/xim.c | 10 +++++++-- include/ntuser.h | 1 + 8 files changed, 50 insertions(+), 31 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 86834546a58..dcea00c788b 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -93,6 +93,25 @@ static HFONT input_context_select_ui_font( INPUTCONTEXT *ctx, HDC hdc ) return font; }
+static void ime_send_message( HIMC himc, UINT msg, WPARAM wparam, LPARAM lparam ) +{ + TRANSMSG *messages = NULL, message = {.message = msg, .wParam = wparam, .lParam = lparam}; + INPUTCONTEXT *ctx; + HIMCC tmp; + + TRACE( "himc %p, msg %#x, wparam %#Ix, lparam %#Ix\n", himc, msg, wparam, lparam ); + + if (!(ctx = ImmLockIMC( himc ))) return; + if (!(tmp = ImmReSizeIMCC( ctx->hMsgBuf, (ctx->dwNumMsgBuf + 1) * sizeof(message) ))) goto done; + if (!(messages = ImmLockIMCC( (ctx->hMsgBuf = tmp) ))) goto done; + messages[ctx->dwNumMsgBuf++] = message; + ImmUnlockIMCC( ctx->hMsgBuf ); + +done: + ImmUnlockIMC( himc ); + if (!messages || !ImmGenerateMessage( himc )) WARN( "Failed to generate himc %p messages, error %lu\n", himc, GetLastError() ); +} + static void ime_ui_paint( HIMC himc, HWND hwnd ) { PAINTSTRUCT ps; @@ -261,6 +280,25 @@ static UINT ime_get_cursor_pos( HIMC himc ) return pos; }
+static UINT ime_set_cursor_pos( HIMC himc, UINT new_pos ) +{ + COMPOSITIONSTRING *string; + INPUTCONTEXT *ctx; + + TRACE( "himc %p, new_pos %u\n", himc, new_pos ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + if ((string = ImmLockIMCC( ctx->hCompStr ))) + { + string->dwCursorPos = new_pos; + ImmUnlockIMCC( ctx->hCompStr ); + } + ImmUnlockIMC( himc ); + + ime_send_message( himc, WM_IME_COMPOSITION, new_pos, GCS_CURSORPOS ); + return 0; +} + static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); @@ -315,6 +353,8 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP return ImmSetOpenStatus( himc, wparam ); case WM_WINE_IME_GET_CURSOR_POS: return ime_get_cursor_pos( himc ); + case WM_WINE_IME_SET_CURSOR_POS: + return ime_set_cursor_pos( himc, wparam ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index 4a3afce09ba..b10d04d77ff 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -63,6 +63,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_IME_KEYUP: return "WM_IME_KEYUP"; case WM_WINE_IME_SET_OPEN_STATUS: return "WM_WINE_IME_SET_OPEN_STATUS"; case WM_WINE_IME_GET_CURSOR_POS: return "WM_WINE_IME_GET_CURSOR_POS"; + case WM_WINE_IME_SET_CURSOR_POS: return "WM_WINE_IME_SET_CURSOR_POS"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index a3375e60957..71fddfe4449 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -31,7 +31,6 @@ static const callback_func callback_funcs[] = x11drv_dnd_drop_event, x11drv_dnd_leave_event, x11drv_ime_set_composition_status, - x11drv_ime_set_cursor_pos, x11drv_ime_update_association, };
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index b92c13ff08a..cbf9c488f3a 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -786,32 +786,6 @@ NTSTATUS x11drv_ime_set_composition_status( UINT open ) return 0; }
-NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) -{ - LPINPUTCONTEXT lpIMC; - LPCOMPOSITIONSTRING compstr; - - if (!hSelectedFrom) - return 0; - - lpIMC = LockRealIMC(FROM_X11); - if (!lpIMC) - return 0; - - compstr = ImmLockIMCC(lpIMC->hCompStr); - if (!compstr) - { - UnlockRealIMC(FROM_X11); - return 0; - } - - compstr->dwCursorPos = pos; - ImmUnlockIMCC(lpIMC->hCompStr); - UnlockRealIMC(FROM_X11); - GenerateIMEMessage(FROM_X11, WM_IME_COMPOSITION, pos, GCS_CURSORPOS); - return 0; -} - NTSTATUS x11drv_ime_update_association( UINT arg ) { HWND focus = UlongToHandle( arg ); diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index 332c4e4b3fa..e48a2c61669 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -97,7 +97,6 @@ enum client_callback client_dnd_drop_event, client_dnd_leave_event, client_ime_set_composition_status, - client_ime_set_cursor_pos, client_ime_update_association, client_funcs_count }; diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index 2cc27abd362..5180969eeb7 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -37,7 +37,6 @@ extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) D extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_set_composition_status( UINT arg ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_ime_set_cursor_pos( UINT pos ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN;
extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 072cf49457a..af9846661af 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -187,6 +187,11 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
if (!params) return 0; + if (!(hwnd = get_builtin_ime_ui( hwnd ))) + { + WARN( "No builtin IME UI, ignoring event.\n" ); + return 0; + }
if (!(text = params->text)) X11DRV_ImmSetInternalString( params->chg_first, params->chg_length, NULL, 0 ); @@ -216,7 +221,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) if (str != text->string.multi_byte) free( str ); }
- x11drv_client_call( client_ime_set_cursor_pos, params->caret ); + send_message( hwnd, WM_WINE_IME_SET_CURSOR_POS, params->caret, 0 );
return 0; } @@ -264,7 +269,8 @@ static int xic_preedit_caret( XIC xic, XPointer user, XPointer arg ) FIXME( "Not implemented\n" ); break; } - x11drv_client_call( client_ime_set_cursor_pos, pos ); + + send_message( hwnd, WM_WINE_IME_SET_CURSOR_POS, pos, 0 ); params->position = pos;
return 0; diff --git a/include/ntuser.h b/include/ntuser.h index fed74155c4a..e7ebf786e25 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -494,6 +494,7 @@ enum wine_internal_message /* builtin IME UI messages */ #define WM_WINE_IME_SET_OPEN_STATUS (WM_USER + 0) #define WM_WINE_IME_GET_CURSOR_POS (WM_USER + 1) +#define WM_WINE_IME_SET_CURSOR_POS (WM_USER + 2)
/* internal IME private */ typedef struct ime_private
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index dcea00c788b..77c485a2e83 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -284,19 +284,21 @@ static UINT ime_set_cursor_pos( HIMC himc, UINT new_pos ) { COMPOSITIONSTRING *string; INPUTCONTEXT *ctx; + UINT pos = 0;
TRACE( "himc %p, new_pos %u\n", himc, new_pos );
if (!(ctx = ImmLockIMC( himc ))) return 0; if ((string = ImmLockIMCC( ctx->hCompStr ))) { + pos = string->dwCursorPos; string->dwCursorPos = new_pos; ImmUnlockIMCC( ctx->hCompStr ); } ImmUnlockIMC( himc );
- ime_send_message( himc, WM_IME_COMPOSITION, new_pos, GCS_CURSORPOS ); - return 0; + if (pos != new_pos) ime_send_message( himc, WM_IME_COMPOSITION, new_pos, GCS_CURSORPOS ); + return pos; }
static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 70 +++++++++++++++++++++++++++++++++++ dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 1 - dlls/winex11.drv/ime.c | 31 ---------------- dlls/winex11.drv/unixlib.h | 1 - dlls/winex11.drv/x11drv_dll.h | 1 - dlls/winex11.drv/xim.c | 10 ++++- include/ntuser.h | 1 + 8 files changed, 80 insertions(+), 36 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 77c485a2e83..77a5be5a97c 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -83,6 +83,45 @@ static WCHAR *input_context_get_comp_str( INPUTCONTEXT *ctx, BOOL result, UINT * return text; }
+static DWORD input_context_set_comp_str( INPUTCONTEXT *ctx, BOOL result, const WCHAR *str, SIZE_T len ) +{ + UINT new_size = sizeof(COMPOSITIONSTRING); + COMPOSITIONSTRING old, *string; + HIMCC tmp; + + TRACE( "ctx %p, result %u, str %s\n", ctx, result, debugstr_wn(str, len) ); + + new_size += len * sizeof(WCHAR); + if (len) new_size += 2 * sizeof(DWORD); + if (!result) new_size += len; + + if (!(string = ImmLockIMCC( ctx->hCompStr ))) goto error; + old = *string; + ImmUnlockIMCC( ctx->hCompStr ); + + if (new_size > old.dwSize) + { + if (!(tmp = ImmReSizeIMCC( ctx->hCompStr, new_size ))) goto error; + ctx->hCompStr = tmp; + } + + if (!(string = ImmLockIMCC( ctx->hCompStr ))) goto error; + memset( string, 0, sizeof(COMPOSITIONSTRING) ); + string->dwSize = sizeof(COMPOSITIONSTRING); + ImmUnlockIMCC( ctx->hCompStr ); + + if (new_size < old.dwSize) + { + if (!(tmp = ImmReSizeIMCC( ctx->hCompStr, new_size ))) goto error; + ctx->hCompStr = tmp; + } + return 0; + +error: + WARN( "Failed to update result string, error %lu\n", GetLastError() ); + return 0; +} + static HFONT input_context_select_ui_font( INPUTCONTEXT *ctx, HDC hdc ) { struct ime_private *priv; @@ -301,6 +340,35 @@ static UINT ime_set_cursor_pos( HIMC himc, UINT new_pos ) return pos; }
+static BOOL ime_set_composition_status( HIMC himc, HWND hwnd, BOOL new_status ) +{ + struct ime_private *priv; + BOOL old_status = FALSE; + INPUTCONTEXT *ctx; + + TRACE( "himc %p, hwnd %p, new_status %u\n", himc, hwnd, new_status ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + if ((priv = ImmLockIMCC( ctx->hPrivate ))) + { + old_status = priv->bInComposition; + priv->bInComposition = new_status; + ImmUnlockIMCC( ctx->hPrivate ); + } + if (new_status != old_status) input_context_set_comp_str( ctx, TRUE, NULL, 0 ); + ImmUnlockIMC( himc ); + + if (old_status < new_status) + ime_send_message( himc, WM_IME_STARTCOMPOSITION, 0, 0 ); + else if (old_status > new_status) + { + ShowWindow( hwnd, SW_HIDE ); + ime_send_message( himc, WM_IME_ENDCOMPOSITION, 0, 0 ); + } + + return old_status; +} + static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); @@ -357,6 +425,8 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP return ime_get_cursor_pos( himc ); case WM_WINE_IME_SET_CURSOR_POS: return ime_set_cursor_pos( himc, wparam ); + case WM_WINE_IME_SET_COMP_STATUS: + return ime_set_composition_status( himc, hwnd, wparam ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index b10d04d77ff..876d92d4aa2 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -64,6 +64,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_WINE_IME_SET_OPEN_STATUS: return "WM_WINE_IME_SET_OPEN_STATUS"; case WM_WINE_IME_GET_CURSOR_POS: return "WM_WINE_IME_GET_CURSOR_POS"; case WM_WINE_IME_SET_CURSOR_POS: return "WM_WINE_IME_SET_CURSOR_POS"; + case WM_WINE_IME_SET_COMP_STATUS: return "WM_WINE_IME_SET_COMP_STATUS"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 71fddfe4449..8445c21470e 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -30,7 +30,6 @@ static const callback_func callback_funcs[] = { x11drv_dnd_drop_event, x11drv_dnd_leave_event, - x11drv_ime_set_composition_status, x11drv_ime_update_association, };
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index cbf9c488f3a..09440140568 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -755,37 +755,6 @@ BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp,
/* Interfaces to XIM and other parts of winex11drv */
-NTSTATUS x11drv_ime_set_composition_status( UINT open ) -{ - HIMC imc; - LPINPUTCONTEXT lpIMC; - LPIMEPRIVATE myPrivate; - - imc = RealIMC(FROM_X11); - lpIMC = ImmLockIMC(imc); - if (lpIMC == NULL) - return 0; - - myPrivate = ImmLockIMCC(lpIMC->hPrivate); - - if (open && !myPrivate->bInComposition) - { - GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0); - } - else if (!open && myPrivate->bInComposition) - { - ShowWindow(myPrivate->hwndDefault, SW_HIDE); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = ImeCreateBlankCompStr(); - GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0); - } - myPrivate->bInComposition = open; - - ImmUnlockIMCC(lpIMC->hPrivate); - ImmUnlockIMC(imc); - return 0; -} - NTSTATUS x11drv_ime_update_association( UINT arg ) { HWND focus = UlongToHandle( arg ); diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index e48a2c61669..484ed4e5725 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -96,7 +96,6 @@ enum client_callback { client_dnd_drop_event, client_dnd_leave_event, - client_ime_set_composition_status, client_ime_update_association, client_funcs_count }; diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index 5180969eeb7..a96e286ae83 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -36,7 +36,6 @@ extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) D
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_dnd_leave_event( UINT arg ) DECLSPEC_HIDDEN; -extern NTSTATUS x11drv_ime_set_composition_status( UINT arg ) DECLSPEC_HIDDEN; extern NTSTATUS x11drv_ime_update_association( UINT arg ) DECLSPEC_HIDDEN;
extern LRESULT WINAPI foreign_window_proc( HWND hwnd, UINT msg, WPARAM wparam, diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index af9846661af..327ab6b5ce2 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -157,8 +157,11 @@ static int xic_preedit_start( XIC xic, XPointer user, XPointer arg )
TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
- x11drv_client_call( client_ime_set_composition_status, TRUE ); ximInComposeMode = TRUE; + + if (!(hwnd = get_builtin_ime_ui( hwnd ))) WARN( "No builtin IME UI, ignoring event.\n" ); + else send_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, TRUE, 0 ); + return -1; }
@@ -174,7 +177,10 @@ static int xic_preedit_done( XIC xic, XPointer user, XPointer arg ) dwCompStringSize = 0; dwCompStringLength = 0; CompositionString = NULL; - x11drv_client_call( client_ime_set_composition_status, FALSE ); + + if (!(hwnd = get_builtin_ime_ui( hwnd ))) WARN( "No builtin IME UI, ignoring event.\n" ); + else send_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, FALSE, 0 ); + return 0; }
diff --git a/include/ntuser.h b/include/ntuser.h index e7ebf786e25..e00bfaee44b 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -495,6 +495,7 @@ enum wine_internal_message #define WM_WINE_IME_SET_OPEN_STATUS (WM_USER + 0) #define WM_WINE_IME_GET_CURSOR_POS (WM_USER + 1) #define WM_WINE_IME_SET_CURSOR_POS (WM_USER + 2) +#define WM_WINE_IME_SET_COMP_STATUS (WM_USER + 3)
/* internal IME private */ typedef struct ime_private
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/xim.c | 54 ++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 31 deletions(-)
diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 327ab6b5ce2..eedfdd06eac 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -44,10 +44,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(xim);
BOOL ximInComposeMode=FALSE;
-/* moved here from imm32 for dll separation */ -static DWORD dwCompStringLength = 0; -static LPBYTE CompositionString = NULL; -static DWORD dwCompStringSize = 0; +static DWORD preedit_len = 0; +static DWORD preedit_max = 0; +static WCHAR *preedit_buf = NULL;
static XIMStyle input_style = 0; static XIMStyle input_style_req = XIMPreeditCallbacks | XIMStatusCallbacks; @@ -80,38 +79,32 @@ static HWND get_builtin_ime_ui( HWND hwnd ) return (HWND)NtUserQueryInputContext( himc, NtUserInputContextBuiltinUI ); }
-static void X11DRV_ImmSetInternalString(UINT offset, UINT selLength, LPWSTR lpComp, UINT len) +static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, UINT new_len ) { - /* Composition strings are edited in chunks */ - unsigned int byte_length = len * sizeof(WCHAR); - unsigned int byte_offset = offset * sizeof(WCHAR); - unsigned int byte_selection = selLength * sizeof(WCHAR); - int byte_expansion = byte_length - byte_selection; - LPBYTE ptr_new; + int diff = new_len - old_len;
- TRACE("( %i, %i, %p, %d):\n", offset, selLength, lpComp, len ); + TRACE( "offset %u, old_len %u, text %s\n", offset, old_len, debugstr_wn(text, new_len) );
- if (byte_expansion + dwCompStringLength >= dwCompStringSize) + if (preedit_len + diff >= preedit_max) { - ptr_new = realloc( CompositionString, dwCompStringSize + byte_expansion ); - if (ptr_new == NULL) + WCHAR *tmp; + + if (!(tmp = realloc( preedit_buf, (preedit_max + diff) * sizeof(WCHAR) ))) { ERR("Couldn't expand composition string buffer\n"); return; }
- CompositionString = ptr_new; - dwCompStringSize += byte_expansion; + preedit_buf = tmp; + preedit_max += diff; }
- ptr_new = CompositionString + byte_offset; - memmove(ptr_new + byte_length, ptr_new + byte_selection, - dwCompStringLength - byte_offset - byte_selection); - if (lpComp) memcpy(ptr_new, lpComp, byte_length); - dwCompStringLength += byte_expansion; + memmove( preedit_buf + offset + new_len, preedit_buf + offset + old_len, + (preedit_len - offset - old_len) * sizeof(WCHAR) ); + if (text) memcpy( preedit_buf + offset, text, new_len * sizeof(WCHAR) ); + preedit_len += diff;
- x11drv_client_func( client_func_ime_set_composition_string, - CompositionString, dwCompStringLength ); + x11drv_client_func( client_func_ime_set_composition_string, preedit_buf, preedit_len * sizeof(WCHAR) ); }
void X11DRV_XIMLookupChars( const char *str, UINT count ) @@ -172,11 +165,10 @@ static int xic_preedit_done( XIC xic, XPointer user, XPointer arg ) TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
ximInComposeMode = FALSE; - if (dwCompStringSize) - free( CompositionString ); - dwCompStringSize = 0; - dwCompStringLength = 0; - CompositionString = NULL; + free( preedit_buf ); + preedit_max = 0; + preedit_len = 0; + preedit_buf = NULL;
if (!(hwnd = get_builtin_ime_ui( hwnd ))) WARN( "No builtin IME UI, ignoring event.\n" ); else send_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, FALSE, 0 ); @@ -200,7 +192,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) }
if (!(text = params->text)) - X11DRV_ImmSetInternalString( params->chg_first, params->chg_length, NULL, 0 ); + xim_update_preedit_string( params->chg_first, params->chg_length, NULL, 0 ); else { size_t text_len; @@ -220,7 +212,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) if ((output = malloc( text_len * sizeof(WCHAR) ))) { text_len = ntdll_umbstowcs( str, text_len, output, text_len ); - X11DRV_ImmSetInternalString( params->chg_first, params->chg_length, output, text_len ); + xim_update_preedit_string( params->chg_first, params->chg_length, output, text_len ); free( output ); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/xim.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index eedfdd06eac..cba737c333f 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -85,11 +85,11 @@ static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, U
TRACE( "offset %u, old_len %u, text %s\n", offset, old_len, debugstr_wn(text, new_len) );
- if (preedit_len + diff >= preedit_max) + if (!preedit_buf || preedit_len + diff >= preedit_max) { WCHAR *tmp;
- if (!(tmp = realloc( preedit_buf, (preedit_max + diff) * sizeof(WCHAR) ))) + if (!(tmp = realloc( preedit_buf, (preedit_max + diff + 1) * sizeof(WCHAR) ))) { ERR("Couldn't expand composition string buffer\n"); return; @@ -103,6 +103,7 @@ static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, U (preedit_len - offset - old_len) * sizeof(WCHAR) ); if (text) memcpy( preedit_buf + offset, text, new_len * sizeof(WCHAR) ); preedit_len += diff; + preedit_buf[preedit_len] = 0;
x11drv_client_func( client_func_ime_set_composition_string, preedit_buf, preedit_len * sizeof(WCHAR) ); } @@ -114,8 +115,9 @@ void X11DRV_XIMLookupChars( const char *str, UINT count )
TRACE("%p %u\n", str, count);
- if (!(output = malloc( count * sizeof(WCHAR) ))) return; + if (!(output = malloc( (count + 1) * sizeof(WCHAR) ))) return; len = ntdll_umbstowcs( str, count, output, count ); + output[len] = 0;
x11drv_client_func( client_func_ime_set_result, output, len * sizeof(WCHAR) ); free( output );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 70 ++++++++++++++++++++++++++++++++++- dlls/imm32/imm_private.h | 1 + dlls/winex11.drv/dllmain.c | 2 - dlls/winex11.drv/event.c | 4 +- dlls/winex11.drv/ime.c | 54 --------------------------- dlls/winex11.drv/keyboard.c | 2 +- dlls/winex11.drv/unixlib.h | 2 - dlls/winex11.drv/x11drv.h | 3 +- dlls/winex11.drv/x11drv_dll.h | 2 - dlls/winex11.drv/xim.c | 39 +++++++++++++------ include/ntuser.h | 1 + 11 files changed, 103 insertions(+), 77 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 77a5be5a97c..49a7e4338d8 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -85,9 +85,11 @@ static WCHAR *input_context_get_comp_str( INPUTCONTEXT *ctx, BOOL result, UINT *
static DWORD input_context_set_comp_str( INPUTCONTEXT *ctx, BOOL result, const WCHAR *str, SIZE_T len ) { + DWORD flags = result ? GCS_RESULTSTR : GCS_COMPSTR; UINT new_size = sizeof(COMPOSITIONSTRING); COMPOSITIONSTRING old, *string; HIMCC tmp; + BYTE *dst;
TRACE( "ctx %p, result %u, str %s\n", ctx, result, debugstr_wn(str, len) );
@@ -108,6 +110,54 @@ static DWORD input_context_set_comp_str( INPUTCONTEXT *ctx, BOOL result, const W if (!(string = ImmLockIMCC( ctx->hCompStr ))) goto error; memset( string, 0, sizeof(COMPOSITIONSTRING) ); string->dwSize = sizeof(COMPOSITIONSTRING); + + if (!result && len) + { + string->dwCursorPos = min( len, old.dwCursorPos ); + + string->dwCompStrLen = len; + string->dwCompStrOffset = string->dwSize; + dst = (BYTE *)string + string->dwCompStrOffset; + memcpy( dst, str, len * sizeof(WCHAR) ); + string->dwSize += len * sizeof(WCHAR); + + string->dwCompClauseLen = 2 * sizeof(DWORD); + string->dwCompClauseOffset = string->dwSize; + dst = (BYTE *)string + string->dwCompClauseOffset; + *(DWORD *)(dst + 0 * sizeof(DWORD)) = 0; + *(DWORD *)(dst + 1 * sizeof(DWORD)) = len; + string->dwSize += 2 * sizeof(DWORD); + + string->dwCompAttrLen = len; + string->dwCompAttrOffset = string->dwSize; + dst = (BYTE *)string + string->dwCompAttrOffset; + memset( dst, ATTR_INPUT, len ); + string->dwSize += len; + } + else if (len) + { + string->dwResultStrLen = len; + string->dwResultStrOffset = string->dwSize; + dst = (BYTE *)string + string->dwResultStrOffset; + memcpy( dst, str, len * sizeof(WCHAR) ); + string->dwSize += len * sizeof(WCHAR); + + string->dwResultClauseLen = 2 * sizeof(DWORD); + string->dwResultClauseOffset = string->dwSize; + dst = (BYTE *)string + string->dwResultClauseOffset; + *(DWORD *)(dst + 0 * sizeof(DWORD)) = 0; + *(DWORD *)(dst + 1 * sizeof(DWORD)) = len; + string->dwSize += 2 * sizeof(DWORD); + } + + if (string->dwCursorPos != old.dwCursorPos) flags |= GCS_CURSORPOS; + if (string->dwDeltaStart != old.dwDeltaStart) flags |= GCS_DELTASTART; + if (string->dwCompStrLen != old.dwCompStrLen) flags |= GCS_COMPSTR; + if (string->dwCompAttrLen != old.dwCompAttrLen) flags |= GCS_COMPATTR; + if (string->dwCompClauseLen != old.dwCompClauseLen) flags |= GCS_COMPCLAUSE; + if (string->dwResultStrLen != old.dwResultStrLen) flags |= GCS_RESULTSTR; + if (string->dwResultClauseLen != old.dwResultClauseLen) flags |= GCS_RESULTCLAUSE; + ImmUnlockIMCC( ctx->hCompStr );
if (new_size < old.dwSize) @@ -115,7 +165,7 @@ static DWORD input_context_set_comp_str( INPUTCONTEXT *ctx, BOOL result, const W if (!(tmp = ImmReSizeIMCC( ctx->hCompStr, new_size ))) goto error; ctx->hCompStr = tmp; } - return 0; + return flags;
error: WARN( "Failed to update result string, error %lu\n", GetLastError() ); @@ -369,6 +419,21 @@ static BOOL ime_set_composition_status( HIMC himc, HWND hwnd, BOOL new_status ) return old_status; }
+static BOOL ime_set_composition_text( HIMC himc, BOOL result, const WCHAR *str, UINT len ) +{ + INPUTCONTEXT *ctx; + DWORD flags; + + TRACE( "himc %p, result %u, str %s\n", himc, result, debugstr_wn(str, len) ); + + if (!(ctx = ImmLockIMC( himc ))) return FALSE; + flags = input_context_set_comp_str( ctx, result, str, len ); + ImmUnlockIMC( himc ); + + ime_send_message( himc, WM_IME_COMPOSITION, len ? str[0] : 0, flags ); + return TRUE; +} + static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); @@ -427,6 +492,9 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP return ime_set_cursor_pos( himc, wparam ); case WM_WINE_IME_SET_COMP_STATUS: return ime_set_composition_status( himc, hwnd, wparam ); + case WM_WINE_IME_SET_COMP_TEXT: + return ime_set_composition_text( himc, !wparam, (const WCHAR *)lparam, + wcslen( (const WCHAR *)lparam ) ); }
return DefWindowProcW( hwnd, msg, wparam, lparam ); diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index 876d92d4aa2..8ea40e1fb27 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -65,6 +65,7 @@ static const char *debugstr_wm_ime( UINT msg ) case WM_WINE_IME_GET_CURSOR_POS: return "WM_WINE_IME_GET_CURSOR_POS"; case WM_WINE_IME_SET_CURSOR_POS: return "WM_WINE_IME_SET_CURSOR_POS"; case WM_WINE_IME_SET_COMP_STATUS: return "WM_WINE_IME_SET_COMP_STATUS"; + case WM_WINE_IME_SET_COMP_TEXT: return "WM_WINE_IME_SET_COMP_TEXT"; default: if (msg == WM_MSIME_SERVICE) return "WM_MSIME_SERVICE"; else if (msg == WM_MSIME_RECONVERTOPTIONS) return "WM_MSIME_RECONVERTOPTIONS"; diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index 8445c21470e..7c463d4e401 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -48,8 +48,6 @@ static const kernel_callback kernel_callbacks[] = x11drv_dnd_enter_event, x11drv_dnd_position_event, x11drv_dnd_post_drop, - x11drv_ime_set_composition_string, - x11drv_ime_set_result, x11drv_systray_change_owner, };
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 1ae39eb9edf..4ec37185751 100644 --- a/dlls/winex11.drv/event.c +++ b/dlls/winex11.drv/event.c @@ -49,8 +49,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(event); WINE_DECLARE_DEBUG_CHANNEL(xdnd);
-extern BOOL ximInComposeMode; - #define DndNotDnd -1 /* OffiX drag&drop */ #define DndUnknown 0 #define DndRawData 1 @@ -810,7 +808,7 @@ static void focus_out( Display *display , HWND hwnd ) int revert; XIC xic;
- if (ximInComposeMode) return; + if (xim_in_compose_mode) return;
x11drv_thread_data()->last_focus = hwnd; if ((xic = X11DRV_get_ic( hwnd ))) XUnsetICFocus( xic ); diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index 09440140568..a69ad81eff5 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -765,57 +765,3 @@ NTSTATUS x11drv_ime_update_association( UINT arg ) ImmAssociateContext(focus,RealIMC(FROM_X11)); return 0; } - - -NTSTATUS WINAPI x11drv_ime_set_composition_string( void *param, ULONG size ) -{ - return ImeSetCompositionString(FROM_X11, SCS_SETSTR, param, size, NULL, 0); -} - -NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG len ) -{ - WCHAR *lpResult = params; - HIMC imc; - LPINPUTCONTEXT lpIMC; - HIMCC newCompStr; - LPIMEPRIVATE myPrivate; - BOOL inComp; - HWND focus; - - len /= sizeof(WCHAR); - if ((focus = GetFocus())) - x11drv_ime_update_association( HandleToUlong( focus )); - - imc = RealIMC(FROM_X11); - lpIMC = ImmLockIMC(imc); - if (lpIMC == NULL) - return 0; - - newCompStr = updateCompStr(lpIMC->hCompStr, NULL, 0); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; - - newCompStr = updateResultStr(lpIMC->hCompStr, lpResult, len); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = newCompStr; - - myPrivate = ImmLockIMCC(lpIMC->hPrivate); - inComp = myPrivate->bInComposition; - ImmUnlockIMCC(lpIMC->hPrivate); - - if (!inComp) - { - ImmSetOpenStatus(imc, TRUE); - GenerateIMEMessage(imc, WM_IME_STARTCOMPOSITION, 0, 0); - } - - GenerateIMEMessage(imc, WM_IME_COMPOSITION, 0, GCS_COMPSTR); - GenerateIMEMessage(imc, WM_IME_COMPOSITION, lpResult[0], GCS_RESULTSTR|GCS_RESULTCLAUSE); - GenerateIMEMessage(imc, WM_IME_ENDCOMPOSITION, 0, 0); - - if (!inComp) - ImmSetOpenStatus(imc, FALSE); - - ImmUnlockIMC(imc); - return 0; -} diff --git a/dlls/winex11.drv/keyboard.c b/dlls/winex11.drv/keyboard.c index b1c47d5258e..195cc65eddb 100644 --- a/dlls/winex11.drv/keyboard.c +++ b/dlls/winex11.drv/keyboard.c @@ -1347,7 +1347,7 @@ BOOL X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
if (status == XLookupChars) { - X11DRV_XIMLookupChars( Str, ascii_chars ); + xim_set_result_string( hwnd, Str, ascii_chars ); if (buf != Str) free( Str ); return TRUE; diff --git a/dlls/winex11.drv/unixlib.h b/dlls/winex11.drv/unixlib.h index 484ed4e5725..de044a9416c 100644 --- a/dlls/winex11.drv/unixlib.h +++ b/dlls/winex11.drv/unixlib.h @@ -83,8 +83,6 @@ enum x11drv_client_funcs client_func_dnd_enter_event, client_func_dnd_position_event, client_func_dnd_post_drop, - client_func_ime_set_composition_string, - client_func_ime_set_result, client_func_systray_change_owner, client_func_last }; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 9efaae3465b..e007f07066a 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -453,6 +453,7 @@ extern int xrender_error_base DECLSPEC_HIDDEN; extern char *process_name DECLSPEC_HIDDEN; extern Display *clipboard_display DECLSPEC_HIDDEN; extern WNDPROC client_foreign_window_proc DECLSPEC_HIDDEN; +extern BOOL xim_in_compose_mode DECLSPEC_HIDDEN;
/* atoms */
@@ -823,7 +824,7 @@ extern struct x11drv_display_device_handler desktop_handler DECLSPEC_HIDDEN; /* XIM support */ extern BOOL xim_init( const WCHAR *input_style ) DECLSPEC_HIDDEN; extern void xim_thread_attach( struct x11drv_thread_data *data ) DECLSPEC_HIDDEN; -extern void X11DRV_XIMLookupChars( const char *str, UINT count ) DECLSPEC_HIDDEN; +extern void xim_set_result_string( HWND hwnd, const char *str, UINT count ) DECLSPEC_HIDDEN; extern XIC X11DRV_get_ic( HWND hwnd ) DECLSPEC_HIDDEN;
#define XEMBED_MAPPED (1 << 0) diff --git a/dlls/winex11.drv/x11drv_dll.h b/dlls/winex11.drv/x11drv_dll.h index a96e286ae83..fbd2a3e74b2 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -30,8 +30,6 @@ extern NTSTATUS WINAPI x11drv_dnd_enter_event( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_dnd_position_event( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_dnd_post_drop( void *data, ULONG size ) DECLSPEC_HIDDEN; -extern NTSTATUS WINAPI x11drv_ime_set_composition_string( void *params, ULONG size ) DECLSPEC_HIDDEN; -extern NTSTATUS WINAPI x11drv_ime_set_result( void *params, ULONG size ) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI x11drv_systray_change_owner( void *params, ULONG size ) DECLSPEC_HIDDEN;
extern NTSTATUS x11drv_dnd_drop_event( UINT arg ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index cba737c333f..25ddb9ea940 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -42,7 +42,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(xim); #define XICProc XIMProc #endif
-BOOL ximInComposeMode=FALSE; +BOOL xim_in_compose_mode = FALSE;
static DWORD preedit_len = 0; static DWORD preedit_max = 0; @@ -79,11 +79,11 @@ static HWND get_builtin_ime_ui( HWND hwnd ) return (HWND)NtUserQueryInputContext( himc, NtUserInputContextBuiltinUI ); }
-static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, UINT new_len ) +static void xim_update_preedit_string( HWND hwnd, UINT offset, UINT old_len, WCHAR *text, UINT new_len ) { int diff = new_len - old_len;
- TRACE( "offset %u, old_len %u, text %s\n", offset, old_len, debugstr_wn(text, new_len) ); + TRACE( "hwnd %p, offset %u, old_len %u, text %s\n", hwnd, offset, old_len, debugstr_wn(text, new_len) );
if (!preedit_buf || preedit_len + diff >= preedit_max) { @@ -105,21 +105,38 @@ static void xim_update_preedit_string( UINT offset, UINT old_len, WCHAR *text, U preedit_len += diff; preedit_buf[preedit_len] = 0;
- x11drv_client_func( client_func_ime_set_composition_string, preedit_buf, preedit_len * sizeof(WCHAR) ); + send_message( hwnd, WM_WINE_IME_SET_COMP_TEXT, TRUE, (LPARAM)preedit_buf ); }
-void X11DRV_XIMLookupChars( const char *str, UINT count ) +void xim_set_result_string( HWND hwnd, const char *str, UINT count ) { WCHAR *output; DWORD len;
- TRACE("%p %u\n", str, count); + TRACE( "hwnd %p, str %s\n", hwnd, debugstr_an(str, count) ); + + if (!(hwnd = get_builtin_ime_ui( hwnd ))) + { + WARN( "No builtin IME UI, ignoring event.\n" ); + return; + }
if (!(output = malloc( (count + 1) * sizeof(WCHAR) ))) return; len = ntdll_umbstowcs( str, count, output, count ); output[len] = 0;
- x11drv_client_func( client_func_ime_set_result, output, len * sizeof(WCHAR) ); + if (!xim_in_compose_mode) + { + send_message( hwnd, WM_WINE_IME_SET_OPEN_STATUS, TRUE, 0 ); + send_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, TRUE, 0 ); + } + send_message( hwnd, WM_WINE_IME_SET_COMP_TEXT, FALSE, (LPARAM)output ); + if (!xim_in_compose_mode) + { + send_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, FALSE, 0 ); + send_message( hwnd, WM_WINE_IME_SET_OPEN_STATUS, FALSE, 0 ); + } + free( output ); }
@@ -152,7 +169,7 @@ static int xic_preedit_start( XIC xic, XPointer user, XPointer arg )
TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
- ximInComposeMode = TRUE; + xim_in_compose_mode = TRUE;
if (!(hwnd = get_builtin_ime_ui( hwnd ))) WARN( "No builtin IME UI, ignoring event.\n" ); else send_message( hwnd, WM_WINE_IME_SET_COMP_STATUS, TRUE, 0 ); @@ -166,7 +183,7 @@ static int xic_preedit_done( XIC xic, XPointer user, XPointer arg )
TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
- ximInComposeMode = FALSE; + xim_in_compose_mode = FALSE; free( preedit_buf ); preedit_max = 0; preedit_len = 0; @@ -194,7 +211,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) }
if (!(text = params->text)) - xim_update_preedit_string( params->chg_first, params->chg_length, NULL, 0 ); + xim_update_preedit_string( hwnd, params->chg_first, params->chg_length, NULL, 0 ); else { size_t text_len; @@ -214,7 +231,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) if ((output = malloc( text_len * sizeof(WCHAR) ))) { text_len = ntdll_umbstowcs( str, text_len, output, text_len ); - xim_update_preedit_string( params->chg_first, params->chg_length, output, text_len ); + xim_update_preedit_string( hwnd, params->chg_first, params->chg_length, output, text_len ); free( output ); }
diff --git a/include/ntuser.h b/include/ntuser.h index e00bfaee44b..331b2b6b4a5 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -496,6 +496,7 @@ enum wine_internal_message #define WM_WINE_IME_GET_CURSOR_POS (WM_USER + 1) #define WM_WINE_IME_SET_CURSOR_POS (WM_USER + 2) #define WM_WINE_IME_SET_COMP_STATUS (WM_USER + 3) +#define WM_WINE_IME_SET_COMP_TEXT EM_REPLACESEL
/* internal IME private */ typedef struct ime_private
v5: Remove some overlooked now unnecessary parameters and variables.
@bsjeon I believe that, with your comctl32 patch, the composition now works as it should for the two sequences you described.
I'm glad to see the WM_IME_ENDCOMPOSITION (x11drv_ime_set_result) fix included. Thank you.
--
The following is not relevant to this MR.
Example of typing '가나' in ibus-hangul: Here is the WINEDEBUG=xim trace result after removing merge_events() from process_events().
``` 00d0:trace:xim:xic_preedit_start xic 0x7d5ebd30, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76f118 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 0, text L"\3131" <== 'ㄱ' 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76f118 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text L"\ac00" <== '가' 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76f118 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text L"\ac04" <== '간' 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76f118 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text (null) 00d0:trace:xim:xic_preedit_done xic 0x7d5ebd30, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xim_set_result_string hwnd 0x1005e, str "\xea\xb0\x80" <== '가' 00d0:trace:xim:xic_create xim 0x7dc5b720, hwnd 0x10068/0 00d0:trace:xim:xic_preedit_start xic 0x7d5ebd30, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76de58 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 0, text L"\b098" <== '나' 00d0:trace:xim:xic_create created XIC 0x7d5ee0a0 00d0:fixme:imm:ime_ui_window_proc hwnd 00020070, himc 00010064, msg WM_IME_NOTIFY, wparam IMN_SETOPENSTATUS, lparam 0 stub!탸 ```
And this is the result of the current xim trace to Wine. ``` 00d0:trace:xim:xic_preedit_start xic 0x7d5f1300, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 0, text L"\3131" <== 'ㄱ' 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text L"\ac00" <== '가' 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text L"\ac04" <== '간' 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text (null) 00d0:trace:xim:xic_preedit_done xic 0x7d5f1300, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_start xic 0x7d5f1300, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 0, text L"\b098" <== '나' 00d0:trace:xim:xim_set_result_string hwnd 0x1005e, str "\xea\xb0\x80" <== '가' ``` You're aware of this issue, right?
On Wed Apr 19 12:22:45 2023 +0000, Byeongsik Jeon wrote:
@bsjeon I believe that, with your comctl32 patch, the composition now
works as it should for the two sequences you described. I'm glad to see the WM_IME_ENDCOMPOSITION (x11drv_ime_set_result) fix included. Thank you. -- The following is not relevant to this MR. Example of typing '가나' in ibus-hangul: After applying this MR, 'XMODIFIERS=@im=ibus WINEDEBUG=xim wine notepad'. Here is the WINEDEBUG=xim trace result after removing merge_events() from process_events().
00d0:trace:xim:xic_preedit_start xic 0x7d5ebd30, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76f118 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 0, text L"\3131" <== 'ㄱ' 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76f118 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text L"\ac00" <== '가' 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76f118 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text L"\ac04" <== '간' 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76f118 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text (null) 00d0:trace:xim:xic_preedit_done xic 0x7d5ebd30, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xim_set_result_string hwnd 0x1005e, str "\xea\xb0\x80" <== '가' 00d0:trace:xim:xic_create xim 0x7dc5b720, hwnd 0x10068/0 00d0:trace:xim:xic_preedit_start xic 0x7d5ebd30, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_draw xic 0x7d5ebd30, hwnd 0x1005e, arg 0x76de58 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 0, text L"\b098" <== '나' 00d0:trace:xim:xic_create created XIC 0x7d5ee0a0 00d0:fixme:imm:ime_ui_window_proc hwnd 00020070, himc 00010064, msg WM_IME_NOTIFY, wparam IMN_SETOPENSTATUS, lparam 0 stub!탸
And this is the result of the current xim trace to Wine.
00d0:trace:xim:xic_preedit_start xic 0x7d5f1300, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 0, text L"\3131" <== 'ㄱ' 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text L"\ac00" <== '가' 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text L"\ac04" <== '간' 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 1, text (null) 00d0:trace:xim:xic_preedit_done xic 0x7d5f1300, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_start xic 0x7d5f1300, hwnd 0x1005e, arg (nil) 00d0:trace:xim:xic_preedit_draw xic 0x7d5f1300, hwnd 0x1005e, arg 0x76f088 00d0:trace:xim:xim_update_preedit_string hwnd 0x20070, offset 0, old_len 0, text L"\b098" <== '나' 00d0:trace:xim:xim_set_result_string hwnd 0x1005e, str "\xea\xb0\x80" <== '가'
You're aware of this issue, right?
I haven't looked at the merge event issue yet. I think I understand how it can be a problem but I will need to investigate it a bit.
On Wed Apr 19 12:22:45 2023 +0000, Rémi Bernon wrote:
I haven't looked at the merge event issue yet. I think I understand how it can be a problem but I will need to investigate it a bit.
Thank you!!
There is a issue when calculating flags in input_context_set_comp_str().
With purely this MR applied, I type 'nihongo<SPACE>n' with ibus-anthy or ibus-mozc.
Below is the trace output. Note the lparam values. The analysis took a long time because I thought something else was causing it.
``` 00d0:trace:imm:input_context_set_comp_str ctx 00EF0690, result 1, str L"\65e5\672c\8a9e" 00d0:trace:imm:ime_send_message himc 00010064, msg 0x10f, wparam 0x65e5, lparam 0x18b8
00d0:trace:imm:input_context_set_comp_str ctx 00EF0690, result 0, str L"n" 00d0:trace:imm:ime_send_message himc 00010064, msg 0x10f, wparam 0x6e, lparam 0x1838 ```