https://git.reactos.org/?p=reactos.git;a=commitdiff;h=bbe5fd5274335c1ece7f7…
commit bbe5fd5274335c1ece7f74964bf21533d59969f3
Author: Katayama Hirofumi MZ <katayama.hirofumi.mz(a)gmail.com>
AuthorDate: Thu Feb 10 22:53:28 2022 +0900
Commit: GitHub <noreply(a)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(