mirror of
https://github.com/reactos/reactos.git
synced 2025-02-22 16:36:33 +00:00
[NTUSER] Implement NtUserSetImeHotKey (#4350)
- Modify NtUserGetImeHotKey and NtUserSetImeHotKey prototypes. - Define enum SETIMEHOTKEY_ACTION in <undocuser.h>. - Define IMEHOTKEY structure in ime.c. - Add IntGetImeHotKeyLangId, IntAddImeHotKey, IntGetImeHotKeyById, IntGetImeHotKeyByKeyAndLang, IntDeleteImeHotKey, IntFreeImeHotKeys, and IntSetImeHotKey helper functions. - Implement NtUserGetImeHotKey and NtUserSetImeHotKey functions. - Cleanup the IME hotkeys at process exit. CORE-11700
This commit is contained in:
parent
e0fc48d6e2
commit
5d5cc57869
5 changed files with 280 additions and 36 deletions
|
@ -394,6 +394,14 @@ typedef enum _QUERY_INPUT_CONTEXT
|
|||
QIC_DEFAULTIMC
|
||||
} QUERY_INPUT_CONTEXT;
|
||||
|
||||
/* NtUserSetImeHotKey actions */
|
||||
typedef enum tagSETIMEHOTKEY_ACTION
|
||||
{
|
||||
SETIMEHOTKEY_DELETE = 1,
|
||||
SETIMEHOTKEY_ADD,
|
||||
SETIMEHOTKEY_DELETEALL
|
||||
} SETIMEHOTKEY_ACTION;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* defined(__cplusplus) */
|
||||
|
|
|
@ -2388,11 +2388,12 @@ NtUserGetIconSize(
|
|||
LONG *plcx,
|
||||
LONG *plcy);
|
||||
|
||||
BOOL NTAPI
|
||||
NtUserGetImeHotKey(IN DWORD dwHotKey,
|
||||
OUT LPUINT lpuModifiers,
|
||||
OUT LPUINT lpuVKey,
|
||||
OUT LPHKL lphKL);
|
||||
BOOL
|
||||
NTAPI
|
||||
NtUserGetImeHotKey(DWORD dwHotKeyId,
|
||||
LPUINT lpuModifiers,
|
||||
LPUINT lpuVirtualKey,
|
||||
LPHKL lphKL);
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
|
@ -3184,14 +3185,14 @@ NTAPI
|
|||
NtUserSetFocus(
|
||||
HWND hWnd);
|
||||
|
||||
DWORD
|
||||
BOOL
|
||||
NTAPI
|
||||
NtUserSetImeHotKey(
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1,
|
||||
DWORD Unknown2,
|
||||
DWORD Unknown3,
|
||||
DWORD Unknown4);
|
||||
DWORD dwHotKeyId,
|
||||
UINT uModifiers,
|
||||
UINT uVirtualKey,
|
||||
HKL hKL,
|
||||
DWORD dwAction);
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
|
|
|
@ -11,6 +11,14 @@
|
|||
DBG_DEFAULT_CHANNEL(UserMisc);
|
||||
|
||||
#define INVALID_THREAD_ID ((ULONG)-1)
|
||||
#define MOD_KEYS (MOD_CONTROL | MOD_SHIFT | MOD_ALT | MOD_WIN)
|
||||
#define MOD_LEFT_RIGHT (MOD_LEFT | MOD_RIGHT)
|
||||
|
||||
#define LANGID_CHINESE_SIMPLIFIED MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED)
|
||||
#define LANGID_JAPANESE MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT)
|
||||
#define LANGID_KOREAN MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN)
|
||||
#define LANGID_CHINESE_TRADITIONAL MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL)
|
||||
#define LANGID_NEUTRAL MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL)
|
||||
|
||||
#define IS_WND_IMELIKE(pwnd) \
|
||||
(((pwnd)->pcls->style & CS_IME) || \
|
||||
|
@ -37,6 +45,255 @@ HIMC ghIMC = NULL;
|
|||
BOOL gfImeOpen = (BOOL)-1;
|
||||
DWORD gdwImeConversion = (DWORD)-1;
|
||||
|
||||
typedef struct tagIMEHOTKEY
|
||||
{
|
||||
struct tagIMEHOTKEY *pNext;
|
||||
DWORD dwHotKeyId;
|
||||
UINT uVirtualKey;
|
||||
UINT uModifiers;
|
||||
HKL hKL;
|
||||
} IMEHOTKEY, *PIMEHOTKEY;
|
||||
|
||||
PIMEHOTKEY gpImeHotKeyList = NULL;
|
||||
|
||||
static LANGID FASTCALL IntGetImeHotKeyLangId(DWORD dwHotKeyId)
|
||||
{
|
||||
#define IME_CHOTKEY 0x10
|
||||
#define IME_JHOTKEY 0x30
|
||||
#define IME_KHOTKEY 0x50
|
||||
#define IME_THOTKEY 0x70
|
||||
#define IME_XHOTKEY 0x90
|
||||
static const LANGID s_array[] =
|
||||
{
|
||||
/* 0x00 */ (WORD)-1,
|
||||
/* 0x10 */ LANGID_CHINESE_SIMPLIFIED,
|
||||
/* 0x20 */ LANGID_CHINESE_SIMPLIFIED,
|
||||
/* 0x30 */ LANGID_JAPANESE,
|
||||
/* 0x40 */ LANGID_JAPANESE,
|
||||
/* 0x50 */ LANGID_KOREAN,
|
||||
/* 0x60 */ LANGID_KOREAN,
|
||||
/* 0x70 */ LANGID_CHINESE_TRADITIONAL,
|
||||
/* 0x80 */ LANGID_CHINESE_TRADITIONAL
|
||||
};
|
||||
|
||||
if (IME_CHOTKEY <= dwHotKeyId && dwHotKeyId < IME_XHOTKEY)
|
||||
return s_array[(dwHotKeyId & 0xF0) >> 4];
|
||||
return LANGID_NEUTRAL;
|
||||
}
|
||||
|
||||
static VOID FASTCALL IntAddImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
|
||||
{
|
||||
PIMEHOTKEY pNode;
|
||||
|
||||
if (!*ppList)
|
||||
{
|
||||
*ppList = pHotKey;
|
||||
return;
|
||||
}
|
||||
|
||||
for (pNode = *ppList; pNode; pNode = pNode->pNext)
|
||||
{
|
||||
if (!pNode->pNext)
|
||||
{
|
||||
pNode->pNext = pHotKey;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static PIMEHOTKEY FASTCALL IntGetImeHotKeyById(PIMEHOTKEY pList, DWORD dwHotKeyId)
|
||||
{
|
||||
PIMEHOTKEY pNode;
|
||||
for (pNode = pList; pNode; pNode = pNode->pNext)
|
||||
{
|
||||
if (pNode->dwHotKeyId == dwHotKeyId)
|
||||
return pNode;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PIMEHOTKEY APIENTRY
|
||||
IntGetImeHotKeyByKeyAndLang(PIMEHOTKEY pList, UINT uModKeys, UINT uLeftRight,
|
||||
UINT uVirtualKey, LANGID TargetLangId)
|
||||
{
|
||||
PIMEHOTKEY pNode;
|
||||
LANGID LangID;
|
||||
UINT uModifiers;
|
||||
|
||||
for (pNode = pList; pNode; pNode = pNode->pNext)
|
||||
{
|
||||
if (pNode->uVirtualKey != uVirtualKey)
|
||||
continue;
|
||||
|
||||
LangID = IntGetImeHotKeyLangId(pNode->dwHotKeyId);
|
||||
if (LangID != TargetLangId)
|
||||
continue;
|
||||
|
||||
uModifiers = pNode->uModifiers;
|
||||
if (uModifiers & MOD_IGNORE_ALL_MODIFIER)
|
||||
return pNode;
|
||||
|
||||
if ((uModifiers & MOD_KEYS) != uModKeys)
|
||||
continue;
|
||||
|
||||
if ((uModifiers & uLeftRight) || (uModifiers & MOD_LEFT_RIGHT) == uLeftRight)
|
||||
return pNode;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static VOID FASTCALL IntDeleteImeHotKey(PIMEHOTKEY *ppList, PIMEHOTKEY pHotKey)
|
||||
{
|
||||
PIMEHOTKEY pNode;
|
||||
|
||||
if (*ppList == pHotKey)
|
||||
{
|
||||
*ppList = pHotKey->pNext;
|
||||
ExFreePoolWithTag(pHotKey, USERTAG_IMEHOTKEY);
|
||||
return;
|
||||
}
|
||||
|
||||
for (pNode = *ppList; pNode; pNode = pNode->pNext)
|
||||
{
|
||||
if (pNode->pNext == pHotKey)
|
||||
{
|
||||
pNode->pNext = pHotKey->pNext;
|
||||
ExFreePoolWithTag(pHotKey, USERTAG_IMEHOTKEY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID FASTCALL IntFreeImeHotKeys(VOID)
|
||||
{
|
||||
PIMEHOTKEY pNode, pNext;
|
||||
for (pNode = gpImeHotKeyList; pNode; pNode = pNext)
|
||||
{
|
||||
pNext = pNode->pNext;
|
||||
ExFreePoolWithTag(pNode, USERTAG_IMEHOTKEY);
|
||||
}
|
||||
gpImeHotKeyList = NULL;
|
||||
}
|
||||
|
||||
static BOOL APIENTRY
|
||||
IntSetImeHotKey(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DWORD dwAction)
|
||||
{
|
||||
PIMEHOTKEY pNode;
|
||||
LANGID LangId;
|
||||
|
||||
switch (dwAction)
|
||||
{
|
||||
case SETIMEHOTKEY_DELETE:
|
||||
pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
|
||||
if (!pNode)
|
||||
return FALSE;
|
||||
|
||||
IntDeleteImeHotKey(&gpImeHotKeyList, pNode);
|
||||
return TRUE;
|
||||
|
||||
case SETIMEHOTKEY_ADD:
|
||||
if (uVirtualKey == VK_PACKET)
|
||||
return FALSE;
|
||||
|
||||
LangId = IntGetImeHotKeyLangId(dwHotKeyId);
|
||||
if (LangId == LANGID_KOREAN)
|
||||
return FALSE;
|
||||
|
||||
pNode = IntGetImeHotKeyByKeyAndLang(gpImeHotKeyList,
|
||||
(uModifiers & MOD_KEYS),
|
||||
(uModifiers & MOD_LEFT_RIGHT),
|
||||
uVirtualKey, LangId);
|
||||
if (!pNode)
|
||||
pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
|
||||
|
||||
if (pNode)
|
||||
{
|
||||
pNode->uModifiers = uModifiers;
|
||||
pNode->uVirtualKey = uVirtualKey;
|
||||
pNode->hKL = hKL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
pNode = ExAllocatePoolWithTag(PagedPool, sizeof(IMEHOTKEY), USERTAG_IMEHOTKEY);
|
||||
if (!pNode)
|
||||
return FALSE;
|
||||
|
||||
pNode->pNext = NULL;
|
||||
pNode->dwHotKeyId = dwHotKeyId;
|
||||
pNode->uModifiers = uModifiers;
|
||||
pNode->uVirtualKey = uVirtualKey;
|
||||
pNode->hKL = hKL;
|
||||
IntAddImeHotKey(&gpImeHotKeyList, pNode);
|
||||
return TRUE;
|
||||
|
||||
case SETIMEHOTKEY_DELETEALL:
|
||||
IntFreeImeHotKeys();
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL NTAPI
|
||||
NtUserGetImeHotKey(DWORD dwHotKeyId, LPUINT lpuModifiers, LPUINT lpuVirtualKey, LPHKL lphKL)
|
||||
{
|
||||
PIMEHOTKEY pNode = NULL;
|
||||
|
||||
UserEnterExclusive();
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
ProbeForWrite(lpuModifiers, sizeof(UINT), 1);
|
||||
ProbeForWrite(lpuVirtualKey, sizeof(UINT), 1);
|
||||
if (lphKL)
|
||||
ProbeForWrite(lphKL, sizeof(HKL), 1);
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
goto Quit;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
pNode = IntGetImeHotKeyById(gpImeHotKeyList, dwHotKeyId);
|
||||
if (!pNode)
|
||||
goto Quit;
|
||||
|
||||
_SEH2_TRY
|
||||
{
|
||||
*lpuModifiers = pNode->uModifiers;
|
||||
*lpuVirtualKey = pNode->uVirtualKey;
|
||||
if (lphKL)
|
||||
*lphKL = pNode->hKL;
|
||||
}
|
||||
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
pNode = NULL;
|
||||
}
|
||||
_SEH2_END;
|
||||
|
||||
Quit:
|
||||
UserLeave();
|
||||
return !!pNode;
|
||||
}
|
||||
|
||||
BOOL
|
||||
NTAPI
|
||||
NtUserSetImeHotKey(
|
||||
DWORD dwHotKeyId,
|
||||
UINT uModifiers,
|
||||
UINT uVirtualKey,
|
||||
HKL hKL,
|
||||
DWORD dwAction)
|
||||
{
|
||||
BOOL ret;
|
||||
UserEnterExclusive();
|
||||
ret = IntSetImeHotKey(dwHotKeyId, uModifiers, uVirtualKey, hKL, dwAction);
|
||||
UserLeave();
|
||||
return ret;
|
||||
}
|
||||
|
||||
PWND FASTCALL IntGetTopLevelWindow(PWND pwnd)
|
||||
{
|
||||
if (!pwnd)
|
||||
|
@ -194,17 +451,6 @@ Quit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
BOOL WINAPI
|
||||
NtUserGetImeHotKey(IN DWORD dwHotKey,
|
||||
OUT LPUINT lpuModifiers,
|
||||
OUT LPUINT lpuVKey,
|
||||
OUT LPHKL lphKL)
|
||||
{
|
||||
STUB
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static VOID FASTCALL UserSetImeConversionKeyState(PTHREADINFO pti, DWORD dwConversion)
|
||||
{
|
||||
HKL hKL;
|
||||
|
@ -305,20 +551,6 @@ Quit:
|
|||
return 0;
|
||||
}
|
||||
|
||||
DWORD
|
||||
APIENTRY
|
||||
NtUserSetImeHotKey(
|
||||
DWORD Unknown0,
|
||||
DWORD Unknown1,
|
||||
DWORD Unknown2,
|
||||
DWORD Unknown3,
|
||||
DWORD Unknown4)
|
||||
{
|
||||
STUB
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD
|
||||
APIENTRY
|
||||
NtUserCheckImeHotKey(
|
||||
|
|
|
@ -85,6 +85,7 @@ BOOL NTAPI UserSendMouseInput(MOUSEINPUT *pMouseInput, BOOL bInjected);
|
|||
|
||||
/* IMM */
|
||||
UINT FASTCALL IntImmProcessKey(PUSER_MESSAGE_QUEUE, PWND, UINT, WPARAM, LPARAM);
|
||||
VOID FASTCALL IntFreeImeHotKeys(VOID);
|
||||
|
||||
extern DWORD gSystemFS;
|
||||
extern UINT gSystemCPCharSet;
|
||||
|
|
|
@ -180,6 +180,8 @@ UserProcessDestroy(PEPROCESS Process)
|
|||
if (ppiScrnSaver == ppiCurrent)
|
||||
ppiScrnSaver = NULL;
|
||||
|
||||
IntFreeImeHotKeys();
|
||||
|
||||
if (gpwlCache)
|
||||
{
|
||||
ExFreePoolWithTag(gpwlCache, USERTAG_WINDOWLIST);
|
||||
|
|
Loading…
Reference in a new issue