Skip to content

Commit

Permalink
[NTUSER] Implement NtUserCheckImeHotKey (#4351)
Browse files Browse the repository at this point in the history
- Modify NtUserCheckImeHotKey prototype.
- Add IntGetImeHotKeyLanguageScore, IntGetActiveKeyboardLayout, IntGetImeHotKeyByKey, and IntCheckImeHotKey helper functions.
- Implement NtUserCheckImeHotKey function.
CORE-11700
  • Loading branch information
katahiromz committed Feb 10, 2022
1 parent 1b06522 commit bbe5fd5
Show file tree
Hide file tree
Showing 2 changed files with 179 additions and 12 deletions.
4 changes: 2 additions & 2 deletions win32ss/include/ntuser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1846,8 +1846,8 @@ NtUserCheckWindowThreadDesktop(
DWORD
NTAPI
NtUserCheckImeHotKey(
DWORD dwUnknown1,
LPARAM dwUnknown2);
UINT uVirtualKey,
LPARAM lParam);

HWND NTAPI
NtUserChildWindowFromPointEx(
Expand Down
187 changes: 177 additions & 10 deletions win32ss/user/ntuser/ime.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -551,16 +728,6 @@ NtUserNotifyIMEStatus(HWND hwnd, BOOL fOpen, DWORD dwConversion)
return 0;
}

DWORD
NTAPI
NtUserCheckImeHotKey(
DWORD VirtualKey,
LPARAM lParam)
{
STUB;
return 0;
}

BOOL
NTAPI
NtUserDisableThreadIme(
Expand Down

0 comments on commit bbe5fd5

Please sign in to comment.