[PATCH v4 0/4] MR9992: Winemac IME rework part 1
-- v4: winemac: Implement and use macdrv_ImeToAsciiEx(). win32: Generate a WM_KEYDOWN message for unconsumed keys. imm32: Pass keyboard state into ImeToAsciiEx(). win32u: Introduce a new ImeToAsciiEx call through NtUserMessageCall. https://gitlab.winehq.org/wine/wine/-/merge_requests/9992
From: Marc-Aurel Zent <mzent@codeweavers.com> --- dlls/imm32/ime.c | 1 + dlls/win32u/driver.c | 12 ++++++++++++ dlls/win32u/imm.c | 1 + include/ntuser.h | 1 + include/wine/gdi_driver.h | 1 + 5 files changed, 16 insertions(+) diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 65f46f20550..ed3f262c47a 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -551,6 +551,7 @@ UINT WINAPI ImeToAsciiEx( UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, params.compstr = compstr; params.key_consumed = &key_consumed; + params.msgs = msgs; status = NtUserMessageCall( ctx->hWnd, WINE_IME_TO_ASCII_EX, vkey, vsc, ¶ms, NtUserImeDriverCall, FALSE ); size = compstr->dwSize; diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 60aba702d1a..9664c355fc2 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -676,6 +676,11 @@ static UINT nulldrv_ImeProcessKey( HIMC himc, UINT wparam, UINT lparam, const BY return 0; } +static UINT nulldrv_ImeToAsciiEx( UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, UINT flags, HIMC himc ) +{ + return 0; +} + static void nulldrv_NotifyIMEStatus( HWND hwnd, UINT status ) { } @@ -1103,6 +1108,11 @@ static UINT loaderdrv_ImeProcessKey( HIMC himc, UINT wparam, UINT lparam, const return load_driver()->pImeProcessKey( himc, wparam, lparam, state ); } +static UINT loaderdrv_ImeToAsciiEx( UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, UINT flags, HIMC himc ) +{ + return load_driver()->pImeToAsciiEx( vkey, vsc, state, msgs, flags, himc ); +} + static void loaderdrv_NotifyIMEStatus( HWND hwnd, UINT status ) { return load_driver()->pNotifyIMEStatus( hwnd, status ); @@ -1256,6 +1266,7 @@ static const struct user_driver_funcs lazy_load_driver = loaderdrv_KbdLayerDescriptor, loaderdrv_ReleaseKbdTables, loaderdrv_ImeProcessKey, + loaderdrv_ImeToAsciiEx, loaderdrv_NotifyIMEStatus, loaderdrv_SetIMECompositionRect, /* cursor/icon functions */ @@ -1360,6 +1371,7 @@ void __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT version SET_USER_FUNC(KbdLayerDescriptor); SET_USER_FUNC(ReleaseKbdTables); SET_USER_FUNC(ImeProcessKey); + SET_USER_FUNC(ImeToAsciiEx); SET_USER_FUNC(NotifyIMEStatus); SET_USER_FUNC(SetIMECompositionRect); SET_USER_FUNC(DestroyCursorIcon); diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c index 3337f66e291..0d225f23e37 100644 --- a/dlls/win32u/imm.c +++ b/dlls/win32u/imm.c @@ -687,6 +687,7 @@ LRESULT ime_driver_call( HWND hwnd, enum wine_ime_call call, WPARAM wparam, LPAR return res; } case WINE_IME_TO_ASCII_EX: + user_driver->pImeToAsciiEx( wparam, lparam, (BYTE *)params->state, params->msgs, 0, params->himc ); return ime_to_tascii_ex( wparam, lparam, params->state, params->compstr, params->key_consumed, params->himc ); case WINE_IME_POST_UPDATE: post_ime_update( hwnd, wparam, (WCHAR *)lparam, (WCHAR *)params ); diff --git a/include/ntuser.h b/include/ntuser.h index ce1b18fdfd9..54a4949e407 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -682,6 +682,7 @@ struct ime_driver_call_params const BYTE *state; COMPOSITIONSTRING *compstr; BOOL *key_consumed; + TRANSMSGLIST *msgs; }; /* NtUserSystemTrayCall calls */ diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index f6390bce878..7e2a6005deb 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -373,6 +373,7 @@ struct user_driver_funcs void (*pReleaseKbdTables)(const KBDTABLES *); /* IME functions */ UINT (*pImeProcessKey)(HIMC,UINT,UINT,const BYTE*); + UINT (*pImeToAsciiEx)(UINT,UINT,BYTE*,TRANSMSGLIST*,UINT,HIMC); void (*pNotifyIMEStatus)(HWND,UINT); BOOL (*pSetIMECompositionRect)(HWND,RECT); /* cursor/icon functions */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9992
From: Marc-Aurel Zent <mzent@codeweavers.com> --- dlls/imm32/ime.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index ed3f262c47a..8369fa7bed9 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -361,12 +361,14 @@ static UINT ime_set_comp_string( HIMC himc, LPARAM lparam ) TRANSMSG *msgs; HIMCC himcc; UINT count; + BYTE state[256]; TRACE( "himc %p\n", himc ); if (!(ctx = ImmLockIMC( himc ))) return 0; - count = ImeToAsciiEx( VK_PROCESSKEY, lparam, NULL, &buffer.list, 0, himc ); + GetKeyboardState( state ); + count = ImeToAsciiEx( VK_PROCESSKEY, lparam, state, &buffer.list, 0, himc ); if (!count) TRACE( "ImeToAsciiEx returned no messages\n" ); else if (count >= buffer.uMsgCount) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9992
From: Marc-Aurel Zent <mzent@codeweavers.com> --- dlls/win32u/imm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c index 0d225f23e37..1bfb6e58320 100644 --- a/dlls/win32u/imm.c +++ b/dlls/win32u/imm.c @@ -687,7 +687,14 @@ LRESULT ime_driver_call( HWND hwnd, enum wine_ime_call call, WPARAM wparam, LPAR return res; } case WINE_IME_TO_ASCII_EX: - user_driver->pImeToAsciiEx( wparam, lparam, (BYTE *)params->state, params->msgs, 0, params->himc ); + res = user_driver->pImeToAsciiEx( wparam, lparam, (BYTE *)params->state, params->msgs, 0, params->himc ); + + if (res) + { + NtUserPostMessage( hwnd, WM_KEYDOWN, wparam, lparam ); + return res; + } + return ime_to_tascii_ex( wparam, lparam, params->state, params->compstr, params->key_consumed, params->himc ); case WINE_IME_POST_UPDATE: post_ime_update( hwnd, wparam, (WCHAR *)lparam, (WCHAR *)params ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9992
From: Marc-Aurel Zent <mzent@codeweavers.com> --- dlls/winemac.drv/gdi.c | 1 + dlls/winemac.drv/keyboard.c | 38 ++++++++++++++++++++++++++----------- dlls/winemac.drv/macdrv.h | 2 ++ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/dlls/winemac.drv/gdi.c b/dlls/winemac.drv/gdi.c index 2ef941aedb4..1bf703459f5 100644 --- a/dlls/winemac.drv/gdi.c +++ b/dlls/winemac.drv/gdi.c @@ -278,6 +278,7 @@ static const struct user_driver_funcs macdrv_funcs = .pUpdateLayeredWindow = macdrv_UpdateLayeredWindow, .pVkKeyScanEx = macdrv_VkKeyScanEx, .pImeProcessKey = macdrv_ImeProcessKey, + .pImeToAsciiEx = macdrv_ImeToAsciiEx, .pNotifyIMEStatus = macdrv_NotifyIMEStatus, .pSetIMECompositionRect = macdrv_SetIMECompositionRect, .pWindowMessage = macdrv_WindowMessage, diff --git a/dlls/winemac.drv/keyboard.c b/dlls/winemac.drv/keyboard.c index 7c49be7849f..0b6a81938e5 100644 --- a/dlls/winemac.drv/keyboard.c +++ b/dlls/winemac.drv/keyboard.c @@ -1086,15 +1086,13 @@ void macdrv_hotkey_press(const macdrv_event *event) UINT macdrv_ImeProcessKey(HIMC himc, UINT wparam, UINT lparam, const BYTE *key_state) { struct macdrv_thread_data *thread_data = macdrv_thread_data(); - WORD scan = HIWORD(lparam) & 0x1ff, vkey = LOWORD(wparam); + WORD vkey = LOWORD(wparam); BOOL repeat = !!(lparam >> 30), pressed = !(lparam >> 31); - unsigned int flags; - int keyc; - UINT ret; - TRACE("himc %p, scan %#x, vkey %#x, repeat %u, pressed %u\n", - himc, scan, vkey, repeat, pressed); + TRACE("himc %p, vkey %#x, repeat %u, pressed %u\n", + himc, vkey, repeat, pressed); + thread_data->repeat = repeat; if (!macdrv_using_input_method()) return 0; if (!pressed) @@ -1111,23 +1109,41 @@ UINT macdrv_ImeProcessKey(HIMC himc, UINT wparam, UINT lparam, const BYTE *key_s case VK_CONTROL: case VK_CAPITAL: case VK_MENU: + case VK_KANA: + case VK_KANJI: + TRACE("Skipping metakey\n"); return 0; } + return 1; +} + +/*********************************************************************** + * ImeToAsciiEx (MACDRV.@) + */ +UINT macdrv_ImeToAsciiEx(UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, UINT flags, HIMC himc) +{ + struct macdrv_thread_data *thread_data = macdrv_thread_data(); + int keyc; + UINT ret; + + TRACE("himc %p, vkey %#x state %p\n", + himc, vkey, state); + flags = thread_data->last_modifiers; - if (key_state[VK_SHIFT] & 0x80) + if (state[VK_SHIFT] & 0x80) flags |= NX_SHIFTMASK; else flags &= ~(NX_SHIFTMASK | NX_DEVICELSHIFTKEYMASK | NX_DEVICERSHIFTKEYMASK); - if (key_state[VK_CAPITAL] & 0x01) + if (state[VK_CAPITAL] & 0x01) flags |= NX_ALPHASHIFTMASK; else flags &= ~NX_ALPHASHIFTMASK; - if (key_state[VK_CONTROL] & 0x80) + if (state[VK_CONTROL] & 0x80) flags |= NX_CONTROLMASK; else flags &= ~(NX_CONTROLMASK | NX_DEVICELCTLKEYMASK | NX_DEVICERCTLKEYMASK); - if (key_state[VK_MENU] & 0x80) + if (state[VK_MENU] & 0x80) flags |= NX_COMMANDMASK; else flags &= ~(NX_COMMANDMASK | NX_DEVICELCMDKEYMASK | NX_DEVICERCMDKEYMASK); @@ -1139,7 +1155,7 @@ UINT macdrv_ImeProcessKey(HIMC himc, UINT wparam, UINT lparam, const BYTE *key_s if (keyc >= ARRAY_SIZE(thread_data->keyc2vkey)) return 0; TRACE("flags 0x%08x keyc 0x%04x\n", flags, keyc); - ret = (UINT)macdrv_ime_process_key(keyc, flags, repeat, himc); + ret = !(UINT)macdrv_ime_process_key(keyc, flags, thread_data->repeat, himc); NtUserMsgWaitForMultipleObjectsEx(0, NULL, 0, QS_POSTMESSAGE | QS_SENDMESSAGE, 0); TRACE("returning %u\n", ret); return ret; diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index ac2a7853652..c415509c270 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -107,6 +107,7 @@ static inline RECT rect_from_cgrect(CGRect cgrect) CFDataRef keyboard_layout_uchr; CGEventSourceKeyboardType keyboard_type; bool iso_keyboard; + bool repeat; CGEventFlags last_modifiers; UInt32 dead_key_state; HKL active_keyboard_layout; @@ -160,6 +161,7 @@ extern void macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, HWND owner_hin extern void macdrv_UnregisterHotKey(HWND hwnd, UINT modifiers, UINT vkey); extern SHORT macdrv_VkKeyScanEx(WCHAR wChar, HKL hkl); extern UINT macdrv_ImeProcessKey(HIMC himc, UINT wparam, UINT lparam, const BYTE *state); +extern UINT macdrv_ImeToAsciiEx(UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, UINT flags, HIMC himc); extern UINT macdrv_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl); extern INT macdrv_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState, LPWSTR bufW, int bufW_size, UINT flags, HKL hkl); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9992
v2: Slightly simplified version that does not use the `key_consumed` mechanism (and leaves the exiting logic there unchanged). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9992#note_129862
participants (2)
-
Marc-Aurel Zent -
Marc-Aurel Zent (@mzent)