https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bbe5fd5274335c1ece7f74...
commit bbe5fd5274335c1ece7f74964bf21533d59969f3 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Thu Feb 10 22:53:28 2022 +0900 Commit: GitHub noreply@github.com CommitDate: Thu Feb 10 22:53:28 2022 +0900
[NTUSER] Implement NtUserCheckImeHotKey (#4351)
- Modify NtUserCheckImeHotKey prototype. - Add IntGetImeHotKeyLanguageScore, IntGetActiveKeyboardLayout, IntGetImeHotKeyByKey, and IntCheckImeHotKey helper functions. - Implement NtUserCheckImeHotKey function. CORE-11700 --- win32ss/include/ntuser.h | 4 +- win32ss/user/ntuser/ime.c | 187 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 179 insertions(+), 12 deletions(-)
diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index f792c08a2c0..95bd2db0a67 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -1846,8 +1846,8 @@ NtUserCheckWindowThreadDesktop( DWORD NTAPI NtUserCheckImeHotKey( - DWORD dwUnknown1, - LPARAM dwUnknown2); + UINT uVirtualKey, + LPARAM lParam);
HWND NTAPI NtUserChildWindowFromPointEx( diff --git a/win32ss/user/ntuser/ime.c b/win32ss/user/ntuser/ime.c index f6b0cb18bb2..1ea65ef512b 100644 --- a/win32ss/user/ntuser/ime.c +++ b/win32ss/user/ntuser/ime.c @@ -11,6 +11,7 @@ DBG_DEFAULT_CHANNEL(UserMisc);
#define INVALID_THREAD_ID ((ULONG)-1) +#define INVALID_HOTKEY ((UINT)-1) #define MOD_KEYS (MOD_CONTROL | MOD_SHIFT | MOD_ALT | MOD_WIN) #define MOD_LEFT_RIGHT (MOD_LEFT | MOD_RIGHT)
@@ -55,6 +56,50 @@ typedef struct tagIMEHOTKEY } IMEHOTKEY, *PIMEHOTKEY;
PIMEHOTKEY gpImeHotKeyList = NULL; +LCID glcid = 0; + +UINT FASTCALL IntGetImeHotKeyLanguageScore(HKL hKL, LANGID HotKeyLangId) +{ + LCID lcid; + + if (HotKeyLangId == LANGID_NEUTRAL || HotKeyLangId == LOWORD(hKL)) + return 3; + + _SEH2_TRY + { + lcid = NtCurrentTeb()->CurrentLocale; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + lcid = MAKELCID(LANGID_NEUTRAL, SORT_DEFAULT); + } + _SEH2_END; + + if (HotKeyLangId == LANGIDFROMLCID(lcid)) + return 2; + + if (glcid == 0) + ZwQueryDefaultLocale(FALSE, &glcid); + + if (HotKeyLangId == LANGIDFROMLCID(glcid)) + return 1; + + return 0; +} + +HKL FASTCALL IntGetActiveKeyboardLayout(VOID) +{ + PTHREADINFO pti; + + if (gpqForeground && gpqForeground->spwndActive) + { + pti = gpqForeground->spwndActive->head.pti; + if (pti && pti->KeyboardLayout) + return pti->KeyboardLayout->hkl; + } + + return UserGetKeyboardLayout(0); +}
static LANGID FASTCALL IntGetImeHotKeyLangId(DWORD dwHotKeyId) { @@ -165,6 +210,117 @@ static VOID FASTCALL IntDeleteImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey) } }
+PIMEHOTKEY +IntGetImeHotKeyByKey(PIMEHOTKEY pList, UINT uModKeys, UINT uLeftRight, UINT uVirtualKey) +{ + PIMEHOTKEY pNode, ret = NULL; + PTHREADINFO pti = GetW32ThreadInfo(); + LANGID LangId; + HKL hKL = IntGetActiveKeyboardLayout(); + BOOL fKorean = (PRIMARYLANGID(LOWORD(hKL)) == LANG_KOREAN); + UINT nScore, nMaxScore = 0; + + for (pNode = pList; pNode; pNode = pNode->pNext) + { + if (pNode->uVirtualKey != uVirtualKey) + continue; + + if ((pNode->uModifiers & MOD_IGNORE_ALL_MODIFIER)) + { + ; + } + else if ((pNode->uModifiers & MOD_KEYS) != uModKeys) + { + continue; + } + else if ((pNode->uModifiers & uLeftRight) || + (pNode->uModifiers & MOD_LEFT_RIGHT) == uLeftRight) + { + ; + } + else + { + continue; + } + + LangId = IntGetImeHotKeyLangId(pNode->dwHotKeyId); + nScore = IntGetImeHotKeyLanguageScore(hKL, LangId); + if (nScore >= 3) + return pNode; + + if (fKorean) + continue; + + if (nScore == 0) + { + if (pNode->dwHotKeyId == IME_CHOTKEY_IME_NONIME_TOGGLE || + pNode->dwHotKeyId == IME_THOTKEY_IME_NONIME_TOGGLE) + { + if (LOWORD(pti->hklPrev) == LangId) + return pNode; + } + } + + if (nMaxScore < nScore) + { + nMaxScore = nScore; + ret = pNode; + } + } + + return ret; +} + +PIMEHOTKEY IntCheckImeHotKey(PUSER_MESSAGE_QUEUE MessageQueue, UINT uVirtualKey, LPARAM lParam) +{ + PIMEHOTKEY pHotKey; + UINT uModifiers; + BOOL bKeyUp = (lParam & 0x80000000); + const BYTE *KeyState = MessageQueue->afKeyState; + static UINT s_uKeyUpVKey = 0; + + if (bKeyUp) + { + if (s_uKeyUpVKey != uVirtualKey) + { + s_uKeyUpVKey = 0; + return NULL; + } + + s_uKeyUpVKey = 0; + } + + uModifiers = 0; + if (IS_KEY_DOWN(KeyState, VK_LSHIFT)) uModifiers |= (MOD_SHIFT | MOD_LEFT); + if (IS_KEY_DOWN(KeyState, VK_RSHIFT)) uModifiers |= (MOD_SHIFT | MOD_RIGHT); + if (IS_KEY_DOWN(KeyState, VK_LCONTROL)) uModifiers |= (MOD_CONTROL | MOD_LEFT); + if (IS_KEY_DOWN(KeyState, VK_RCONTROL)) uModifiers |= (MOD_CONTROL | MOD_RIGHT); + if (IS_KEY_DOWN(KeyState, VK_LMENU)) uModifiers |= (MOD_ALT | MOD_LEFT); + if (IS_KEY_DOWN(KeyState, VK_RMENU)) uModifiers |= (MOD_ALT | MOD_RIGHT); + + pHotKey = IntGetImeHotKeyByKey(gpImeHotKeyList, + (uModifiers & MOD_KEYS), + (uModifiers & MOD_LEFT_RIGHT), + uVirtualKey); + if (pHotKey) + { + if (bKeyUp) + { + if (pHotKey->uModifiers & MOD_ON_KEYUP) + return pHotKey; + } + else + { + if (pHotKey->uModifiers & MOD_ON_KEYUP) + s_uKeyUpVKey = uVirtualKey; + else + return pHotKey; + } + } + + return NULL; +} + VOID FASTCALL IntFreeImeHotKeys(VOID) { PIMEHOTKEY pNode, pNext; @@ -294,6 +450,27 @@ NtUserSetImeHotKey( return ret; }
+DWORD +NTAPI +NtUserCheckImeHotKey(UINT uVirtualKey, LPARAM lParam) +{ + PIMEHOTKEY pNode; + DWORD ret = INVALID_HOTKEY; + + UserEnterExclusive(); + + if (!gpqForeground || !IS_IMM_MODE()) + goto Quit; + + pNode = IntCheckImeHotKey(gpqForeground, uVirtualKey, lParam); + if (pNode) + ret = pNode->dwHotKeyId; + +Quit: + UserLeave(); + return ret; +} + PWND FASTCALL IntGetTopLevelWindow(PWND pwnd) { if (!pwnd) @@ -551,16 +728,6 @@ Quit: return 0; }
-DWORD -NTAPI -NtUserCheckImeHotKey( - DWORD VirtualKey, - LPARAM lParam) -{ - STUB; - return 0; -} - BOOL NTAPI NtUserDisableThreadIme(