[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
This commit is contained in:
Katayama Hirofumi MZ 2023-12-03 17:33:22 +09:00 committed by GitHub
parent 9ea2222967
commit 75cf6920bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 163 additions and 109 deletions

View file

@ -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.@)
*/

View file

@ -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);
}

View file

@ -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? */
{
if (Imm32ProcessHotKey(hWnd, hIMC, hKL, dwHotKeyID))
/* 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? */
{
/* 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;
}

View file

@ -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);

View file

@ -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))

View file

@ -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) */