https://git.reactos.org/?p=reactos.git;a=commitdiff;h=75cf6920bc62f70dc481be5f5d0e63e18cfafd81
commit 75cf6920bc62f70dc481be5f5d0e63e18cfafd81 Author: Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com> AuthorDate: Sun Dec 3 17:33:22 2023 +0900 Commit: GitHub <nore...@github.com> CommitDate: Sun Dec 3 17:33:22 2023 +0900 [IMM32][SDK][NTUSER] Implement ImmProcessKey for Cicero (#6106) Complete CTF IMM. - Add CtfImeProcessCicHotkey and CtfImeSetActiveContextAlways to access CTF IMEs. - Check whether Cicero is started in the current thread in ImmProcessKey. - Call CtfImeProcessCicHotkey if necessary in ImmProcessKey. - Modify <CtfImeTable.h>. - Add CI_CICERO_STARTED flag to "ntuser.h". - Fix Imm32JCloseOpen. CORE-19268 --- dll/win32/imm32/ctf.c | 106 +++++++++++++++++++++++++++++- dll/win32/imm32/imm.c | 9 +-- dll/win32/imm32/keymsg.c | 134 +++++++++++--------------------------- dll/win32/imm32/precomp.h | 18 +++++ sdk/include/reactos/CtfImeTable.h | 4 +- win32ss/include/ntuser.h | 1 + 6 files changed, 163 insertions(+), 109 deletions(-) diff --git a/dll/win32/imm32/ctf.c b/dll/win32/imm32/ctf.c index 23e4b41c3ed..f4463cc67f1 100644 --- a/dll/win32/imm32/ctf.c +++ b/dll/win32/imm32/ctf.c @@ -738,6 +738,20 @@ CtfImeCreateThreadMgr(VOID) return CTF_IME_FN(CtfImeCreateThreadMgr)(); } +/*********************************************************************** + * This function calls the same name function of the CTF IME side. + */ +BOOL +CtfImeProcessCicHotkey(_In_ HIMC hIMC, _In_ UINT vKey, _In_ LPARAM lParam) +{ + TRACE("(%p, %u, %p)\n", hIMC, vKey, lParam); + + if (!Imm32LoadCtfIme()) + return FALSE; + + return CTF_IME_FN(CtfImeProcessCicHotkey)(hIMC, vKey, lParam); +} + /*********************************************************************** * This function calls the same name function of the CTF IME side. */ @@ -775,7 +789,7 @@ BOOL WINAPI CtfImmIsCiceroStartedInThread(VOID) { TRACE("()\n"); - return !!(GetWin32ClientInfo()->CI_flags & 0x200); + return !!(GetWin32ClientInfo()->CI_flags & CI_CICERO_STARTED); } /*********************************************************************** @@ -785,9 +799,9 @@ VOID WINAPI CtfImmSetCiceroStartInThread(_In_ BOOL bStarted) { TRACE("(%d)\n", bStarted); if (bStarted) - GetWin32ClientInfo()->CI_flags |= 0x200; + GetWin32ClientInfo()->CI_flags |= CI_CICERO_STARTED; else - GetWin32ClientInfo()->CI_flags &= ~0x200; + GetWin32ClientInfo()->CI_flags &= ~CI_CICERO_STARTED; } /*********************************************************************** @@ -832,6 +846,24 @@ CtfImeDestroyInputContext(_In_ HIMC hIMC) return CTF_IME_FN(CtfImeDestroyInputContext)(hIMC); } +/*********************************************************************** + * This function calls the same name function of the CTF IME side. + */ +HRESULT +CtfImeSetActiveContextAlways( + _In_ HIMC hIMC, + _In_ BOOL fActive, + _In_ HWND hWnd, + _In_ HKL hKL) +{ + TRACE("(%p, %d, %p, %p)\n", hIMC, fActive, hWnd, hKL); + + if (!Imm32LoadCtfIme()) + return E_FAIL; + + return CTF_IME_FN(CtfImeSetActiveContextAlways)(hIMC, fActive, hWnd, hKL); +} + /*********************************************************************** * The callback function to activate CTF IMEs. Used in CtfAImmActivate. */ @@ -1173,6 +1205,74 @@ CtfImmTIMActivate(_In_ HKL hKL) return hr; } +/*********************************************************************** + * Setting language band + */ + +typedef struct IMM_DELAY_SET_LANG_BAND +{ + HWND hWnd; + BOOL fSet; +} IMM_DELAY_SET_LANG_BAND, *PIMM_DELAY_SET_LANG_BAND; + +/* Sends a message to set the language band with delay. */ +static DWORD APIENTRY Imm32DelaySetLangBandProc(LPVOID arg) +{ + HWND hwndDefIME; + WPARAM wParam; + DWORD_PTR lResult; + PIMM_DELAY_SET_LANG_BAND pSetBand = arg; + + Sleep(3000); /* Delay 3 seconds! */ + + hwndDefIME = ImmGetDefaultIMEWnd(pSetBand->hWnd); + if (hwndDefIME) + { + wParam = (pSetBand->fSet ? IMS_SETLANGBAND : IMS_UNSETLANGBAND); + SendMessageTimeoutW(hwndDefIME, WM_IME_SYSTEM, wParam, (LPARAM)pSetBand->hWnd, + SMTO_BLOCK | SMTO_ABORTIFHUNG, 5000, &lResult); + } + ImmLocalFree(pSetBand); + return FALSE; +} + +/* Updates the language band. */ +LRESULT +CtfImmSetLangBand( + _In_ HWND hWnd, + _In_ BOOL fSet) +{ + HANDLE hThread; + PWND pWnd = NULL; + PIMM_DELAY_SET_LANG_BAND pSetBand; + DWORD_PTR lResult = 0; + + if (hWnd && gpsi) + pWnd = ValidateHwndNoErr(hWnd); + + if (IS_NULL_UNEXPECTEDLY(pWnd)) + return 0; + + if (pWnd->state2 & WNDS2_WMCREATEMSGPROCESSED) + { + SendMessageTimeoutW(hWnd, WM_USER + 0x105, 0, fSet, SMTO_BLOCK | SMTO_ABORTIFHUNG, + 5000, &lResult); + return lResult; + } + + pSetBand = ImmLocalAlloc(0, sizeof(IMM_DELAY_SET_LANG_BAND)); + if (IS_NULL_UNEXPECTEDLY(pSetBand)) + return 0; + + pSetBand->hWnd = hWnd; + pSetBand->fSet = fSet; + + hThread = CreateThread(NULL, 0, Imm32DelaySetLangBandProc, pSetBand, 0, NULL); + if (hThread) + CloseHandle(hThread); + return 0; +} + /*********************************************************************** * CtfImmGenerateMessage (IMM32.@) */ diff --git a/dll/win32/imm32/imm.c b/dll/win32/imm32/imm.c index 3ea5bae50ea..aa81c0935bd 100644 --- a/dll/win32/imm32/imm.c +++ b/dll/win32/imm32/imm.c @@ -183,7 +183,6 @@ Retry: return TRUE; } -// Win: SelectInputContext VOID APIENTRY Imm32SelectInputContext(HKL hNewKL, HKL hOldKL, HIMC hIMC) { PCLIENTIMC pClientImc; @@ -490,12 +489,6 @@ BOOL WINAPI ImmActivateLayout(HKL hKL) return TRUE; } -/* Win: Internal_CtfImeSetActiveContextAlways */ -static VOID APIENTRY Imm32CiceroSetActiveContext(HIMC hIMC, BOOL fActive, HWND hWnd, HKL hKL) -{ - TRACE("We have to do something\n"); -} - /*********************************************************************** * ImmAssociateContext (IMM32.@) */ @@ -1196,7 +1189,7 @@ BOOL WINAPI ImmSetActiveContext(HWND hWnd, HIMC hIMC, BOOL fActive) hKL = GetKeyboardLayout(0); if (IS_CICERO_MODE() && !IS_16BIT_MODE()) { - Imm32CiceroSetActiveContext(hIMC, fActive, hWnd, hKL); + CtfImeSetActiveContextAlways(hIMC, fActive, hWnd, hKL); hKL = GetKeyboardLayout(0); } diff --git a/dll/win32/imm32/keymsg.c b/dll/win32/imm32/keymsg.c index 4131b751071..f1dd211b607 100644 --- a/dll/win32/imm32/keymsg.c +++ b/dll/win32/imm32/keymsg.c @@ -158,7 +158,6 @@ BOOL APIENTRY Imm32CSymbolToggle(HIMC hIMC, HKL hKL, HWND hWnd) } /* Open or close Japanese IME */ -/* Win: JCloseOpen */ BOOL APIENTRY Imm32JCloseOpen(HIMC hIMC, HKL hKL, HWND hWnd) { BOOL fOpen; @@ -177,7 +176,7 @@ BOOL APIENTRY Imm32JCloseOpen(HIMC hIMC, HKL hKL, HWND hWnd) pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); if (pIC) { - pIC->dwChange |= INPUTCONTEXTDX_CHANGE_OPEN; /* Notify open change */ + pIC->dwChange |= INPUTCONTEXTDX_CHANGE_FORCE_OPEN; ImmUnlockIMC(hIMC); } } @@ -331,85 +330,23 @@ ImmIsUIMessageAW(HWND hWndIME, UINT msg, WPARAM wParam, LPARAM lParam, BOOL bAns return TRUE; } -typedef struct IMM_DELAY_SET_LANG_BAND -{ - HWND hWnd; - BOOL fSet; -} IMM_DELAY_SET_LANG_BAND, *PIMM_DELAY_SET_LANG_BAND; - -/* Sends a message to set the language band with delay. */ -/* Win: DelaySetLangBand */ -static DWORD APIENTRY Imm32DelaySetLangBandProc(LPVOID arg) -{ - HWND hwndDefIME; - WPARAM wParam; - DWORD_PTR lResult; - PIMM_DELAY_SET_LANG_BAND pSetBand = arg; - - Sleep(3000); /* Delay 3 seconds! */ - - hwndDefIME = ImmGetDefaultIMEWnd(pSetBand->hWnd); - if (hwndDefIME) - { - wParam = (pSetBand->fSet ? IMS_SETLANGBAND : IMS_UNSETLANGBAND); - SendMessageTimeoutW(hwndDefIME, WM_IME_SYSTEM, wParam, (LPARAM)pSetBand->hWnd, - SMTO_BLOCK | SMTO_ABORTIFHUNG, 5000, &lResult); - } - ImmLocalFree(pSetBand); - return FALSE; -} - -/* Updates the language band. */ -/* Win: CtfImmSetLangBand */ -LRESULT APIENTRY CtfImmSetLangBand(HWND hWnd, BOOL fSet) -{ - HANDLE hThread; - PWND pWnd = NULL; - PIMM_DELAY_SET_LANG_BAND pSetBand; - DWORD_PTR lResult = 0; - - if (hWnd && gpsi) - pWnd = ValidateHwndNoErr(hWnd); - - if (IS_NULL_UNEXPECTEDLY(pWnd)) - return 0; - - if (pWnd->state2 & WNDS2_WMCREATEMSGPROCESSED) - { - SendMessageTimeoutW(hWnd, WM_USER + 0x105, 0, fSet, SMTO_BLOCK | SMTO_ABORTIFHUNG, - 5000, &lResult); - return lResult; - } - - pSetBand = ImmLocalAlloc(0, sizeof(IMM_DELAY_SET_LANG_BAND)); - if (IS_NULL_UNEXPECTEDLY(pSetBand)) - return 0; - - pSetBand->hWnd = hWnd; - pSetBand->fSet = fSet; - - hThread = CreateThread(NULL, 0, Imm32DelaySetLangBandProc, pSetBand, 0, NULL); - if (hThread) - CloseHandle(hThread); - return 0; -} - -/* Win: SendNotificationProc */ -static BOOL CALLBACK Imm32SendNotificationProc(HIMC hIMC, LPARAM lParam) +static BOOL CALLBACK +Imm32SendNotificationProc( + _In_ HIMC hIMC, + _In_ LPARAM lParam) { HWND hWnd; LPINPUTCONTEXTDX pIC; + UNREFERENCED_PARAMETER(lParam); + pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); if (IS_NULL_UNEXPECTEDLY(pIC)) return TRUE; hWnd = pIC->hWnd; - if (hWnd == NULL || !IsWindow(hWnd)) - { - ERR("\n"); + if (!IsWindow(hWnd)) goto Quit; - } TRACE("dwChange: 0x%08X\n", pIC->dwChange); @@ -427,7 +364,6 @@ Quit: return TRUE; } -/* Win: ImmSendNotification */ BOOL APIENTRY Imm32SendNotification(BOOL bProcess) { return ImmEnumInputContext((bProcess ? -1 : 0), Imm32SendNotificationProc, 0); @@ -783,11 +719,11 @@ ImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID) PIMEDPI pImeDpi; LPINPUTCONTEXTDX pIC; BYTE KeyState[256]; - UINT vk; - BOOL bUseIme = TRUE, bSkipThisKey = FALSE, bLowWordOnly = FALSE; + BOOL bLowWordOnly = FALSE, bSkipThisKey = FALSE, bHotKeyDone = TRUE; TRACE("(%p, %p, 0x%X, %p, 0x%lX)\n", hWnd, hKL, vKey, lParam, dwHotKeyID); + /* Process the key by the IME */ hIMC = ImmGetContext(hWnd); pImeDpi = ImmLockImeDpi(hKL); if (pImeDpi) @@ -795,7 +731,7 @@ ImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID) pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); if (pIC) { - if (LOBYTE(vKey) == VK_PACKET && + if ((LOBYTE(vKey) == VK_PACKET) && !(pImeDpi->ImeInfo.fdwProperty & IME_PROP_ACCEPT_WIDE_VKEY)) { if (ImeDpi_IsUnicode(pImeDpi)) @@ -804,29 +740,23 @@ ImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID) } else { - bUseIme = FALSE; if (pIC->fOpen) - bSkipThisKey = TRUE; + ret |= IPHK_SKIPTHISKEY; + + bSkipThisKey = TRUE; } } - if (bUseIme) + if (!bSkipThisKey && GetKeyboardState(KeyState)) { - if (GetKeyboardState(KeyState)) + UINT vk = (bLowWordOnly ? LOWORD(vKey) : vKey); + if (pImeDpi->ImeProcessKey(hIMC, vk, lParam, KeyState)) { - vk = (bLowWordOnly ? LOWORD(vKey) : vKey); - if (pImeDpi->ImeProcessKey(hIMC, vk, lParam, KeyState)) - { - pIC->bNeedsTrans = TRUE; - pIC->nVKey = vKey; - ret |= IPHK_PROCESSBYIME; - } + pIC->bNeedsTrans = TRUE; + pIC->nVKey = vKey; + ret |= IPHK_PROCESSBYIME; } } - else if (bSkipThisKey) - { - ret |= IPHK_SKIPTHISKEY; - } ImmUnlockIMC(hIMC); } @@ -834,21 +764,32 @@ ImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID) ImmUnlockImeDpi(pImeDpi); } - if (dwHotKeyID != INVALID_HOTKEY_ID) /* Valid Hot-key */ + /* Process the hot-key if necessary */ + if (!CtfImmIsCiceroStartedInThread()) /* Not Cicero? */ + { + /* Process IMM IME hotkey */ + if ((dwHotKeyID == INVALID_HOTKEY_ID) || !Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID)) + bHotKeyDone = FALSE; + } + else if (!CtfImeProcessCicHotkey(hIMC, vKey, lParam)) /* CTF IME not processed the hotkey? */ { - if (Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID)) + /* Process IMM IME hotkey */ + if (!IS_IME_HKL(hKL) || + ((dwHotKeyID == INVALID_HOTKEY_ID) || !Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID))) { - if (vKey != VK_KANJI || dwHotKeyID != IME_JHOTKEY_CLOSE_OPEN) - ret |= IPHK_HOTKEY; + bHotKeyDone = FALSE; } } + if (bHotKeyDone && ((vKey != VK_KANJI) || (dwHotKeyID != IME_JHOTKEY_CLOSE_OPEN))) + ret |= IPHK_HOTKEY; + if ((ret & IPHK_PROCESSBYIME) && (ImmGetAppCompatFlags(hIMC) & 0x10000)) { /* The key has been processed by IME's ImeProcessKey */ LANGID wLangID = LANGIDFROMLCID(GetSystemDefaultLCID()); - if (PRIMARYLANGID(wLangID) == LANG_KOREAN && - (vKey == VK_PROCESSKEY || (ret & IPHK_HOTKEY))) + if ((PRIMARYLANGID(wLangID) == LANG_KOREAN) && + ((vKey == VK_PROCESSKEY) || (ret & IPHK_HOTKEY))) { /* Korean don't want VK_PROCESSKEY and IME hot-keys */ } @@ -856,6 +797,7 @@ ImmProcessKey(HWND hWnd, HKL hKL, UINT vKey, LPARAM lParam, DWORD dwHotKeyID) { /* Add WM_KEYDOWN:VK_PROCESSKEY message */ ImmTranslateMessage(hWnd, WM_KEYDOWN, VK_PROCESSKEY, lParam); + ret &= ~IPHK_PROCESSBYIME; ret |= IPHK_SKIPTHISKEY; } diff --git a/dll/win32/imm32/precomp.h b/dll/win32/imm32/precomp.h index 3f667d1d6f5..cb87f48890c 100644 --- a/dll/win32/imm32/precomp.h +++ b/dll/win32/imm32/precomp.h @@ -201,3 +201,21 @@ HRESULT CtfImmCoInitialize(VOID); HRESULT CtfImeCreateThreadMgr(VOID); HRESULT CtfImeDestroyThreadMgr(VOID); HRESULT Imm32ActivateOrDeactivateTIM(_In_ BOOL bCreate); + +HRESULT +CtfImeSetActiveContextAlways( + _In_ HIMC hIMC, + _In_ BOOL fActive, + _In_ HWND hWnd, + _In_ HKL hKL); + +BOOL +CtfImeProcessCicHotkey( + _In_ HIMC hIMC, + _In_ UINT vKey, + _In_ LPARAM lParam); + +LRESULT +CtfImmSetLangBand( + _In_ HWND hWnd, + _In_ BOOL fSet); diff --git a/sdk/include/reactos/CtfImeTable.h b/sdk/include/reactos/CtfImeTable.h index 14f701b6c46..99a208e6f42 100644 --- a/sdk/include/reactos/CtfImeTable.h +++ b/sdk/include/reactos/CtfImeTable.h @@ -12,7 +12,7 @@ DEFINE_CTF_IME_FN(CtfImeCreateThreadMgr, HRESULT, (VOID)) DEFINE_CTF_IME_FN(CtfImeDestroyThreadMgr, HRESULT, (VOID)) DEFINE_CTF_IME_FN(CtfImeCreateInputContext, HRESULT, (HIMC hIMC)) DEFINE_CTF_IME_FN(CtfImeDestroyInputContext, HRESULT, (HIMC hIMC)) -DEFINE_CTF_IME_FN(CtfImeSetActiveContextAlways, HRESULT, (DWORD dwFIXME1, DWORD dwFIXME2, DWORD dwFIXME3, DWORD dwFIXME4)) -DEFINE_CTF_IME_FN(CtfImeProcessCicHotkey, HRESULT, (DWORD dwFIXME1, DWORD dwFIXME2, DWORD dwFIXME3)) +DEFINE_CTF_IME_FN(CtfImeSetActiveContextAlways, HRESULT, (HIMC hIMC, BOOL fActive, HWND hWnd, HKL hKL)) +DEFINE_CTF_IME_FN(CtfImeProcessCicHotkey, HRESULT, (HIMC hIMC, UINT vKey, LPARAM lParam)) DEFINE_CTF_IME_FN(CtfImeDispatchDefImeMessage, LRESULT, (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)) DEFINE_CTF_IME_FN(CtfImeIsIME, BOOL, (HKL hKL)) diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index 2763b4b24cc..c5e08f83ac2 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -305,6 +305,7 @@ typedef struct _CALLBACKWND #define CI_IMMACTIVATE 0x00000040 /* IMM/IME (Asian input) */ #define CI_CTFCOINIT 0x00000080 /* Did CTF CoInitialize? */ #define CI_CTFTIM 0x00000100 /* CTF Thread Input Manager (TIM) */ +#define CI_CICERO_STARTED 0x00000200 /* Is Cicero started in the thread? */ #define CI_TSFDISABLED 0x00000400 /* TSF (Text Services Framework a.k.a. Cicero) */ #define CI_AIMMACTIVATED 0x00000800 /* Active IMM (AIMM) */