-- v7: winemac: Use the default IME implementation for ImeToAsciiEx. winemac: Process IME input through the driver interface. win32u: Introduce a new ImeProcessKey call through NtUserMessageCall. winemac: Send IME key input from ImeProcessKey. winemac: Wait for IME input result on the unix side. winemac: Delay ime_set_text until ImeToAsciiEx requests it. winex11: Use IMN_WINE_SET_COMP_STRING / ImeToAsciiEx instead of callbacks. win32u: Introduce a new ImeToAsciiEx call through NtUserMessageCall. winex11: Send an internal WM_IME_NOTIFY wparam on composition updates. winex11: Use ime_comp_buf != NULL instead of ximInComposeMode. winex11: Use an internal WM_IME_NOTIFY wparam to get cursor pos. winex11: Use an internal WM_IME_NOTIFY wparam to set open status.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 19 ++++++++++++++++--- 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 | 6 ++---- include/ntuser.h | 3 +++ 7 files changed, 21 insertions(+), 19 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 3c4550c3cd9..4f0832238c0 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -40,6 +40,7 @@ static const char *debugstr_imn( WPARAM wparam ) case IMN_SETCOMPOSITIONWINDOW: return "IMN_SETCOMPOSITIONWINDOW"; case IMN_GUIDELINE: return "IMN_GUIDELINE"; case IMN_SETSTATUSWINDOWPOS: return "IMN_SETSTATUSWINDOWPOS"; + case IMN_WINE_SET_OPEN_STATUS: return "IMN_WINE_SET_OPEN_STATUS"; default: return wine_dbg_sprintf( "%#Ix", wparam ); } } @@ -242,6 +243,20 @@ static void ime_ui_start_composition( HIMC himc, HWND hwnd ) ImmUnlockIMC( himc ); }
+static LRESULT ime_ui_notify( HIMC himc, HWND hwnd, WPARAM wparam, LPARAM lparam ) +{ + TRACE( "himc %p, hwnd %p, wparam %s, lparam %#Ix\n", hwnd, himc, debugstr_imn(wparam), lparam ); + + switch (wparam) + { + case IMN_WINE_SET_OPEN_STATUS: + return ImmSetOpenStatus( himc, lparam ); + default: + FIXME( "himc %p, hwnd %p, wparam %s, lparam %#Ix stub!\n", hwnd, himc, debugstr_imn(wparam), lparam ); + return 0; + } +} + static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { HIMC himc = (HIMC)GetWindowLongPtrW( hwnd, IMMGWL_IMC ); @@ -284,9 +299,7 @@ static LRESULT WINAPI ime_ui_window_proc( HWND hwnd, UINT msg, WPARAM wparam, LP ShowWindow( hwnd, SW_HIDE ); break; case WM_IME_NOTIFY: - FIXME( "hwnd %p, himc %p, msg %s, wparam %s, lparam %#Ix stub!\n", hwnd, himc, - debugstr_wm_ime(msg), debugstr_imn(wparam), lparam ); - return 0; + return ime_ui_notify( himc, hwnd, wparam, lparam ); case WM_IME_CONTROL: FIXME( "hwnd %p, himc %p, msg %s, wparam %s, lparam %#Ix stub!\n", hwnd, himc, debugstr_wm_ime(msg), debugstr_imc(wparam), lparam ); 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 3601cb8c680..bdb1594799e 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -119,12 +119,10 @@ 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 ); + send_message( hwnd, WM_IME_NOTIFY, IMN_WINE_SET_OPEN_STATUS, TRUE ); break; case XIMPreeditDisable: - x11drv_client_call( client_ime_set_open_status, FALSE ); - break; - default: + send_message( hwnd, WM_IME_NOTIFY, IMN_WINE_SET_OPEN_STATUS, FALSE ); break; }
diff --git a/include/ntuser.h b/include/ntuser.h index 3d43eb476e4..14551227539 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -490,6 +490,9 @@ enum wine_internal_message #define IME_INTERNAL_HKL_ACTIVATE 0x19 #define IME_INTERNAL_HKL_DEACTIVATE 0x20
+/* internal WM_IME_NOTIFY wparams, not compatible with Windows */ +#define IMN_WINE_SET_OPEN_STATUS 0x000f + /* internal IME private */ typedef struct ime_private {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 22 ++++++++++++++++++++++ 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 | 2 +- include/ntuser.h | 1 + 7 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 4f0832238c0..472407e7e7a 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -41,6 +41,7 @@ static const char *debugstr_imn( WPARAM wparam ) case IMN_GUIDELINE: return "IMN_GUIDELINE"; case IMN_SETSTATUSWINDOWPOS: return "IMN_SETSTATUSWINDOWPOS"; case IMN_WINE_SET_OPEN_STATUS: return "IMN_WINE_SET_OPEN_STATUS"; + case IMN_WINE_GET_CURSOR_POS: return "IMN_WINE_GET_CURSOR_POS"; default: return wine_dbg_sprintf( "%#Ix", wparam ); } } @@ -243,6 +244,25 @@ static void ime_ui_start_composition( HIMC himc, HWND hwnd ) ImmUnlockIMC( himc ); }
+static UINT ime_get_cursor_pos( HIMC himc ) +{ + COMPOSITIONSTRING *compstr; + INPUTCONTEXT *ctx; + UINT pos = 0; + + TRACE( "himc %p\n", himc ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + if ((compstr = ImmLockIMCC( ctx->hCompStr ))) + { + pos = compstr->dwCursorPos; + ImmUnlockIMCC( ctx->hCompStr ); + } + ImmUnlockIMC( himc ); + + return pos; +} + static LRESULT ime_ui_notify( HIMC himc, HWND hwnd, WPARAM wparam, LPARAM lparam ) { TRACE( "himc %p, hwnd %p, wparam %s, lparam %#Ix\n", hwnd, himc, debugstr_imn(wparam), lparam ); @@ -251,6 +271,8 @@ static LRESULT ime_ui_notify( HIMC himc, HWND hwnd, WPARAM wparam, LPARAM lparam { case IMN_WINE_SET_OPEN_STATUS: return ImmSetOpenStatus( himc, lparam ); + case IMN_WINE_GET_CURSOR_POS: + return ime_get_cursor_pos( himc ); default: FIXME( "himc %p, hwnd %p, wparam %s, lparam %#Ix stub!\n", hwnd, himc, debugstr_imn(wparam), lparam ); return 0; 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 bdb1594799e..4ac7f72ce67 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -203,7 +203,7 @@ static int xic_preedit_caret( XIC xic, XPointer user, XPointer arg )
if (!params) return 0;
- pos = x11drv_client_call( client_ime_get_cursor_pos, 0 ); + pos = send_message( hwnd, WM_IME_NOTIFY, IMN_WINE_GET_CURSOR_POS, 0 ); switch (params->direction) { case XIMForwardChar: diff --git a/include/ntuser.h b/include/ntuser.h index 14551227539..db3d98e1315 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -492,6 +492,7 @@ enum wine_internal_message
/* internal WM_IME_NOTIFY wparams, not compatible with Windows */ #define IMN_WINE_SET_OPEN_STATUS 0x000f +#define IMN_WINE_GET_CURSOR_POS 0x0010
/* internal IME private */ typedef struct ime_private
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/event.c | 4 +--- dlls/winex11.drv/x11drv.h | 2 +- dlls/winex11.drv/xim.c | 12 ++++++++---- 3 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c index 1ae39eb9edf..aea119e1ec7 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/x11drv.h b/dlls/winex11.drv/x11drv.h index 9efaae3465b..05f576b8fb5 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -435,7 +435,6 @@ extern BOOL keyboard_grabbed DECLSPEC_HIDDEN; extern unsigned int screen_bpp DECLSPEC_HIDDEN; extern BOOL usexrandr DECLSPEC_HIDDEN; extern BOOL usexvidmode DECLSPEC_HIDDEN; -extern BOOL ximInComposeMode DECLSPEC_HIDDEN; extern BOOL use_take_focus DECLSPEC_HIDDEN; extern BOOL use_primary_selection DECLSPEC_HIDDEN; extern BOOL use_system_cursors DECLSPEC_HIDDEN; @@ -823,6 +822,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 BOOL xim_in_compose_mode(void) DECLSPEC_HIDDEN; extern void X11DRV_XIMLookupChars( const char *str, UINT count ) DECLSPEC_HIDDEN; extern XIC X11DRV_get_ic( HWND hwnd ) DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index 4ac7f72ce67..5e5cac0026d 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -42,8 +42,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(xim); #define XICProc XIMProc #endif
-BOOL ximInComposeMode=FALSE; - static WCHAR *ime_comp_buf;
static XIMStyle input_style = 0; @@ -69,6 +67,11 @@ static const char *debugstr_xim_style( XIMStyle style ) return wine_dbg_sprintf( "%s", buffer ); }
+BOOL xim_in_compose_mode(void) +{ + return !!ime_comp_buf; +} + static void xim_update_comp_string( UINT offset, UINT old_len, const WCHAR *text, UINT new_len ) { UINT len = ime_comp_buf ? wcslen( ime_comp_buf ) : 0; @@ -136,7 +139,9 @@ 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 ((ime_comp_buf = realloc( ime_comp_buf, sizeof(WCHAR) ))) *ime_comp_buf = 0; + else ERR( "Failed to allocate preedit buffer\n" ); + return -1; }
@@ -146,7 +151,6 @@ static int xic_preedit_done( XIC xic, XPointer user, XPointer arg )
TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
- ximInComposeMode = FALSE; free( ime_comp_buf ); ime_comp_buf = NULL;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 58 +++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/keyboard.c | 2 +- dlls/winex11.drv/x11drv.h | 2 +- dlls/winex11.drv/xim.c | 23 +++++++++++++-- include/ntuser.h | 1 + 5 files changed, 82 insertions(+), 4 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 472407e7e7a..5ddc8973c2d 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -42,6 +42,7 @@ static const char *debugstr_imn( WPARAM wparam ) case IMN_SETSTATUSWINDOWPOS: return "IMN_SETSTATUSWINDOWPOS"; case IMN_WINE_SET_OPEN_STATUS: return "IMN_WINE_SET_OPEN_STATUS"; case IMN_WINE_GET_CURSOR_POS: return "IMN_WINE_GET_CURSOR_POS"; + case IMN_WINE_SET_COMP_STRING: return "IMN_WINE_SET_COMP_STRING"; default: return wine_dbg_sprintf( "%#Ix", wparam ); } } @@ -263,6 +264,61 @@ static UINT ime_get_cursor_pos( HIMC himc ) return pos; }
+static UINT ime_set_comp_string( HIMC himc, LPARAM lparam ) +{ + union + { + struct + { + UINT uMsgCount; + TRANSMSG TransMsg[10]; + }; + TRANSMSGLIST list; + } buffer = {.uMsgCount = ARRAY_SIZE(buffer.TransMsg)}; + COMPOSITIONSTRING *compstr; + INPUTCONTEXT *ctx; + TRANSMSG *msgs; + HIMCC himcc; + UINT count; + + TRACE( "himc %p\n", himc ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + + if (!(himcc = ImmReSizeIMCC( ctx->hCompStr, sizeof(*compstr) + sizeof(lparam) ))) + WARN( "Failed to resize input context composition string\n" ); + else if (!(compstr = ImmLockIMCC( (ctx->hCompStr = himcc) ))) + WARN( "Failed to lock input context composition string\n" ); + else + { + memset( compstr, 0, sizeof(*compstr) ); + compstr->dwSize = sizeof(*compstr) + sizeof(lparam); + compstr->dwPrivateSize = sizeof(lparam); + compstr->dwPrivateOffset = compstr->dwSize - sizeof(lparam); + memcpy( (BYTE *)compstr + compstr->dwPrivateOffset, &lparam, sizeof(lparam) ); + ImmUnlockIMCC( ctx->hCompStr ); + } + + count = ImeToAsciiEx( VK_PROCESSKEY, 0, NULL, &buffer.list, 0, himc ); + if (count >= buffer.uMsgCount) + WARN( "ImeToAsciiEx returned %#x messages\n", count ); + else if (!(himcc = ImmReSizeIMCC( ctx->hMsgBuf, (ctx->dwNumMsgBuf + count) * sizeof(*msgs) ))) + WARN( "Failed to resize input context message buffer\n" ); + else if (!(msgs = ImmLockIMCC( (ctx->hMsgBuf = himcc) ))) + WARN( "Failed to lock input context message buffer\n" ); + else + { + memcpy( msgs + ctx->dwNumMsgBuf, buffer.TransMsg, count * sizeof(*msgs) ); + ImmUnlockIMCC( ctx->hMsgBuf ); + ctx->dwNumMsgBuf += count; + } + + ImmUnlockIMC( himc ); + ImmGenerateMessage( himc ); + + return 0; +} + static LRESULT ime_ui_notify( HIMC himc, HWND hwnd, WPARAM wparam, LPARAM lparam ) { TRACE( "himc %p, hwnd %p, wparam %s, lparam %#Ix\n", hwnd, himc, debugstr_imn(wparam), lparam ); @@ -273,6 +329,8 @@ static LRESULT ime_ui_notify( HIMC himc, HWND hwnd, WPARAM wparam, LPARAM lparam return ImmSetOpenStatus( himc, lparam ); case IMN_WINE_GET_CURSOR_POS: return ime_get_cursor_pos( himc ); + case IMN_WINE_SET_COMP_STRING: + return ime_set_comp_string( himc, lparam ); default: FIXME( "himc %p, hwnd %p, wparam %s, lparam %#Ix stub!\n", hwnd, himc, debugstr_imn(wparam), lparam ); 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/x11drv.h b/dlls/winex11.drv/x11drv.h index 05f576b8fb5..9768aea9f11 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -823,7 +823,7 @@ extern struct x11drv_display_device_handler desktop_handler DECLSPEC_HIDDEN; extern BOOL xim_init( const WCHAR *input_style ) DECLSPEC_HIDDEN; extern void xim_thread_attach( struct x11drv_thread_data *data ) DECLSPEC_HIDDEN; extern BOOL xim_in_compose_mode(void) 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/xim.c b/dlls/winex11.drv/xim.c index 5e5cac0026d..ae596e83662 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -42,6 +42,13 @@ WINE_DEFAULT_DEBUG_CHANNEL(xim); #define XICProc XIMProc #endif
+struct ime_update +{ + DWORD cursor_pos; + WCHAR *comp_str; + WCHAR *result_str; +}; + static WCHAR *ime_comp_buf;
static XIMStyle input_style = 0; @@ -72,6 +79,12 @@ BOOL xim_in_compose_mode(void) return !!ime_comp_buf; }
+static void send_ime_composition_update( HWND hwnd, UINT cursor_pos, WCHAR *comp_str, WCHAR *result_str ) +{ + struct ime_update update = {.cursor_pos = cursor_pos, .comp_str = comp_str, .result_str = result_str}; + send_message( hwnd, WM_IME_NOTIFY, IMN_WINE_SET_COMP_STRING, (LPARAM)&update ); +} + static void xim_update_comp_string( UINT offset, UINT old_len, const WCHAR *text, UINT new_len ) { UINT len = ime_comp_buf ? wcslen( ime_comp_buf ) : 0; @@ -96,18 +109,20 @@ static void xim_update_comp_string( UINT offset, UINT old_len, const WCHAR *text x11drv_client_func( client_func_ime_set_composition_string, ime_comp_buf, len * sizeof(WCHAR) ); }
-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, string %s\n", hwnd, debugstr_an(str, count) );
if (!(output = malloc( (count + 1) * sizeof(WCHAR) ))) return; len = ntdll_umbstowcs( str, count, output, count ); output[len] = 0;
+ send_ime_composition_update( hwnd, -1, ime_comp_buf, output ); x11drv_client_func( client_func_ime_set_result, output, len * sizeof(WCHAR) ); + free( output ); }
@@ -141,6 +156,7 @@ static int xic_preedit_start( XIC xic, XPointer user, XPointer arg ) x11drv_client_call( client_ime_set_composition_status, TRUE ); if ((ime_comp_buf = realloc( ime_comp_buf, sizeof(WCHAR) ))) *ime_comp_buf = 0; else ERR( "Failed to allocate preedit buffer\n" ); + send_ime_composition_update( hwnd, -1, ime_comp_buf, NULL );
return -1; } @@ -151,6 +167,7 @@ static int xic_preedit_done( XIC xic, XPointer user, XPointer arg )
TRACE( "xic %p, hwnd %p, arg %p\n", xic, hwnd, arg );
+ send_ime_composition_update( hwnd, -1, NULL, NULL ); free( ime_comp_buf ); ime_comp_buf = NULL;
@@ -192,6 +209,7 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg )
if (text && str != text->string.multi_byte) free( str );
+ send_ime_composition_update( hwnd, params->caret, ime_comp_buf, NULL ); x11drv_client_call( client_ime_set_cursor_pos, params->caret );
return 0; @@ -236,6 +254,7 @@ static int xic_preedit_caret( XIC xic, XPointer user, XPointer arg ) break; } x11drv_client_call( client_ime_set_cursor_pos, pos ); + send_ime_composition_update( hwnd, pos, ime_comp_buf, NULL ); params->position = pos;
return 0; diff --git a/include/ntuser.h b/include/ntuser.h index db3d98e1315..1727350c891 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -493,6 +493,7 @@ enum wine_internal_message /* internal WM_IME_NOTIFY wparams, not compatible with Windows */ #define IMN_WINE_SET_OPEN_STATUS 0x000f #define IMN_WINE_GET_CURSOR_POS 0x0010 +#define IMN_WINE_SET_COMP_STRING 0x0011
/* internal IME private */ typedef struct ime_private
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 39 ++++++++++++++++++++++++---- dlls/imm32/imm_private.h | 2 ++ dlls/win32u/driver.c | 12 +++++++++ dlls/win32u/imm.c | 13 ++++++++++ dlls/win32u/message.c | 3 +++ dlls/win32u/ntuser_private.h | 4 +++ dlls/winex11.drv/ime.c | 8 ------ dlls/winex11.drv/init.c | 1 + dlls/winex11.drv/winex11.drv.spec | 1 - dlls/winex11.drv/x11drv.h | 2 ++ dlls/winex11.drv/xim.c | 43 +++++++++++++++++++++++++++++++ dlls/wow64win/user.c | 15 +++++++++++ include/ntuser.h | 16 ++++++++++++ include/wine/gdi_driver.h | 3 +++ 14 files changed, 148 insertions(+), 14 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 5ddc8973c2d..89c505af6cb 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -449,12 +449,41 @@ BOOL WINAPI ImeProcessKey( HIMC himc, UINT vkey, LPARAM key_data, BYTE *key_stat return FALSE; }
-UINT WINAPI ImeToAsciiEx( UINT vkey, UINT scan_code, BYTE *key_state, TRANSMSGLIST *msgs, UINT state, HIMC himc ) +UINT WINAPI ImeToAsciiEx( UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, UINT flags, HIMC himc ) { - FIXME( "vkey %u, scan_code %u, key_state %p, msgs %p, state %u, himc %p stub!\n", - vkey, scan_code, key_state, msgs, state, himc ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return 0; + COMPOSITIONSTRING old_compstr, *compstr; + UINT ret, count = 0; + INPUTCONTEXT *ctx; + + TRACE( "vkey %#x, vsc %#x, state %p, msgs %p, flags %#x, himc %p\n", + vkey, vsc, state, msgs, flags, himc ); + + if (!(ctx = ImmLockIMC( himc ))) return 0; + if (!(compstr = ImmLockIMCC( ctx->hCompStr ))) goto done; + old_compstr = *compstr; + + do + { + struct ime_driver_call_params params = {.himc = himc, .state = state}; + HIMCC himcc; + + ImmUnlockIMCC( ctx->hCompStr ); + if (!(himcc = ImmReSizeIMCC( ctx->hCompStr, old_compstr.dwSize ))) goto done; + if (!(compstr = ImmLockIMCC( (ctx->hCompStr = himcc) ))) goto done; + + params.compstr = compstr; + ret = NtUserMessageCall( ctx->hWnd, WINE_IME_TO_ASCII_EX, vkey, vsc, ¶ms, + NtUserImeDriverCall, FALSE ); + old_compstr.dwSize = compstr->dwSize; + } while (ret == STATUS_BUFFER_TOO_SMALL); + + if (ret) WARN( "WINE_IME_TO_ASCII_EX returned status %#x\n", ret ); + + ImmUnlockIMCC( ctx->hCompStr ); + +done: + ImmUnlockIMC( himc ); + return count; }
BOOL WINAPI ImeConfigure( HKL hkl, HWND hwnd, DWORD mode, void *data ) diff --git a/dlls/imm32/imm_private.h b/dlls/imm32/imm_private.h index 8a957494ce9..4cc4acda6c1 100644 --- a/dlls/imm32/imm_private.h +++ b/dlls/imm32/imm_private.h @@ -19,6 +19,8 @@ #include <stdarg.h> #include <stddef.h>
+#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" #include "wingdi.h" diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 5bae77da5f4..200c6cc78a2 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -716,6 +716,11 @@ static SHORT nulldrv_VkKeyScanEx( WCHAR ch, HKL layout ) return -256; /* use default implementation */ }
+static UINT nulldrv_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc ) +{ + return 0; +} + static LRESULT nulldrv_DesktopWindowProc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) { return default_window_proc( hwnd, msg, wparam, lparam, FALSE ); @@ -1070,6 +1075,11 @@ static SHORT loaderdrv_VkKeyScanEx( WCHAR ch, HKL layout ) return load_driver()->pVkKeyScanEx( ch, layout ); }
+static UINT loaderdrv_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc ) +{ + return load_driver()->pImeToAsciiEx( vkey, vsc, state, compstr, himc ); +} + static LONG loaderdrv_ChangeDisplaySettings( LPDEVMODEW displays, LPCWSTR primary_name, HWND hwnd, DWORD flags, LPVOID lparam ) { @@ -1176,6 +1186,7 @@ static const struct user_driver_funcs lazy_load_driver = loaderdrv_ToUnicodeEx, loaderdrv_UnregisterHotKey, loaderdrv_VkKeyScanEx, + loaderdrv_ImeToAsciiEx, /* cursor/icon functions */ nulldrv_DestroyCursorIcon, loaderdrv_SetCursor, @@ -1255,6 +1266,7 @@ void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version SET_USER_FUNC(ToUnicodeEx); SET_USER_FUNC(UnregisterHotKey); SET_USER_FUNC(VkKeyScanEx); + SET_USER_FUNC(ImeToAsciiEx); SET_USER_FUNC(DestroyCursorIcon); SET_USER_FUNC(SetCursor); SET_USER_FUNC(GetCursorPos); diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c index 7dee4912e27..9090131d26c 100644 --- a/dlls/win32u/imm.c +++ b/dlls/win32u/imm.c @@ -421,6 +421,19 @@ NTSTATUS WINAPI NtUserBuildHimcList( UINT thread_id, UINT count, HIMC *buffer, U return STATUS_SUCCESS; }
+LRESULT ime_driver_call( HWND hwnd, enum wine_ime_call call, WPARAM wparam, LPARAM lparam, + struct ime_driver_call_params *params ) +{ + switch (call) + { + case WINE_IME_TO_ASCII_EX: + return user_driver->pImeToAsciiEx( wparam, lparam, params->state, params->compstr, params->himc ); + default: + ERR( "Unknown IME driver call %#x\n", call ); + return 0; + } +} + BOOL WINAPI DECLSPEC_HIDDEN ImmProcessKey( HWND hwnd, HKL hkl, UINT vkey, LPARAM key_data, DWORD unknown ) { struct imm_process_key_params params = diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 5ca568d7302..b3d94120455 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3522,6 +3522,9 @@ LRESULT WINAPI NtUserMessageCall( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpa spy_exit_message( ansi, hwnd, msg, (LPARAM)result_info, wparam, lparam ); return 0;
+ case NtUserImeDriverCall: + return ime_driver_call( hwnd, msg, wparam, lparam, result_info ); + default: FIXME( "%p %x %lx %lx %p %x %x\n", hwnd, msg, (long)wparam, lparam, result_info, (int)type, ansi ); } diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h index c9c2dfa571a..0e7d84e3faa 100644 --- a/dlls/win32u/ntuser_private.h +++ b/dlls/win32u/ntuser_private.h @@ -229,6 +229,10 @@ BOOL needs_ime_window( HWND hwnd ) DECLSPEC_HIDDEN; extern void register_builtin_classes(void) DECLSPEC_HIDDEN; extern void register_desktop_class(void) DECLSPEC_HIDDEN;
+/* imm.c */ +extern LRESULT ime_driver_call( HWND hwnd, enum wine_ime_call call, WPARAM wparam, LPARAM lparam, + struct ime_driver_call_params *params ) DECLSPEC_HIDDEN; + /* cursoricon.c */ HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN;
diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index b92c13ff08a..61d56030101 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -521,14 +521,6 @@ BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) return TRUE; }
-UINT WINAPI ImeToAsciiEx (UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState, - TRANSMSGLIST *lpdwTransKey, UINT fuState, HIMC hIMC) -{ - /* See the comment at the head of this file */ - TRACE("We do no processing via this route\n"); - return 0; -} - BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) { struct xim_preedit_state_params preedit_params; diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index e26cfb5a789..058dcf965c6 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -398,6 +398,7 @@ static const struct user_driver_funcs x11drv_funcs = .pMapVirtualKeyEx = X11DRV_MapVirtualKeyEx, .pToUnicodeEx = X11DRV_ToUnicodeEx, .pVkKeyScanEx = X11DRV_VkKeyScanEx, + .pImeToAsciiEx = X11DRV_ImeToAsciiEx, .pDestroyCursorIcon = X11DRV_DestroyCursorIcon, .pSetCursor = X11DRV_SetCursor, .pGetCursorPos = X11DRV_GetCursorPos, diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index a753536eb3f..3f343da3dea 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -12,7 +12,6 @@
#IME Interface @ stdcall ImeSelect(long long) -@ stdcall ImeToAsciiEx(long long ptr ptr long long) @ stdcall NotifyIME(long long long long) @ stdcall ImeSetCompositionString(long long ptr long ptr long) @ stdcall ImeProcessKey(long long long ptr) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 9768aea9f11..7283f4020c2 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -208,6 +208,8 @@ extern INT X11DRV_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size ) DECLSPE extern UINT X11DRV_MapVirtualKeyEx( UINT code, UINT map_type, HKL hkl ) DECLSPEC_HIDDEN; extern INT X11DRV_ToUnicodeEx( UINT virtKey, UINT scanCode, const BYTE *lpKeyState, LPWSTR bufW, int bufW_size, UINT flags, HKL hkl ) DECLSPEC_HIDDEN; +extern UINT X11DRV_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state, + COMPOSITIONSTRING *compstr, HIMC himc ) DECLSPEC_HIDDEN; extern SHORT X11DRV_VkKeyScanEx( WCHAR wChar, HKL hkl ) DECLSPEC_HIDDEN; extern void X11DRV_DestroyCursorIcon( HCURSOR handle ) DECLSPEC_HIDDEN; extern void X11DRV_SetCursor( HCURSOR handle ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index ae596e83662..fdcb7704a2f 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -27,6 +27,8 @@ #include <stdlib.h> #include <stdarg.h>
+#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" #include "winnls.h" @@ -505,3 +507,44 @@ XIC X11DRV_get_ic( HWND hwnd )
return ret; } + +/*********************************************************************** + * ImeToAsciiEx (X11DRV.@) + * + * As XIM filters key events upfront, we don't use ImeProcessKey and ImeToAsciiEx is instead called + * back from the IME UI window procedure when WM_IME_NOTIFY / IMN_WINE_SET_COMP_STRING messages are + * sent to it, to retrieve composition string updates and generate WM_IME messages. + */ +UINT X11DRV_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc ) +{ + UINT needed = sizeof(COMPOSITIONSTRING), comp_len, result_len; + void *private = (BYTE *)compstr + compstr->dwPrivateOffset; + struct ime_update *update = *(struct ime_update **)private; + + TRACE( "vkey %#x, vsc %#x, state %p, compstr %p, himc %p\n", vkey, vsc, state, compstr, himc ); + + if (!update->comp_str) comp_len = 0; + else + { + comp_len = wcslen( update->comp_str ); + needed += comp_len * sizeof(WCHAR); /* GCS_COMPSTR */ + needed += comp_len; /* GCS_COMPATTR */ + needed += 2 * sizeof(DWORD); /* GCS_COMPCLAUSE */ + } + + if (!update->result_str) result_len = 0; + else + { + result_len = wcslen( update->result_str ); + needed += result_len * sizeof(WCHAR); /* GCS_RESULTSTR */ + needed += 2 * sizeof(DWORD); /* GCS_RESULTCLAUSE */ + } + + if (compstr->dwSize < needed) + { + compstr->dwSize = needed; + return STATUS_BUFFER_TOO_SMALL; + } + + return 0; +} diff --git a/dlls/wow64win/user.c b/dlls/wow64win/user.c index e1ce2dd8321..8c006d07e2a 100644 --- a/dlls/wow64win/user.c +++ b/dlls/wow64win/user.c @@ -3116,6 +3116,21 @@ NTSTATUS WINAPI wow64_NtUserMessageCall( UINT *args ) return message_call_32to64( hwnd, msg, wparam, lparam, LongToPtr( result32 ), type, ansi ); } + + case NtUserImeDriverCall: + { + struct + { + ULONG himc; + ULONG state; + ULONG compstr; + } *params32 = result_info; + struct ime_driver_call_params params; + params.himc = UlongToPtr( params32->himc ); + params.state = UlongToPtr( params32->state ); + params.compstr = UlongToPtr( params32->compstr ); + return NtUserMessageCall( hwnd, msg, wparam, lparam, ¶ms, type, ansi ); + } }
return message_call_32to64( hwnd, msg, wparam, lparam, result_info, type, ansi ); diff --git a/include/ntuser.h b/include/ntuser.h index 1727350c891..5d352552a70 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -22,6 +22,7 @@ #include <winuser.h> #include <wingdi.h> #include <imm.h> +#include <immdev.h> #include <winternl.h>
/* KernelCallbackTable codes, not compatible with Windows */ @@ -305,6 +306,7 @@ enum NtUserSpyEnter = 0x0304, NtUserSpyExit = 0x0305, NtUserWinProcResult = 0x0306, + NtUserImeDriverCall = 0x0307, };
/* NtUserThunkedMenuItemInfo codes */ @@ -495,6 +497,20 @@ enum wine_internal_message #define IMN_WINE_GET_CURSOR_POS 0x0010 #define IMN_WINE_SET_COMP_STRING 0x0011
+/* builtin IME driver calls */ +enum wine_ime_call +{ + WINE_IME_TO_ASCII_EX, +}; + +/* NtUserImeDriverCall params */ +struct ime_driver_call_params +{ + HIMC himc; + const BYTE *state; + COMPOSITIONSTRING *compstr; +}; + /* internal IME private */ typedef struct ime_private { diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 0eb24fd4424..3ffc28dc15a 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -23,6 +23,7 @@
#include "winternl.h" #include "ntuser.h" +#include "immdev.h" #include "ddk/d3dkmthk.h" #include "wine/list.h"
@@ -287,6 +288,8 @@ struct user_driver_funcs INT (*pToUnicodeEx)(UINT,UINT,const BYTE *,LPWSTR,int,UINT,HKL); void (*pUnregisterHotKey)(HWND, UINT, UINT); SHORT (*pVkKeyScanEx)(WCHAR, HKL); + /* IME functions */ + UINT (*pImeToAsciiEx)(UINT,UINT,const BYTE*,COMPOSITIONSTRING*,HIMC); /* cursor/icon functions */ void (*pDestroyCursorIcon)(HCURSOR); void (*pSetCursor)(HCURSOR);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 35 ++++++++++ dlls/winex11.drv/dllmain.c | 5 -- dlls/winex11.drv/ime.c | 124 ---------------------------------- dlls/winex11.drv/unixlib.h | 5 -- dlls/winex11.drv/x11drv_dll.h | 5 -- dlls/winex11.drv/xim.c | 63 +++++++++++++---- 6 files changed, 84 insertions(+), 153 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 89c505af6cb..300e5fe12cb 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -478,10 +478,45 @@ UINT WINAPI ImeToAsciiEx( UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, } while (ret == STATUS_BUFFER_TOO_SMALL);
if (ret) WARN( "WINE_IME_TO_ASCII_EX returned status %#x\n", ret ); + else + { + if (!old_compstr.dwCompStrOffset && compstr->dwCompStrOffset) + { + TRANSMSG msg = {.message = WM_IME_STARTCOMPOSITION}; + msgs->TransMsg[count++] = msg; + } + else if (old_compstr.dwCompStrOffset && !compstr->dwCompStrOffset) + { + TRANSMSG msg = {.message = WM_IME_ENDCOMPOSITION}; + msgs->TransMsg[count++] = msg; + } + + if (compstr->dwResultStrLen) + { + const WCHAR *result = (WCHAR *)((BYTE *)compstr + compstr->dwResultStrOffset); + TRANSMSG msg = {.message = WM_IME_COMPOSITION, .wParam = result[0], .lParam = GCS_RESULTSTR}; + if (compstr->dwResultClauseOffset) msg.lParam |= GCS_RESULTCLAUSE; + msgs->TransMsg[count++] = msg; + } + + if (compstr->dwCompStrLen) + { + const WCHAR *comp = (WCHAR *)((BYTE *)compstr + compstr->dwCompStrOffset); + TRANSMSG msg = {.message = WM_IME_COMPOSITION, .wParam = comp[0], .lParam = GCS_COMPSTR}; + if (compstr->dwCursorPos != old_compstr.dwCursorPos) msg.lParam |= GCS_CURSORPOS; + if (compstr->dwDeltaStart != old_compstr.dwDeltaStart) msg.lParam |= GCS_DELTASTART; + if (compstr->dwCompAttrOffset) msg.lParam |= GCS_COMPATTR; + if (compstr->dwCompClauseOffset) msg.lParam |= GCS_COMPCLAUSE; + else msg.lParam |= CS_INSERTCHAR|CS_NOMOVECARET; + msgs->TransMsg[count++] = msg; + } + }
ImmUnlockIMCC( ctx->hCompStr );
done: + if (count >= msgs->uMsgCount) FIXME( "More than %u messages queued, messages possibly lost\n", msgs->uMsgCount ); + else TRACE( "Returning %u messages queued\n", count ); ImmUnlockIMC( himc ); return count; } diff --git a/dlls/winex11.drv/dllmain.c b/dlls/winex11.drv/dllmain.c index a3375e60957..3aa0a9875d0 100644 --- a/dlls/winex11.drv/dllmain.c +++ b/dlls/winex11.drv/dllmain.c @@ -30,9 +30,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, };
C_ASSERT( ARRAYSIZE(callback_funcs) == client_funcs_count ); @@ -50,8 +47,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/ime.c b/dlls/winex11.drv/ime.c index 61d56030101..91d9f085ff0 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -744,127 +744,3 @@ BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp,
return TRUE; } - -/* 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_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 ); - - ImmGetContext(focus); - - if (focus && hSelectedFrom) - 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/unixlib.h b/dlls/winex11.drv/unixlib.h index 332c4e4b3fa..cae523b2f96 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 }; @@ -96,9 +94,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..bab27afce14 100644 --- a/dlls/winex11.drv/x11drv_dll.h +++ b/dlls/winex11.drv/x11drv_dll.h @@ -30,15 +30,10 @@ 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; 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, LPARAM lparam ) DECLSPEC_HIDDEN; diff --git a/dlls/winex11.drv/xim.c b/dlls/winex11.drv/xim.c index fdcb7704a2f..510754cb039 100644 --- a/dlls/winex11.drv/xim.c +++ b/dlls/winex11.drv/xim.c @@ -105,10 +105,7 @@ static void xim_update_comp_string( UINT offset, UINT old_len, const WCHAR *text ptr = ime_comp_buf + offset; memmove( ptr + new_len, ptr + old_len, (len - offset - old_len) * sizeof(WCHAR) ); if (text) memcpy( ptr, text, new_len * sizeof(WCHAR) ); - len += diff; - ime_comp_buf[len] = 0; - - x11drv_client_func( client_func_ime_set_composition_string, ime_comp_buf, len * sizeof(WCHAR) ); + ime_comp_buf[len + diff] = 0; }
void xim_set_result_string( HWND hwnd, const char *str, UINT count ) @@ -123,7 +120,6 @@ void xim_set_result_string( HWND hwnd, const char *str, UINT count ) output[len] = 0;
send_ime_composition_update( hwnd, -1, ime_comp_buf, output ); - x11drv_client_func( client_func_ime_set_result, output, len * sizeof(WCHAR) );
free( output ); } @@ -155,7 +151,6 @@ 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 ); if ((ime_comp_buf = realloc( ime_comp_buf, sizeof(WCHAR) ))) *ime_comp_buf = 0; else ERR( "Failed to allocate preedit buffer\n" ); send_ime_composition_update( hwnd, -1, ime_comp_buf, NULL ); @@ -173,7 +168,6 @@ static int xic_preedit_done( XIC xic, XPointer user, XPointer arg ) free( ime_comp_buf ); ime_comp_buf = NULL;
- x11drv_client_call( client_ime_set_composition_status, FALSE ); return 0; }
@@ -212,7 +206,6 @@ static int xic_preedit_draw( XIC xic, XPointer user, XPointer arg ) if (text && str != text->string.multi_byte) free( str );
send_ime_composition_update( hwnd, params->caret, ime_comp_buf, NULL ); - x11drv_client_call( client_ime_set_cursor_pos, params->caret );
return 0; } @@ -255,7 +248,7 @@ 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_ime_composition_update( hwnd, pos, ime_comp_buf, NULL ); params->position = pos;
@@ -409,8 +402,6 @@ static void xim_open( Display *display, XPointer user, XPointer arg ) TRACE( "display %p, data %p, arg %p\n", display, user, arg ); if (!(data->xim = xim_create( data ))) return; XUnregisterIMInstantiateCallback( display, NULL, NULL, NULL, xim_open, user ); - - x11drv_client_call( client_ime_update_association, 0 ); }
static void xim_destroy( XIM xim, XPointer user, XPointer arg ) @@ -433,8 +424,8 @@ void xim_thread_attach( struct x11drv_thread_data *data ) for (i = 0; list && i < count; ++i) TRACE( " %d: %s\n", i, list[i] ); if (list) XFreeStringList( list );
- if ((data->xim = xim_create( data ))) x11drv_client_call( client_ime_update_association, 0 ); - else XRegisterIMInstantiateCallback( display, NULL, NULL, NULL, xim_open, (XPointer)data ); + if ((data->xim = xim_create( data ))) return; + XRegisterIMInstantiateCallback( display, NULL, NULL, NULL, xim_open, (XPointer)data ); }
static BOOL xic_destroy( XIC xic, XPointer user, XPointer arg ) @@ -518,7 +509,7 @@ XIC X11DRV_get_ic( HWND hwnd ) UINT X11DRV_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc ) { UINT needed = sizeof(COMPOSITIONSTRING), comp_len, result_len; - void *private = (BYTE *)compstr + compstr->dwPrivateOffset; + void *dst, *private = (BYTE *)compstr + compstr->dwPrivateOffset; struct ime_update *update = *(struct ime_update **)private;
TRACE( "vkey %#x, vsc %#x, state %p, compstr %p, himc %p\n", vkey, vsc, state, compstr, himc ); @@ -546,5 +537,49 @@ UINT X11DRV_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTR return STATUS_BUFFER_TOO_SMALL; }
+ memset( compstr, 0, sizeof(*compstr) ); + compstr->dwSize = sizeof(*compstr); + + if (update->comp_str) + { + compstr->dwCursorPos = update->cursor_pos; + compstr->dwDeltaStart = 0; + + compstr->dwCompStrLen = comp_len; + compstr->dwCompStrOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwCompStrOffset; + memcpy( dst, update->comp_str, compstr->dwCompStrLen * sizeof(WCHAR) ); + compstr->dwSize += compstr->dwCompStrLen * sizeof(WCHAR); + + compstr->dwCompClauseLen = 2 * sizeof(DWORD); + compstr->dwCompClauseOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwCompClauseOffset; + *((DWORD *)dst + 0) = 0; + *((DWORD *)dst + 1) = compstr->dwCompStrLen; + compstr->dwSize += compstr->dwCompClauseLen; + + compstr->dwCompAttrLen = compstr->dwCompStrLen; + compstr->dwCompAttrOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwCompAttrOffset; + memset( dst, ATTR_INPUT, compstr->dwCompAttrLen ); + compstr->dwSize += compstr->dwCompAttrLen; + } + + if (update->result_str) + { + compstr->dwResultStrLen = result_len; + compstr->dwResultStrOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwResultStrOffset; + memcpy( dst, update->result_str, compstr->dwResultStrLen * sizeof(WCHAR) ); + compstr->dwSize += compstr->dwResultStrLen * sizeof(WCHAR); + + compstr->dwResultClauseLen = 2 * sizeof(DWORD); + compstr->dwResultClauseOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwResultClauseOffset; + *((DWORD *)dst + 0) = 0; + *((DWORD *)dst + 1) = compstr->dwResultStrLen; + compstr->dwSize += compstr->dwResultClauseLen; + } + return 0; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/event.c | 47 ++++++++++++++++++++++++++++++++-- dlls/winemac.drv/ime.c | 12 ++++++--- dlls/winemac.drv/macdrv.h | 1 + dlls/winemac.drv/macdrv_main.c | 2 ++ dlls/winemac.drv/unixlib.h | 1 + 5 files changed, 58 insertions(+), 5 deletions(-)
diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c index 03c49b34bae..cc8aa4681c6 100644 --- a/dlls/winemac.drv/event.c +++ b/dlls/winemac.drv/event.c @@ -32,6 +32,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(event); WINE_DECLARE_DEBUG_CHANNEL(imm);
+struct ime_update +{ + struct ime_set_text_params *comp_params; + DWORD comp_size; + struct ime_set_text_params *result_params; + DWORD result_size; +}; +static struct ime_update ime_update;
/* return the name of an Mac event */ static const char *dbgstr_event(int type) @@ -170,7 +178,20 @@ static void macdrv_im_set_text(const macdrv_event *event) if (length) CFStringGetCharacters(event->im_set_text.text, CFRangeMake(0, length), params->text);
- macdrv_client_func(client_func_ime_set_text, params, size); + free(ime_update.comp_params); + ime_update.comp_params = NULL; + + if (params->complete) + { + free(ime_update.result_params); + ime_update.result_params = params; + ime_update.result_size = size; + } + else + { + ime_update.comp_params = params; + ime_update.comp_size = size; + } }
/*********************************************************************** @@ -179,7 +200,29 @@ static void macdrv_im_set_text(const macdrv_event *event) static void macdrv_sent_text_input(const macdrv_event *event) { TRACE_(imm)("handled: %s\n", event->sent_text_input.handled ? "TRUE" : "FALSE"); - *event->sent_text_input.done = event->sent_text_input.handled ? 1 : -1; + *event->sent_text_input.done = event->sent_text_input.handled || ime_update.result_params ? 1 : -1; +} + + +/*********************************************************************** + * macdrv_ime_get_text_input + */ +NTSTATUS macdrv_ime_get_text_input(void *arg) +{ + if (ime_update.result_params) + { + macdrv_client_func(client_func_ime_set_text, ime_update.result_params, ime_update.result_size); + free(ime_update.result_params); + ime_update.result_params = NULL; + } + if (ime_update.comp_params) + { + macdrv_client_func(client_func_ime_set_text, ime_update.comp_params, ime_update.comp_size); + free(ime_update.comp_params); + ime_update.comp_params = NULL; + } + + return 0; }
diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c index 059a5c443f3..351eb28ff98 100644 --- a/dlls/winemac.drv/ime.c +++ b/dlls/winemac.drv/ime.c @@ -679,10 +679,16 @@ UINT WINAPI ImeToAsciiEx(UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState,
return msgs; } - else if ((lpIMC = LockRealIMC(hIMC))) + else { - UpdateDataInDefaultIMEWindow( lpIMC, hwnd, FALSE ); - UnlockRealIMC(hIMC); + /* trigger the pending client_func_ime_set_text call */ + MACDRV_CALL(ime_get_text_input, NULL); + + if ((lpIMC = LockRealIMC(hIMC))) + { + UpdateDataInDefaultIMEWindow( lpIMC, hwnd, FALSE ); + UnlockRealIMC(hIMC); + } } return 0; } diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 281d49c1e9a..b77e62f75db 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -277,6 +277,7 @@ extern NTSTATUS macdrv_dnd_have_format(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_release(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_retain(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_ime_process_text_input(void *arg) DECLSPEC_HIDDEN; +extern NTSTATUS macdrv_ime_get_text_input(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_notify_icon(void *arg) DECLSPEC_HIDDEN;
extern NTSTATUS macdrv_client_func(enum macdrv_client_funcs func, const void *params, diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index a4b280283ee..bf03ab6f5fe 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -635,6 +635,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = macdrv_dnd_retain, macdrv_ime_clear, macdrv_ime_process_text_input, + macdrv_ime_get_text_input, macdrv_ime_using_input_method, macdrv_init, macdrv_notify_icon, @@ -761,6 +762,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = macdrv_dnd_retain, macdrv_ime_clear, wow64_ime_process_text_input, + macdrv_ime_get_text_input, macdrv_ime_using_input_method, wow64_init, wow64_notify_icon, diff --git a/dlls/winemac.drv/unixlib.h b/dlls/winemac.drv/unixlib.h index ca5115f4982..b3f45291904 100644 --- a/dlls/winemac.drv/unixlib.h +++ b/dlls/winemac.drv/unixlib.h @@ -28,6 +28,7 @@ enum macdrv_funcs unix_dnd_retain, unix_ime_clear, unix_ime_process_text_input, + unix_ime_get_text_input, unix_ime_using_input_method, unix_init, unix_notify_icon,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/ime.c | 10 +++------- dlls/winemac.drv/keyboard.c | 14 ++++++-------- dlls/winemac.drv/macdrv_main.c | 2 -- dlls/winemac.drv/unixlib.h | 1 - 4 files changed, 9 insertions(+), 18 deletions(-)
diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c index 351eb28ff98..23e6d1c78cc 100644 --- a/dlls/winemac.drv/ime.c +++ b/dlls/winemac.drv/ime.c @@ -628,7 +628,7 @@ UINT WINAPI ImeToAsciiEx(UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState, LPIMEPRIVATE myPrivate; HWND hwnd; UINT repeat; - int done = 0; + UINT ret;
TRACE("uVKey 0x%04x uScanCode 0x%04x fuState %u hIMC %p\n", uVKey, uScanCode, fuState, hIMC);
@@ -660,13 +660,9 @@ UINT WINAPI ImeToAsciiEx(UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState, params.scan = uScanCode; params.repeat = repeat; params.key_state = lpbKeyState; - params.done = &done; - MACDRV_CALL(ime_process_text_input, ¶ms); + ret = MACDRV_CALL(ime_process_text_input, ¶ms);
- while (!done) - MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_POSTMESSAGE | QS_SENDMESSAGE, 0); - - if (done < 0) + if (!ret) { UINT msgs = 0; UINT msg = (uScanCode & 0x8000) ? WM_KEYUP : WM_KEYDOWN; diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c index 14731f2d235..17abbedb230 100644 --- a/dlls/winemac.drv/keyboard.c +++ b/dlls/winemac.drv/keyboard.c @@ -1197,7 +1197,7 @@ NTSTATUS macdrv_ime_process_text_input(void *arg) void *himc = UlongToHandle(params->himc); const BYTE *key_state = params->key_state; unsigned int flags; - int keyc; + int keyc, done = 0;
TRACE("vkey 0x%04x scan 0x%04x repeat %u himc %p\n", params->vkey, params->scan, params->repeat, himc); @@ -1224,17 +1224,15 @@ NTSTATUS macdrv_ime_process_text_input(void *arg) for (keyc = 0; keyc < ARRAY_SIZE(thread_data->keyc2vkey); keyc++) if (thread_data->keyc2vkey[keyc] == params->vkey) break;
- if (keyc >= ARRAY_SIZE(thread_data->keyc2vkey)) - { - *params->done = -1; - return 0; - } + if (keyc >= ARRAY_SIZE(thread_data->keyc2vkey)) return 0;
TRACE("flags 0x%08x keyc 0x%04x\n", flags, keyc);
macdrv_send_text_input_event(((params->scan & 0x8000) == 0), flags, params->repeat, keyc, - himc, params->done); - return 0; + himc, &done); + while (!done) NtUserMsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_POSTMESSAGE | QS_SENDMESSAGE, 0); + + return done > 0; }
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index bf03ab6f5fe..7e91e0ca3e1 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -673,7 +673,6 @@ static NTSTATUS wow64_ime_process_text_input(void *arg) UINT scan; UINT repeat; ULONG key_state; - ULONG done; } *params32 = arg; struct process_text_input_params params;
@@ -682,7 +681,6 @@ static NTSTATUS wow64_ime_process_text_input(void *arg) params.scan = params32->scan; params.repeat = params32->repeat; params.key_state = UlongToPtr(params32->key_state); - params.done = UlongToPtr(params32->done); return macdrv_ime_process_text_input(¶ms); }
diff --git a/dlls/winemac.drv/unixlib.h b/dlls/winemac.drv/unixlib.h index b3f45291904..493e4f6c139 100644 --- a/dlls/winemac.drv/unixlib.h +++ b/dlls/winemac.drv/unixlib.h @@ -69,7 +69,6 @@ struct process_text_input_params UINT scan; UINT repeat; const BYTE *key_state; - int *done; };
/* macdrv_init params */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/ime.c | 72 ++++++++++-------------------------------- include/ntuser.h | 1 - 2 files changed, 17 insertions(+), 56 deletions(-)
diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c index 23e6d1c78cc..1914940f242 100644 --- a/dlls/winemac.drv/ime.c +++ b/dlls/winemac.drv/ime.c @@ -469,24 +469,6 @@ static void GenerateIMEMessage(HIMC hIMC, UINT msg, WPARAM wParam, LPARAM lParam UnlockRealIMC(hIMC); }
-static BOOL GenerateMessageToTransKey(TRANSMSGLIST *lpTransBuf, UINT *uNumTranMsgs, - UINT msg, WPARAM wParam, LPARAM lParam) -{ - LPTRANSMSG ptr; - - if (*uNumTranMsgs + 1 >= lpTransBuf->uMsgCount) - return FALSE; - - ptr = lpTransBuf->TransMsg + *uNumTranMsgs; - ptr->message = msg; - ptr->wParam = wParam; - ptr->lParam = lParam; - (*uNumTranMsgs)++; - - return TRUE; -} - - static BOOL IME_RemoveFromSelected(HIMC hIMC) { int i; @@ -535,8 +517,14 @@ static void UpdateDataInDefaultIMEWindow(INPUTCONTEXT *lpIMC, HWND hwnd, BOOL sh
BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT vKey, LPARAM lKeyData, const LPBYTE lpbKeyState) { + struct process_text_input_params params = + { + .himc = (UINT_PTR)hIMC, .vkey = LOWORD(vKey), .scan = HIWORD(lKeyData), + .repeat = !!(lKeyData >> 30), .key_state = lpbKeyState, + }; LPINPUTCONTEXT lpIMC; BOOL inIME; + UINT ret;
TRACE("hIMC %p vKey 0x%04x lKeyData 0x%08Ix lpbKeyState %p\n", hIMC, vKey, lKeyData, lpbKeyState);
@@ -567,14 +555,17 @@ BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT vKey, LPARAM lKeyData, const LPBYTE lp ImmSetOpenStatus(RealIMC(FROM_MACDRV), FALSE); }
- myPrivate->repeat = (lKeyData >> 30) & 0x1; - myPrivate->bInternalState = inIME; ImmUnlockIMCC(lpIMC->hPrivate); } UnlockRealIMC(hIMC);
- return inIME; + if (!inIME) return FALSE; + + TRACE( "Processing Mac 0x%04x\n", vKey ); + ret = MACDRV_CALL( ime_process_text_input, ¶ms ); + + return ret != 0; }
BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) @@ -611,7 +602,6 @@ BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) myPrivate->bInternalState = FALSE; myPrivate->textfont = NULL; myPrivate->hwndDefault = NULL; - myPrivate->repeat = 0; ImmUnlockIMCC(lpIMC->hPrivate); UnlockRealIMC(hIMC); } @@ -622,13 +612,10 @@ BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) UINT WINAPI ImeToAsciiEx(UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState, TRANSMSGLIST *lpdwTransKey, UINT fuState, HIMC hIMC) { - struct process_text_input_params params; UINT vkey; LPINPUTCONTEXT lpIMC; LPIMEPRIVATE myPrivate; HWND hwnd; - UINT repeat; - UINT ret;
TRACE("uVKey 0x%04x uScanCode 0x%04x fuState %u hIMC %p\n", uVKey, uScanCode, fuState, hIMC);
@@ -650,41 +637,16 @@ UINT WINAPI ImeToAsciiEx(UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState, return 0; }
- repeat = myPrivate->repeat; ImmUnlockIMCC(lpIMC->hPrivate); UnlockRealIMC(hIMC);
- TRACE("Processing Mac 0x%04x\n", vkey); - params.himc = HandleToULong(hIMC); - params.vkey = uVKey; - params.scan = uScanCode; - params.repeat = repeat; - params.key_state = lpbKeyState; - ret = MACDRV_CALL(ime_process_text_input, ¶ms); - - if (!ret) - { - UINT msgs = 0; - UINT msg = (uScanCode & 0x8000) ? WM_KEYUP : WM_KEYDOWN; - - /* KeyStroke not processed by the IME - * so we need to rebuild the KeyDown message and pass it on to WINE - */ - if (!GenerateMessageToTransKey(lpdwTransKey, &msgs, msg, vkey, MAKELONG(0x0001, uScanCode))) - GenerateIMEMessage(hIMC, msg, vkey, MAKELONG(0x0001, uScanCode)); + /* trigger the pending client_func_ime_set_text call */ + MACDRV_CALL(ime_get_text_input, NULL);
- return msgs; - } - else + if ((lpIMC = LockRealIMC(hIMC))) { - /* trigger the pending client_func_ime_set_text call */ - MACDRV_CALL(ime_get_text_input, NULL); - - if ((lpIMC = LockRealIMC(hIMC))) - { - UpdateDataInDefaultIMEWindow( lpIMC, hwnd, FALSE ); - UnlockRealIMC(hIMC); - } + UpdateDataInDefaultIMEWindow( lpIMC, hwnd, FALSE ); + UnlockRealIMC(hIMC); } return 0; } diff --git a/include/ntuser.h b/include/ntuser.h index 5d352552a70..b165c9a8706 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -518,7 +518,6 @@ typedef struct ime_private BOOL bInternalState; HFONT textfont; HWND hwndDefault; - UINT repeat; } IMEPRIVATE, *LPIMEPRIVATE;
#define WM_SYSTIMER 0x0118
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/imm32/ime.c | 17 +++++++++++++---- dlls/win32u/driver.c | 12 ++++++++++++ dlls/win32u/imm.c | 2 ++ dlls/winex11.drv/ime.c | 7 ------- dlls/winex11.drv/winex11.drv.spec | 1 - include/ntuser.h | 1 + include/wine/gdi_driver.h | 1 + 7 files changed, 29 insertions(+), 12 deletions(-)
diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 300e5fe12cb..eb0fa5576f7 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -442,11 +442,20 @@ BOOL WINAPI ImeSetActiveContext( HIMC himc, BOOL flag ) return TRUE; }
-BOOL WINAPI ImeProcessKey( HIMC himc, UINT vkey, LPARAM key_data, BYTE *key_state ) +BOOL WINAPI ImeProcessKey( HIMC himc, UINT vkey, LPARAM lparam, BYTE *state ) { - FIXME( "himc %p, vkey %u, key_data %#Ix, key_state %p stub!\n", himc, vkey, key_data, key_state ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + struct ime_driver_call_params params = {.himc = himc, .state = state}; + INPUTCONTEXT *ctx; + LRESULT ret; + + TRACE( "himc %p, vkey %#x, lparam %#Ix, state %p\n", himc, vkey, lparam, state ); + + if (!(ctx = ImmLockIMC( himc ))) return FALSE; + ret = NtUserMessageCall( ctx->hWnd, WINE_IME_PROCESS_KEY, vkey, lparam, ¶ms, + NtUserImeDriverCall, FALSE ); + ImmUnlockIMC( himc ); + + return ret; }
UINT WINAPI ImeToAsciiEx( UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, UINT flags, HIMC himc ) diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 200c6cc78a2..0aac2f4b751 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -716,6 +716,11 @@ static SHORT nulldrv_VkKeyScanEx( WCHAR ch, HKL layout ) return -256; /* use default implementation */ }
+static UINT nulldrv_ImeProcessKey( HIMC himc, UINT wparam, UINT lparam, const BYTE *state ) +{ + return 0; +} + static UINT nulldrv_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc ) { return 0; @@ -1075,6 +1080,11 @@ static SHORT loaderdrv_VkKeyScanEx( WCHAR ch, HKL layout ) return load_driver()->pVkKeyScanEx( ch, layout ); }
+static UINT loaderdrv_ImeProcessKey( HIMC himc, UINT wparam, UINT lparam, const BYTE *state ) +{ + return load_driver()->pImeProcessKey( himc, wparam, lparam, state ); +} + static UINT loaderdrv_ImeToAsciiEx( UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc ) { return load_driver()->pImeToAsciiEx( vkey, vsc, state, compstr, himc ); @@ -1186,6 +1196,7 @@ static const struct user_driver_funcs lazy_load_driver = loaderdrv_ToUnicodeEx, loaderdrv_UnregisterHotKey, loaderdrv_VkKeyScanEx, + loaderdrv_ImeProcessKey, loaderdrv_ImeToAsciiEx, /* cursor/icon functions */ nulldrv_DestroyCursorIcon, @@ -1266,6 +1277,7 @@ void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version SET_USER_FUNC(ToUnicodeEx); SET_USER_FUNC(UnregisterHotKey); SET_USER_FUNC(VkKeyScanEx); + SET_USER_FUNC(ImeProcessKey); SET_USER_FUNC(ImeToAsciiEx); SET_USER_FUNC(DestroyCursorIcon); SET_USER_FUNC(SetCursor); diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c index 9090131d26c..b01a8518073 100644 --- a/dlls/win32u/imm.c +++ b/dlls/win32u/imm.c @@ -426,6 +426,8 @@ LRESULT ime_driver_call( HWND hwnd, enum wine_ime_call call, WPARAM wparam, LPAR { switch (call) { + case WINE_IME_PROCESS_KEY: + return user_driver->pImeProcessKey( params->himc, wparam, lparam, params->state ); case WINE_IME_TO_ASCII_EX: return user_driver->pImeToAsciiEx( wparam, lparam, params->state, params->compstr, params->himc ); default: diff --git a/dlls/winex11.drv/ime.c b/dlls/winex11.drv/ime.c index 91d9f085ff0..e663d48bbcb 100644 --- a/dlls/winex11.drv/ime.c +++ b/dlls/winex11.drv/ime.c @@ -477,13 +477,6 @@ static void IME_AddToSelected(HIMC hIMC) hSelectedFrom[hSelectedCount-1] = hIMC; }
-BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT vKey, LPARAM lKeyData, const LPBYTE lpbKeyState) -{ - /* See the comment at the head of this file */ - TRACE("We do no processing via this route\n"); - return FALSE; -} - BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) { LPINPUTCONTEXT lpIMC; diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec index 3f343da3dea..0074000bf1a 100644 --- a/dlls/winex11.drv/winex11.drv.spec +++ b/dlls/winex11.drv/winex11.drv.spec @@ -14,4 +14,3 @@ @ stdcall ImeSelect(long long) @ stdcall NotifyIME(long long long long) @ stdcall ImeSetCompositionString(long long ptr long ptr long) -@ stdcall ImeProcessKey(long long long ptr) diff --git a/include/ntuser.h b/include/ntuser.h index b165c9a8706..17ff0757205 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -500,6 +500,7 @@ enum wine_internal_message /* builtin IME driver calls */ enum wine_ime_call { + WINE_IME_PROCESS_KEY, WINE_IME_TO_ASCII_EX, };
diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 3ffc28dc15a..0ee5024094c 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -289,6 +289,7 @@ struct user_driver_funcs void (*pUnregisterHotKey)(HWND, UINT, UINT); SHORT (*pVkKeyScanEx)(WCHAR, HKL); /* IME functions */ + UINT (*pImeProcessKey)(HIMC,UINT,UINT,const BYTE*); UINT (*pImeToAsciiEx)(UINT,UINT,const BYTE*,COMPOSITIONSTRING*,HIMC); /* cursor/icon functions */ void (*pDestroyCursorIcon)(HCURSOR);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/gdi.c | 1 + dlls/winemac.drv/ime.c | 78 +------------------------------ dlls/winemac.drv/keyboard.c | 29 ++++++++---- dlls/winemac.drv/macdrv.h | 2 +- dlls/winemac.drv/macdrv_main.c | 30 ------------ dlls/winemac.drv/unixlib.h | 12 ----- dlls/winemac.drv/winemac.drv.spec | 1 - 7 files changed, 22 insertions(+), 131 deletions(-)
diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c index d22532fd3b7..e8c35ec6ef8 100644 --- a/dlls/winemac.drv/gdi.c +++ b/dlls/winemac.drv/gdi.c @@ -302,6 +302,7 @@ static const struct user_driver_funcs macdrv_funcs = .pUpdateClipboard = macdrv_UpdateClipboard, .pUpdateLayeredWindow = macdrv_UpdateLayeredWindow, .pVkKeyScanEx = macdrv_VkKeyScanEx, + .pImeProcessKey = macdrv_ImeProcessKey, .pWindowMessage = macdrv_WindowMessage, .pWindowPosChanged = macdrv_WindowPosChanged, .pWindowPosChanging = macdrv_WindowPosChanging, diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c index 1914940f242..bb308a7c9e8 100644 --- a/dlls/winemac.drv/ime.c +++ b/dlls/winemac.drv/ime.c @@ -515,59 +515,6 @@ static void UpdateDataInDefaultIMEWindow(INPUTCONTEXT *lpIMC, HWND hwnd, BOOL sh ImmUnlockIMCC(lpIMC->hCompStr); }
-BOOL WINAPI ImeProcessKey(HIMC hIMC, UINT vKey, LPARAM lKeyData, const LPBYTE lpbKeyState) -{ - struct process_text_input_params params = - { - .himc = (UINT_PTR)hIMC, .vkey = LOWORD(vKey), .scan = HIWORD(lKeyData), - .repeat = !!(lKeyData >> 30), .key_state = lpbKeyState, - }; - LPINPUTCONTEXT lpIMC; - BOOL inIME; - UINT ret; - - TRACE("hIMC %p vKey 0x%04x lKeyData 0x%08Ix lpbKeyState %p\n", hIMC, vKey, lKeyData, lpbKeyState); - - switch (vKey) - { - case VK_SHIFT: - case VK_CONTROL: - case VK_CAPITAL: - case VK_MENU: - return FALSE; - } - - inIME = MACDRV_CALL(ime_using_input_method, NULL); - lpIMC = LockRealIMC(hIMC); - if (lpIMC) - { - LPIMEPRIVATE myPrivate; - HWND hwnd = input_context_get_ui_hwnd( lpIMC ); - myPrivate = ImmLockIMCC(lpIMC->hPrivate); - - if (inIME && !myPrivate->bInternalState) - ImmSetOpenStatus(RealIMC(FROM_MACDRV), TRUE); - else if (!inIME && myPrivate->bInternalState) - { - ShowWindow( hwnd, SW_HIDE ); - ImmDestroyIMCC(lpIMC->hCompStr); - lpIMC->hCompStr = ImeCreateBlankCompStr(); - ImmSetOpenStatus(RealIMC(FROM_MACDRV), FALSE); - } - - myPrivate->bInternalState = inIME; - ImmUnlockIMCC(lpIMC->hPrivate); - } - UnlockRealIMC(hIMC); - - if (!inIME) return FALSE; - - TRACE( "Processing Mac 0x%04x\n", vKey ); - ret = MACDRV_CALL( ime_process_text_input, ¶ms ); - - return ret != 0; -} - BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) { LPINPUTCONTEXT lpIMC; @@ -612,39 +559,16 @@ BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) UINT WINAPI ImeToAsciiEx(UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState, TRANSMSGLIST *lpdwTransKey, UINT fuState, HIMC hIMC) { - UINT vkey; LPINPUTCONTEXT lpIMC; - LPIMEPRIVATE myPrivate; - HWND hwnd;
TRACE("uVKey 0x%04x uScanCode 0x%04x fuState %u hIMC %p\n", uVKey, uScanCode, fuState, hIMC);
- vkey = LOWORD(uVKey); - - if (vkey == VK_KANA || vkey == VK_KANJI || vkey == VK_MENU) - { - TRACE("Skipping metakey\n"); - return 0; - } - - lpIMC = LockRealIMC(hIMC); - hwnd = input_context_get_ui_hwnd( lpIMC ); - myPrivate = ImmLockIMCC(lpIMC->hPrivate); - if (!myPrivate->bInternalState) - { - ImmUnlockIMCC(lpIMC->hPrivate); - UnlockRealIMC(hIMC); - return 0; - } - - ImmUnlockIMCC(lpIMC->hPrivate); - UnlockRealIMC(hIMC); - /* trigger the pending client_func_ime_set_text call */ MACDRV_CALL(ime_get_text_input, NULL);
if ((lpIMC = LockRealIMC(hIMC))) { + HWND hwnd = input_context_get_ui_hwnd( lpIMC ); UpdateDataInDefaultIMEWindow( lpIMC, hwnd, FALSE ); UnlockRealIMC(hIMC); } diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c index 17abbedb230..c1963daa56e 100644 --- a/dlls/winemac.drv/keyboard.c +++ b/dlls/winemac.drv/keyboard.c @@ -1188,19 +1188,29 @@ void macdrv_hotkey_press(const macdrv_event *event)
/*********************************************************************** - * macdrv_process_text_input + * ImeProcessKey (MACDRV.@) */ -NTSTATUS macdrv_ime_process_text_input(void *arg) +UINT macdrv_ImeProcessKey(HIMC himc, UINT wparam, UINT lparam, const BYTE *key_state) { - struct process_text_input_params *params = arg; struct macdrv_thread_data *thread_data = macdrv_thread_data(); - void *himc = UlongToHandle(params->himc); - const BYTE *key_state = params->key_state; + WORD scan = HIWORD(lparam) & 0x1ff, vkey = LOWORD(wparam); + BOOL repeat = !!(lparam >> 30), pressed = !(lparam >> 31); unsigned int flags; int keyc, done = 0;
- TRACE("vkey 0x%04x scan 0x%04x repeat %u himc %p\n", params->vkey, params->scan, - params->repeat, himc); + TRACE("himc %p, scan %#x, vkey %#x, repeat %u, pressed %u\n", + himc, scan, vkey, repeat, pressed); + + if (!macdrv_using_input_method()) return 0; + + switch (vkey) + { + case VK_SHIFT: + case VK_CONTROL: + case VK_CAPITAL: + case VK_MENU: + return 0; + }
flags = thread_data->last_modifiers; if (key_state[VK_SHIFT] & 0x80) @@ -1222,14 +1232,13 @@ NTSTATUS macdrv_ime_process_text_input(void *arg)
/* Find the Mac keycode corresponding to the scan code */ for (keyc = 0; keyc < ARRAY_SIZE(thread_data->keyc2vkey); keyc++) - if (thread_data->keyc2vkey[keyc] == params->vkey) break; + if (thread_data->keyc2vkey[keyc] == vkey) break;
if (keyc >= ARRAY_SIZE(thread_data->keyc2vkey)) return 0;
TRACE("flags 0x%08x keyc 0x%04x\n", flags, keyc);
- macdrv_send_text_input_event(((params->scan & 0x8000) == 0), flags, params->repeat, keyc, - himc, &done); + macdrv_send_text_input_event(pressed, flags, repeat, keyc, himc, &done); while (!done) NtUserMsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_POSTMESSAGE | QS_SENDMESSAGE, 0);
return done > 0; diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index b77e62f75db..15ea44dadcf 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -162,6 +162,7 @@ extern BOOL macdrv_SetCursorPos(INT x, INT y) DECLSPEC_HIDDEN; extern BOOL macdrv_RegisterHotKey(HWND hwnd, UINT mod_flags, UINT vkey) DECLSPEC_HIDDEN; extern void macdrv_UnregisterHotKey(HWND hwnd, UINT modifiers, UINT vkey) DECLSPEC_HIDDEN; extern SHORT macdrv_VkKeyScanEx(WCHAR wChar, HKL hkl) DECLSPEC_HIDDEN; +extern UINT macdrv_ImeProcessKey(HIMC himc, UINT wparam, UINT lparam, const BYTE *state) DECLSPEC_HIDDEN; extern UINT macdrv_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl) DECLSPEC_HIDDEN; extern INT macdrv_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState, LPWSTR bufW, int bufW_size, UINT flags, HKL hkl) DECLSPEC_HIDDEN; @@ -276,7 +277,6 @@ extern NTSTATUS macdrv_dnd_get_formats(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_have_format(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_release(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_retain(void *arg) DECLSPEC_HIDDEN; -extern NTSTATUS macdrv_ime_process_text_input(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_ime_get_text_input(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_notify_icon(void *arg) DECLSPEC_HIDDEN;
diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index 7e91e0ca3e1..df7fe0ea1bc 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -612,12 +612,6 @@ static NTSTATUS macdrv_ime_clear(void *arg) }
-static NTSTATUS macdrv_ime_using_input_method(void *arg) -{ - return macdrv_using_input_method(); -} - - static NTSTATUS macdrv_quit_result(void *arg) { struct quit_result_params *params = arg; @@ -634,9 +628,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = macdrv_dnd_release, macdrv_dnd_retain, macdrv_ime_clear, - macdrv_ime_process_text_input, macdrv_ime_get_text_input, - macdrv_ime_using_input_method, macdrv_init, macdrv_notify_icon, macdrv_quit_result, @@ -664,26 +656,6 @@ static NTSTATUS wow64_dnd_get_data(void *arg) return macdrv_dnd_get_data(¶ms); }
-static NTSTATUS wow64_ime_process_text_input(void *arg) -{ - struct - { - UINT himc; - UINT vkey; - UINT scan; - UINT repeat; - ULONG key_state; - } *params32 = arg; - struct process_text_input_params params; - - params.himc = params32->himc; - params.vkey = params32->vkey; - params.scan = params32->scan; - params.repeat = params32->repeat; - params.key_state = UlongToPtr(params32->key_state); - return macdrv_ime_process_text_input(¶ms); -} - static NTSTATUS wow64_init(void *arg) { struct @@ -759,9 +731,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = macdrv_dnd_release, macdrv_dnd_retain, macdrv_ime_clear, - wow64_ime_process_text_input, macdrv_ime_get_text_input, - macdrv_ime_using_input_method, wow64_init, wow64_notify_icon, macdrv_quit_result, diff --git a/dlls/winemac.drv/unixlib.h b/dlls/winemac.drv/unixlib.h index 493e4f6c139..3350ed5cc60 100644 --- a/dlls/winemac.drv/unixlib.h +++ b/dlls/winemac.drv/unixlib.h @@ -27,9 +27,7 @@ enum macdrv_funcs unix_dnd_release, unix_dnd_retain, unix_ime_clear, - unix_ime_process_text_input, unix_ime_get_text_input, - unix_ime_using_input_method, unix_init, unix_notify_icon, unix_quit_result, @@ -61,16 +59,6 @@ struct dnd_have_format_params UINT format; };
-/* macdrv_ime_process_text_input params */ -struct process_text_input_params -{ - UINT himc; - UINT vkey; - UINT scan; - UINT repeat; - const BYTE *key_state; -}; - /* macdrv_init params */ struct localized_string { diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec index debaec8239d..7c2ef82631d 100644 --- a/dlls/winemac.drv/winemac.drv.spec +++ b/dlls/winemac.drv/winemac.drv.spec @@ -2,7 +2,6 @@ @ cdecl wine_notify_icon(long ptr)
# IME -@ stdcall ImeProcessKey(long long long ptr) @ stdcall ImeSelect(long long) @ stdcall ImeSetCompositionString(long long ptr long ptr long) @ stdcall ImeToAsciiEx(long long ptr ptr long long)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/dllmain.c | 1 - dlls/winemac.drv/event.c | 137 ++++++++++++++++++++++-------- dlls/winemac.drv/gdi.c | 1 + dlls/winemac.drv/ime.c | 88 ------------------- dlls/winemac.drv/macdrv.h | 5 +- dlls/winemac.drv/macdrv_dll.h | 1 - dlls/winemac.drv/macdrv_main.c | 2 - dlls/winemac.drv/unixlib.h | 12 --- dlls/winemac.drv/winemac.drv.spec | 1 - 9 files changed, 107 insertions(+), 141 deletions(-)
diff --git a/dlls/winemac.drv/dllmain.c b/dlls/winemac.drv/dllmain.c index 41e9e908b61..265d6e46d5c 100644 --- a/dlls/winemac.drv/dllmain.c +++ b/dlls/winemac.drv/dllmain.c @@ -375,7 +375,6 @@ static const kernel_callback kernel_callbacks[] = macdrv_dnd_query_drop, macdrv_dnd_query_exited, macdrv_ime_query_char_rect, - macdrv_ime_set_text, };
C_ASSERT(NtUserDriverCallbackFirst + ARRAYSIZE(kernel_callbacks) == client_func_last); diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c index cc8aa4681c6..498addf785a 100644 --- a/dlls/winemac.drv/event.c +++ b/dlls/winemac.drv/event.c @@ -32,12 +32,21 @@ WINE_DEFAULT_DEBUG_CHANNEL(event); WINE_DECLARE_DEBUG_CHANNEL(imm);
+/* IME works synchronously, key input is passed from ImeProcessKey, to the + * host IME. We wait for it to be handled, or not, which is notified using + * the sent_text_input event. Meanwhile, while processing the key, the host + * IME may send one or more im_set_text events to update the input text. + * + * If ImeProcessKey returns TRUE, ImeToAsciiEx will then be called to retrieve + * the composition string updates. + * + * If ImeProcessKey returns FALSE, ImeToAsciiEx will not be called. + */ struct ime_update { - struct ime_set_text_params *comp_params; - DWORD comp_size; - struct ime_set_text_params *result_params; - DWORD result_size; + DWORD cursor_pos; + WCHAR *comp_str; + WCHAR *result_str; }; static struct ime_update ime_update;
@@ -159,38 +168,34 @@ static macdrv_event_mask get_event_mask(DWORD mask) static void macdrv_im_set_text(const macdrv_event *event) { HWND hwnd = macdrv_get_window_hwnd(event->window); - struct ime_set_text_params *params; - CFIndex length = 0, size; + CFIndex length = 0; + WCHAR *text = NULL;
TRACE_(imm)("win %p/%p himc %p text %s complete %u\n", hwnd, event->window, event->im_set_text.himc, debugstr_cf(event->im_set_text.text), event->im_set_text.complete);
if (event->im_set_text.text) + { length = CFStringGetLength(event->im_set_text.text); + if (!(text = malloc((length + 1) * sizeof(WCHAR)))) return; + if (length) CFStringGetCharacters(event->im_set_text.text, CFRangeMake(0, length), text); + text[length] = 0; + }
- size = offsetof(struct ime_set_text_params, text[length]); - if (!(params = malloc(size))) return; - params->hwnd = HandleToUlong(hwnd); - params->himc = (UINT_PTR)event->im_set_text.himc; - params->cursor_pos = event->im_set_text.cursor_pos; - params->complete = event->im_set_text.complete; - - if (length) - CFStringGetCharacters(event->im_set_text.text, CFRangeMake(0, length), params->text); - - free(ime_update.comp_params); - ime_update.comp_params = NULL; + /* discard any pending comp text */ + free(ime_update.comp_str); + ime_update.comp_str = NULL; + ime_update.cursor_pos = -1;
- if (params->complete) + if (event->im_set_text.complete) { - free(ime_update.result_params); - ime_update.result_params = params; - ime_update.result_size = size; + free(ime_update.result_str); + ime_update.result_str = text; } else { - ime_update.comp_params = params; - ime_update.comp_size = size; + ime_update.comp_str = text; + ime_update.cursor_pos = event->im_set_text.cursor_pos; } }
@@ -200,28 +205,90 @@ static void macdrv_im_set_text(const macdrv_event *event) static void macdrv_sent_text_input(const macdrv_event *event) { TRACE_(imm)("handled: %s\n", event->sent_text_input.handled ? "TRUE" : "FALSE"); - *event->sent_text_input.done = event->sent_text_input.handled || ime_update.result_params ? 1 : -1; + *event->sent_text_input.done = event->sent_text_input.handled || ime_update.result_str ? 1 : -1; }
/*********************************************************************** - * macdrv_ime_get_text_input + * ImeToAsciiEx (MACDRV.@) */ -NTSTATUS macdrv_ime_get_text_input(void *arg) +UINT macdrv_ImeToAsciiEx(UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc) { - if (ime_update.result_params) + UINT needed = sizeof(COMPOSITIONSTRING), comp_len, result_len; + struct ime_update *update = &ime_update; + void *dst; + + TRACE_(imm)("vkey %#x, vsc %#x, state %p, compstr %p, himc %p\n", vkey, vsc, state, compstr, himc); + + if (!update->comp_str) comp_len = 0; + else + { + comp_len = wcslen(update->comp_str); + needed += comp_len * sizeof(WCHAR); /* GCS_COMPSTR */ + needed += comp_len; /* GCS_COMPATTR */ + needed += 2 * sizeof(DWORD); /* GCS_COMPCLAUSE */ + } + + if (!update->result_str) result_len = 0; + else + { + result_len = wcslen(update->result_str); + needed += result_len * sizeof(WCHAR); /* GCS_RESULTSTR */ + needed += 2 * sizeof(DWORD); /* GCS_RESULTCLAUSE */ + } + + if (compstr->dwSize < needed) { - macdrv_client_func(client_func_ime_set_text, ime_update.result_params, ime_update.result_size); - free(ime_update.result_params); - ime_update.result_params = NULL; + compstr->dwSize = needed; + return STATUS_BUFFER_TOO_SMALL; } - if (ime_update.comp_params) + + memset( compstr, 0, sizeof(*compstr) ); + compstr->dwSize = sizeof(*compstr); + + if (update->comp_str) + { + compstr->dwCursorPos = update->cursor_pos; + compstr->dwDeltaStart = 0; + + compstr->dwCompStrLen = comp_len; + compstr->dwCompStrOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwCompStrOffset; + memcpy(dst, update->comp_str, compstr->dwCompStrLen * sizeof(WCHAR)); + compstr->dwSize += compstr->dwCompStrLen * sizeof(WCHAR); + + compstr->dwCompClauseLen = 2 * sizeof(DWORD); + compstr->dwCompClauseOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwCompClauseOffset; + *((DWORD *)dst + 0) = 0; + *((DWORD *)dst + 1) = compstr->dwCompStrLen; + compstr->dwSize += compstr->dwCompClauseLen; + + compstr->dwCompAttrLen = compstr->dwCompStrLen; + compstr->dwCompAttrOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwCompAttrOffset; + memset(dst, ATTR_INPUT, compstr->dwCompAttrLen); + compstr->dwSize += compstr->dwCompAttrLen; + } + + if (update->result_str) { - macdrv_client_func(client_func_ime_set_text, ime_update.comp_params, ime_update.comp_size); - free(ime_update.comp_params); - ime_update.comp_params = NULL; + compstr->dwResultStrLen = result_len; + compstr->dwResultStrOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwResultStrOffset; + memcpy(dst, update->result_str, compstr->dwResultStrLen * sizeof(WCHAR)); + compstr->dwSize += compstr->dwResultStrLen * sizeof(WCHAR); + + compstr->dwResultClauseLen = 2 * sizeof(DWORD); + compstr->dwResultClauseOffset = compstr->dwSize; + dst = (BYTE *)compstr + compstr->dwResultClauseOffset; + *((DWORD *)dst + 0) = 0; + *((DWORD *)dst + 1) = compstr->dwResultStrLen; + compstr->dwSize += compstr->dwResultClauseLen; }
+ free(update->result_str); + update->result_str = NULL; return 0; }
diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c index e8c35ec6ef8..bea683b77df 100644 --- a/dlls/winemac.drv/gdi.c +++ b/dlls/winemac.drv/gdi.c @@ -303,6 +303,7 @@ static const struct user_driver_funcs macdrv_funcs = .pUpdateLayeredWindow = macdrv_UpdateLayeredWindow, .pVkKeyScanEx = macdrv_VkKeyScanEx, .pImeProcessKey = macdrv_ImeProcessKey, + .pImeToAsciiEx = macdrv_ImeToAsciiEx, .pWindowMessage = macdrv_WindowMessage, .pWindowPosChanged = macdrv_WindowPosChanged, .pWindowPosChanging = macdrv_WindowPosChanging, diff --git a/dlls/winemac.drv/ime.c b/dlls/winemac.drv/ime.c index bb308a7c9e8..1121c490d1a 100644 --- a/dlls/winemac.drv/ime.c +++ b/dlls/winemac.drv/ime.c @@ -495,26 +495,6 @@ static void IME_AddToSelected(HIMC hIMC) hSelectedFrom[hSelectedCount - 1] = hIMC; }
-static void UpdateDataInDefaultIMEWindow(INPUTCONTEXT *lpIMC, HWND hwnd, BOOL showable) -{ - LPCOMPOSITIONSTRING compstr; - - if (lpIMC->hCompStr) - compstr = ImmLockIMCC(lpIMC->hCompStr); - else - compstr = NULL; - - if (compstr == NULL || compstr->dwCompStrLen == 0) - ShowWindow(hwnd, SW_HIDE); - else if (showable) - ShowWindow(hwnd, SW_SHOWNOACTIVATE); - - RedrawWindow(hwnd, NULL, NULL, RDW_ERASENOW | RDW_INVALIDATE); - - if (compstr != NULL) - ImmUnlockIMCC(lpIMC->hCompStr); -} - BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) { LPINPUTCONTEXT lpIMC; @@ -556,25 +536,6 @@ BOOL WINAPI ImeSelect(HIMC hIMC, BOOL fSelect) return TRUE; }
-UINT WINAPI ImeToAsciiEx(UINT uVKey, UINT uScanCode, const LPBYTE lpbKeyState, - TRANSMSGLIST *lpdwTransKey, UINT fuState, HIMC hIMC) -{ - LPINPUTCONTEXT lpIMC; - - TRACE("uVKey 0x%04x uScanCode 0x%04x fuState %u hIMC %p\n", uVKey, uScanCode, fuState, hIMC); - - /* trigger the pending client_func_ime_set_text call */ - MACDRV_CALL(ime_get_text_input, NULL); - - if ((lpIMC = LockRealIMC(hIMC))) - { - HWND hwnd = input_context_get_ui_hwnd( lpIMC ); - UpdateDataInDefaultIMEWindow( lpIMC, hwnd, FALSE ); - UnlockRealIMC(hIMC); - } - return 0; -} - BOOL WINAPI NotifyIME(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue) { BOOL bRet = FALSE; @@ -812,57 +773,8 @@ BOOL WINAPI ImeSetCompositionString(HIMC hIMC, DWORD dwIndex, LPCVOID lpComp, DW return IME_SetCompositionString(hIMC, dwIndex, lpComp, dwCompLen, 0, FALSE); }
-static void IME_NotifyComplete(void* hIMC) -{ - NotifyIME(hIMC, NI_COMPOSITIONSTR, CPS_COMPLETE, 0); -} - /* Interfaces to other parts of the Mac driver */
-/*********************************************************************** - * macdrv_ime_set_text - */ -NTSTATUS WINAPI macdrv_ime_set_text(void *arg, ULONG size) -{ - struct ime_set_text_params *params = arg; - ULONG length = (size - offsetof(struct ime_set_text_params, text)) / sizeof(WCHAR); - void *himc = param_ptr(params->himc); - HWND hwnd = UlongToHandle(params->hwnd); - - if (!himc) himc = RealIMC(FROM_MACDRV); - - if (length) - { - if (himc) - IME_SetCompositionString(himc, SCS_SETSTR, params->text, length * sizeof(WCHAR), - params->cursor_pos, !params->complete); - else - { - INPUT input; - unsigned int i; - - input.type = INPUT_KEYBOARD; - input.ki.wVk = 0; - input.ki.time = 0; - input.ki.dwExtraInfo = 0; - - for (i = 0; i < length; i++) - { - input.ki.wScan = params->text[i]; - input.ki.dwFlags = KEYEVENTF_UNICODE; - __wine_send_input(hwnd, &input, NULL); - - input.ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP; - __wine_send_input(hwnd, &input, NULL); - } - } - } - - if (params->complete) - IME_NotifyComplete(himc); - return 0; -} - /************************************************************************** * macdrv_ime_query_char_rect */ diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 15ea44dadcf..7c638a44ff2 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -28,6 +28,9 @@ #endif
#include "macdrv_cocoa.h" + +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" #include "ntgdi.h" @@ -163,6 +166,7 @@ extern BOOL macdrv_RegisterHotKey(HWND hwnd, UINT mod_flags, UINT vkey) DECLSPEC extern void macdrv_UnregisterHotKey(HWND hwnd, UINT modifiers, UINT vkey) DECLSPEC_HIDDEN; extern SHORT macdrv_VkKeyScanEx(WCHAR wChar, HKL hkl) DECLSPEC_HIDDEN; extern UINT macdrv_ImeProcessKey(HIMC himc, UINT wparam, UINT lparam, const BYTE *state) DECLSPEC_HIDDEN; +extern UINT macdrv_ImeToAsciiEx(UINT vkey, UINT vsc, const BYTE *state, COMPOSITIONSTRING *compstr, HIMC himc) DECLSPEC_HIDDEN; extern UINT macdrv_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl) DECLSPEC_HIDDEN; extern INT macdrv_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState, LPWSTR bufW, int bufW_size, UINT flags, HKL hkl) DECLSPEC_HIDDEN; @@ -277,7 +281,6 @@ extern NTSTATUS macdrv_dnd_get_formats(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_have_format(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_release(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_dnd_retain(void *arg) DECLSPEC_HIDDEN; -extern NTSTATUS macdrv_ime_get_text_input(void *arg) DECLSPEC_HIDDEN; extern NTSTATUS macdrv_notify_icon(void *arg) DECLSPEC_HIDDEN;
extern NTSTATUS macdrv_client_func(enum macdrv_client_funcs func, const void *params, diff --git a/dlls/winemac.drv/macdrv_dll.h b/dlls/winemac.drv/macdrv_dll.h index 3a11528eabc..8f13b6b69aa 100644 --- a/dlls/winemac.drv/macdrv_dll.h +++ b/dlls/winemac.drv/macdrv_dll.h @@ -31,7 +31,6 @@ extern NTSTATUS WINAPI macdrv_dnd_query_drag(void *arg, ULONG size) DECLSPEC_HID extern NTSTATUS WINAPI macdrv_dnd_query_drop(void *arg, ULONG size) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI macdrv_dnd_query_exited(void *arg, ULONG size) DECLSPEC_HIDDEN;
-extern NTSTATUS WINAPI macdrv_ime_set_text(void *params, ULONG size) DECLSPEC_HIDDEN; extern NTSTATUS WINAPI macdrv_ime_query_char_rect(void *params, ULONG size) DECLSPEC_HIDDEN;
extern HMODULE macdrv_module DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/macdrv_main.c b/dlls/winemac.drv/macdrv_main.c index df7fe0ea1bc..944497c2371 100644 --- a/dlls/winemac.drv/macdrv_main.c +++ b/dlls/winemac.drv/macdrv_main.c @@ -628,7 +628,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] = macdrv_dnd_release, macdrv_dnd_retain, macdrv_ime_clear, - macdrv_ime_get_text_input, macdrv_init, macdrv_notify_icon, macdrv_quit_result, @@ -731,7 +730,6 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = macdrv_dnd_release, macdrv_dnd_retain, macdrv_ime_clear, - macdrv_ime_get_text_input, wow64_init, wow64_notify_icon, macdrv_quit_result, diff --git a/dlls/winemac.drv/unixlib.h b/dlls/winemac.drv/unixlib.h index 3350ed5cc60..1afddc42614 100644 --- a/dlls/winemac.drv/unixlib.h +++ b/dlls/winemac.drv/unixlib.h @@ -27,7 +27,6 @@ enum macdrv_funcs unix_dnd_release, unix_dnd_retain, unix_ime_clear, - unix_ime_get_text_input, unix_init, unix_notify_icon, unix_quit_result, @@ -94,7 +93,6 @@ enum macdrv_client_funcs client_func_dnd_query_drop, client_func_dnd_query_exited, client_func_ime_query_char_rect, - client_func_ime_set_text, client_func_last };
@@ -170,16 +168,6 @@ struct ime_query_char_rect_params UINT32 length; };
-/* macdrv_ime_set_text params */ -struct ime_set_text_params -{ - UINT32 hwnd; - UINT32 cursor_pos; - UINT32 himc; - UINT32 complete; - WCHAR text[1]; -}; - static inline void *param_ptr(UINT64 param) { return (void *)(UINT_PTR)param; diff --git a/dlls/winemac.drv/winemac.drv.spec b/dlls/winemac.drv/winemac.drv.spec index 7c2ef82631d..bd441b7d69b 100644 --- a/dlls/winemac.drv/winemac.drv.spec +++ b/dlls/winemac.drv/winemac.drv.spec @@ -4,5 +4,4 @@ # IME @ stdcall ImeSelect(long long) @ stdcall ImeSetCompositionString(long long ptr long ptr long) -@ stdcall ImeToAsciiEx(long long ptr ptr long long) @ stdcall NotifyIME(long long long long)
This now uses a similar mechanism as is used by native MSCTF, and exposed in https://gitlab.winehq.org/wine/wine/-/merge_requests/2749, with WM_IME_NOTIFY private messages.
For the asynchronous mode, used in winex11, WM_IME_NOTIFY / IMN_WINE_SET_COMP_STRING messages are sent, with a lparam cookie. To keep the implementations close between synchronous and asynchronous mode, this triggers calls to ImeToAsciiEx, in the same way ImmTranslateMessage does in the synchronous mode, and it then sends the generated IME messages to the window instead of posting them. In this asynchronous mode, the cookie is passed in the composition string private area where the user driver will find it.
For winex11, the cookie is a pointer to an ime_update structure, containing pointers to the last composition string and result strings. As we're sending messages, it works synchronously and it can live on the kernel stack for now, but I think we might want to make this more asynchronous in the future and dynamically allocate the updates. This would cause leaks if the messages aren't processed though.
I'm adding winemac changes as well to show that it works there as well in a synchronous mode.
There are some minor issues in v7, and some interesting good stuffs. But before we talk about that, I have one question.
Is it not allowed to access "win32u/imm.c::imc->client_ptr" from the UNIX side?
I tried writing a POC patchset. But it's such a simple concept that I'm wondering if there's something I'm missing.
[poc_use_imc_client_ptr.patch](/uploads/1698909b42ab8fbad97976c1b4f8b042/poc_use_imc_client_ptr.patch)
On Mon May 8 07:48:55 2023 +0000, Byeongsik Jeon wrote:
There are some minor issues in v7, and some interesting good stuffs. But before we talk about that, I have one question. Is it not allowed to access "win32u/imm.c::imc->client_ptr" from the UNIX side? I tried writing a POC patchset. But it's such a simple concept that I'm wondering if there's something I'm missing. [poc_use_imc_client_ptr.patch](/uploads/1698909b42ab8fbad97976c1b4f8b042/poc_use_imc_client_ptr.patch)
You can access it, probably, but then some members such as the composition string is behind a pseudo handle, which require callbacks to access. In general we want as little callbacks as possible, and here probably, do as much as possible in imm32.
There is also the fact that I'm trying to move XIM handling, and input in general, to a separate "rawinput" thread, which will fix several long standing bugs and design issues, as well as let us implement more HID features such as touch input, in user32.
If the thread sending the updates isn't the same as the one owning the input context, you cannot safely access the input context members anymore, because it isn't synchronized with the owning thread which may be reading, or destroying them at the same time.
On Mon May 8 07:51:41 2023 +0000, Rémi Bernon wrote:
This now uses a similar mechanism as is used by native MSCTF, and exposed in https://gitlab.winehq.org/wine/wine/-/merge_requests/2749, with WM_IME_NOTIFY private messages. For the asynchronous mode, used in winex11, WM_IME_NOTIFY / IMN_WINE_SET_COMP_STRING messages are sent, with a lparam cookie. To keep the implementations close between synchronous and asynchronous mode, this triggers calls to ImeToAsciiEx, in the same way ImmTranslateMessage does in the synchronous mode, and it then sends the generated IME messages to the window instead of posting them. In this asynchronous mode, the cookie is passed in the composition string private area where the user driver will find it. For winex11, the cookie is a pointer to an ime_update structure, containing pointers to the last composition string and result strings. As we're sending messages, it works synchronously and it can live on the kernel stack for now, but I think we might want to make this more asynchronous in the future and dynamically allocate the updates. This would cause leaks if the messages aren't processed though. I'm adding winemac changes as well to show that it works there as well in a synchronous mode.
I realize now that using LPARAM as a pointer isn't safe on WOW64, as it's truncated as soon at it reaches a 32-bit side. I'll make this differently, using pseudo handles and keeping the updates in a list.
You can access it, probably, but then some members such as the composition string is behind a pseudo handle, which require callbacks to access. In general we want as little callbacks as possible, and here probably, do as much as possible in imm32.
Yes, KeUserModeCallback used. I think it can be implemented in win32u, probably using NtAllocateVirtualMemory.
There is also the fact that I'm trying to move XIM handling, and input in general, to a separate "rawinput" thread, which will fix several long standing bugs and design issues, as well as let us implement more HID features such as touch input, in user32.
If the thread sending the updates isn't the same as the one owning the input context, you cannot safely access the input context members anymore, because it isn't synchronized with the owning thread which may be reading, or destroying them at the same time.
Thanks for the answer.
I think imm32/ime.c should be designed as the common code for the Wine builtin ime infrastructure. Each sub-IME can be either an "in-thread" or "separate-thread" implementation.
In my opinion, you are applying a "separate-thread" implementation to "in-thread" code too early.
I would suggest separating the steps.
First, move the code to consider only the current implementation, "in-thread". If we implement the HIMCC related functions on the UNIX side and use client_ptr, the data copying issue will be eliminated.
Later, extend imm32/ime.c when implementing "separate thread" ime.
I know it's a presumptuous opinion. Just an opinion.
MS IME has a feature called ImePad. It looks similar to v7 except that it uses the default IME window procedure directly.
I'm attaching a SPY++ test screen. I cleaned it up a bit in the application window procedure to make it easier to tell where the messages are coming from. ``` if (ImmIsUIMessageW( 0, msg, wparam, lparam )) return 0; else return DefWindowProc( hwnd, msg, wparam, lparam ); ``` ![jp_ime_pad](/uploads/7652ce621f7c7e6bf6df81e888abc4c8/jp_ime_pad.png)