[PATCH v2 0/5] MR9992: Winemac IME rework part 1
-- v2: winemac: Implement and use macdrv_ImeToAsciiEx(). win32u: Mark rejected IME messages as unprocessed. imm32: Generate a proper 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/imm32/ime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dlls/imm32/ime.c b/dlls/imm32/ime.c index 8369fa7bed9..f448412e10b 100644 --- a/dlls/imm32/ime.c +++ b/dlls/imm32/ime.c @@ -594,7 +594,7 @@ UINT WINAPI ImeToAsciiEx( UINT vkey, UINT vsc, BYTE *state, TRANSMSGLIST *msgs, if (!key_consumed) { - TRANSMSG msg = {.message = WM_IME_KEYDOWN, .wParam = vkey, .lParam = vsc}; + TRANSMSG msg = {.message = WM_KEYDOWN, .wParam = LOWORD( vkey ), .lParam = MAKELONG( 1, vsc )}; msgs->TransMsg[count++] = msg; } } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9992
From: Marc-Aurel Zent <mzent@codeweavers.com> --- dlls/win32u/imm.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/dlls/win32u/imm.c b/dlls/win32u/imm.c index 0d225f23e37..c501cd89e1d 100644 --- a/dlls/win32u/imm.c +++ b/dlls/win32u/imm.c @@ -687,8 +687,17 @@ 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 ); + { + UINT ret = user_driver->pImeToAsciiEx( wparam, lparam, (BYTE *)params->state, params->msgs, 0, params->himc ); + + if (ret) + { + *params->key_consumed = FALSE; + NtUserNotifyIMEStatus( hwnd, 0 ); + return 0; + } 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 ); return 0; -- 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
On Wed Jan 28 16:04:35 2026 +0000, Rémi Bernon wrote:
The split of ImeToAsciiEx from ImeProcessKey doesn't seem right to me. ImeProcessKey should return whether the key has been consumed or not, there's no good way to backtrack on an decision to consume a key. It needs to be this way, I think, and I have been contemplating how to write a test for this, but it is not trivially possible to show this on native Windows at least without physically pressing keys, since `NtUserSendInput` and friends do not seem to be passing through the native IME subsystem in the same way as it does for Wine.
In any case, FFXIV specifically always has an active IME context while the game is running and then in its window message loop, decides to discard IME input when no text field is active in-engine (like for normal WASD movement), by calling `ImmGetVirtualKey()` and indeed backtracking on the decision to consume a key by replacing `VK_PROCESSKEY` again with the original key. This works fine on native Windows and Wine versions pre-IME unification (somewhere around Wine 7.7 on macOS at least), where pretty much IME was handled similarly to how it is done in this MR conceptually. Here I chose to backtrack with the already existing and fairly recently added `key_consumed` parameter (which seems to work fine here, but maybe there are some side effects, I am not seeing here at the moment), however in the original implementation it was all handled in the `ImeToAsciiEx` implementation of the user driver like so: ``` /* 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)); ``` If there is a more elegant solution to feeding IME input around the `ImeToAsciiEx` stage into the native Cocoa input context, then that would be preferable, but I don't currently see a way to make this happen... -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9992#note_128286
On Wed Jan 28 16:04:35 2026 +0000, Marc-Aurel Zent wrote:
It needs to be this way, I think, and I have been contemplating how to write a test for this, but it is not trivially possible to show this on native Windows at least without physically pressing keys, since `NtUserSendInput` and friends do not seem to be passing through the native IME subsystem in the same way as it does for Wine. In any case, FFXIV specifically always has an active IME context while the game is running and then in its window message loop, decides to discard IME input when no text field is active in-engine (like for normal WASD movement), by calling `ImmGetVirtualKey()` and indeed backtracking on the decision to consume a key by replacing `VK_PROCESSKEY` again with the original key. This works fine on native Windows and Wine versions pre-IME unification (somewhere around Wine 7.7 on macOS at least), where pretty much IME was handled similarly to how it is done in this MR conceptually. Here I chose to backtrack with the already existing and fairly recently added `key_consumed` parameter (which seems to work fine here, but maybe there are some side effects, I am not seeing here at the moment), however in the original implementation it was all handled in the `ImeToAsciiEx` implementation of the user driver like so: ``` /* 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)); ``` If there is a more elegant solution to feeding IME input around the `ImeToAsciiEx` stage into the native Cocoa input context, then that would be preferable, but I don't currently see a way to make this happen... I have not seen much evidence so far that SendInput does a very different thing from real user input, and it's usually usable for testing.
Otherwise you can go for the heavy weaponry and use dinput tests to create an HID keyboard you can control in the tests. In any case I am still skeptical of the conclusion, and I would rather think that something else in our message processing is involved, and tests are going to be needed to decide. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9992#note_128289
We also probably need a better way to integrate host IMEs as it would be unfortunate to unconditionally return TRUE from ImeProcessKey, and it would be better to only do so if there's an actual IME to be fed on the host side.
At least on the Cocoa side of things I don't think there is a good way to do this even using private APIs (as in asking the native IME if it would consume a key event).
I'm not completely clear on what it implies, like whether normal keyboard message need to be restored and where (or whether this is already working or not), and this could perhaps also be added to these tests.
Unfortunately in my windows VM for some reason the non interactive IME tests still do not generate a VK_PROCESSKEY when using SendInput/keybd_event instead of physically pressing the key... But maybe this can be solved more elegantly somehow rather than interpreting the success of ImeToAsciiEx in the user driver, although I think it still makes sense to handle this in win32u in a more unified way. I am also not familiar with the inner workings of how this is handled on winex11 there; this patch was designed to be a no-op though for all other drivers. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9992#note_129512
The following self-contained [ime_test.c](https://gitlab.winehq.org/-/project/5/uploads/d54834a54cea2796f930d8be92eb37...) should show the desired behavior (Windows completely ignoring the IME processing for keys that are backtracked on) well.
If the application restores msg.wParam == VK_PROCESS back to msg.wParam = ImmGetVirtualKey(hwnd), then in NtUserTranslateMessage it no longer goes through the IMM/IME-related code path. Instead, it follows the NtUserToUnicodeEx route—that is, the normal keyboard driver WM_KEYDOWN processing path. So I’m wondering why the patch is being made in the IME code. But I may be misunderstanding the exact scenario in which this becomes a problem. By any chance, are you testing this with the "Japanese – Kana" or "2-Set Korean" keyboard input source? In the test program you provided, "Japanese - Kana": ``` IME detected VK_PROCESSKEY, Replacing with original VK: 0x0041 (A) WM_KEYDOWN: wParam = 0x0041 (A) scan=0x1E WM_CHAR / WM_IME_CHAR: char = 0x3061 (?) WM_KEYUP: wParam = 0x0041 (A) ``` Is this what you would like it to look like? ``` IME detected VK_PROCESSKEY, Replacing with original VK: 0x0041 (A) WM_KEYDOWN: wParam = 0x0041 (A) scan=0x1E WM_CHAR / WM_IME_CHAR: char = 0x0061 (a) WM_KEYUP: wParam = 0x0041 (A) ``` Then, this appears to be an issue within macdrv_ToUnicodeEx. With “Japanese – Kana,” the keycode-to-Hiragana mapping is also handled at the keyboard driver level. It might be easier to understand this by comparing it with "Japanese – Romanji". As far as I know, the IME input sources provided by macOS do not have an IME on/off mode, and we need to switch the input source in order to type A–Z characters. In other words, under normal IME input source conditions, macdrv_ToUnicodeEx is not usually called. In my opinion, it might be possible to handle this in macdrv_ToUnicodeEx by checking the result of macdrv_using_input_method(), although that could make the code a bit more complicated. Anyway, this is my analysis so far, and I hope this is useful, but I’m not certain. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9992#note_129514
On Thu Feb 12 12:44:51 2026 +0000, Byeongsik Jeon wrote:
The following self-contained [ime_test.c](https://gitlab.winehq.org/-/project/5/uploads/d54834a54cea2796f930d8be92eb37...) should show the desired behavior (Windows completely ignoring the IME processing for keys that are backtracked on) well. If the application restores msg.wParam == VK_PROCESS back to msg.wParam = ImmGetVirtualKey(hwnd), then in NtUserTranslateMessage it no longer goes through the IMM/IME-related code path. Instead, it follows the NtUserToUnicodeEx route—that is, the normal keyboard driver WM_KEYDOWN processing path. So I’m wondering why the patch is being made in the IME code. But I may be misunderstanding the exact scenario in which this becomes a problem. By any chance, are you testing this with the "Japanese – Kana" or "2-Set Korean" keyboard input source? In the test program you provided, "Japanese - Kana":
IME detected VK_PROCESSKEY, Replacing with original VK: 0x0041 (A) WM_KEYDOWN: wParam = 0x0041 (A) scan=0x1E WM_CHAR / WM_IME_CHAR: char = 0x3061 (?) WM_KEYUP: wParam = 0x0041 (A)Is this what you would like it to look like? ``` IME detected VK_PROCESSKEY, Replacing with original VK: 0x0041 (A) WM_KEYDOWN: wParam = 0x0041 (A) scan=0x1E WM_CHAR / WM_IME_CHAR: char = 0x0061 (a) WM_KEYUP: wParam = 0x0041 (A) ``` Then, this appears to be an issue within macdrv_ToUnicodeEx. With “Japanese – Kana,” the keycode-to-Hiragana mapping is also handled at the keyboard driver level. It might be easier to understand this by comparing it with "Japanese – Romanji". As far as I know, the IME input sources provided by macOS do not have an IME on/off mode, and we need to switch the input source in order to type A–Z characters. In other words, under normal IME input source conditions, macdrv_ToUnicodeEx is not usually called. In my opinion, it might be possible to handle this in macdrv_ToUnicodeEx by checking the result of macdrv_using_input_method(), although that could make the code a bit more complicated. Anyway, this is my analysis so far, and I hope this is useful, but I’m not certain. ---- Update: Although I haven't tested it myself, TISCopyCurrentASCIICapableInputSource should allow UCKeyTranslate to behave as intended. Fwiw regarding IME detection I think a solution (which also applies to other platforms where it might be hard as well) would be to have a mapping of well known non-IME host keyboard layouts, as a hardcoded name list if we can't do better, mapped to their corresponding well-known Windows HKL values, and every unknown host layout exposed as a generic Wine IME HKL, with the IME HKL bit set, as any other native IMEs.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/9992#note_129602
In my opinion, it might be possible to handle this in macdrv_ToUnicodeEx by checking the result of macdrv_using_input_method(), although that could make the code a bit more complicated.
The problem that this is supposed to fix primarily is not feeding the `A` character at all into the native IME system in that scenario, which the current implementation does (the test is more about observing this effect). The resulting `WM_CHAR` is still wrong there, but that is only secondary to the issue.
Fwiw regarding IME detection I think a solution (which also applies to other platforms where it might be hard as well) would be to have a mapping of well known non-IME host keyboard layouts, as a hardcoded name list if we can't do better, mapped to their corresponding well-known Windows HKL values, and every unknown host layout exposed as a generic Wine IME HKL, with the IME HKL bit set, as any other native IMEs.
This already works pretty well as it is with `macdrv_using_input_method(void)`, although it would indeed be nicer to have this on a per-key granularity, instead of per-layout, but I think that is the best that can currently be done. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/9992#note_129743
participants (4)
-
Byeongsik Jeon (@bsjeon) -
Marc-Aurel Zent -
Marc-Aurel Zent (@mzent) -
Rémi Bernon (@rbernon)