fix(windows): reduce the number of places km scan flag

The SCAN_FLAG_KEYMAN_KEY_EVENT was checked in OnKey pressess as well
as an early return option in _KeymanProcessKeystroke. This change
removes the extra and allows _KeymanProcessKeystroke, to be the
central place for code readablitiy and maintainablity.

It also adds a processToggleChange call in kmhook_getmessage as
it is sometimes called before the TIP hook. the call is also idempotent
This commit is contained in:
rc-swag 2026-03-20 09:22:35 +10:00
parent f4c5d9df02
commit c1c3952717
4 changed files with 28 additions and 41 deletions

View file

@ -142,7 +142,7 @@ BOOL TIPProcessKeyInternal(
// We need to check if the last key is the same as `wparam` or `VK_PROCESSKEY`
// (VK_PROCESSKEY is what synthesised keys on the KeyUP have).
// Just the lastscan code is not sufficient because we have the case where
// Shift press is processed here before the low level keyboard hook.
// Shift press is processed here before the kmhook_getmessage hook.
if (((_td->LastKey == wParam || _td->LastKey == VK_PROCESSKEY) && _td->LastScanCode == SCAN_FLAG_KEYMAN_KEY_EVENT)
|| scan == SCAN_FLAG_KEYMAN_KEY_EVENT) {
if (wParam == VK_CAPITAL && !isUp) {
@ -150,7 +150,8 @@ BOOL TIPProcessKeyInternal(
// a Caps Lock event
ProcessToggleChange((UINT)wParam); // I4793
}
SendDebugMessageFormat("Virtual Key was generated by Keyman [Scan=0xFF]");
// TODO: should we clear the scan code flag even though we are now finished?
SendDebugMessageFormat("Virtual Key was generated by Keyman [Scan=%x wParam=%x] [LastKey=%x LastScanCode=%x]");
return_SendDebugExit(FALSE);
}

View file

@ -174,8 +174,11 @@ LRESULT _kmnGetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
if (mp->wParam != VK_BACK) {
if(scan == SCAN_FLAG_KEYMAN_KEY_EVENT) {
mp->lParam = (mp->lParam & 0xFF00FFFFL) | (MapVirtualKey((UINT)mp->wParam, 0) << 16);
SendDebugMessageFormat("wm_keyman clear `SCAN_FLAG_KEYMAN_KEY_EVENT` new_wParam=%x new_lParam=%x LastKey=%x LastScanCode=%x",
mp->wParam, mp->lParam, _td->LastKey, _td->LastScanCode);
if (mp->wParam == VK_CAPITAL) {
ProcessToggleChange(VK_CAPITAL);
}
SendDebugMessageFormat("WMKEY=%x clear `SCAN_FLAG_KEYMAN_KEY_EVENT` new_wParam=%x new_lParam=%x LastKey=%x LastScanCode=%x",
mp->message, mp->wParam, mp->lParam, _td->LastKey, _td->LastScanCode);
}
}
}

View file

@ -178,17 +178,10 @@ STDAPI CKMTipTextService::OnTestKeyDown(ITfContext *pContext, WPARAM wParam, LPA
{
SendDebugEntry();
LogKey(0, wParam, lParam);
// If the keystroke is a Keyman-generated key, ignore it
// But we need to pass Caps Lock through, even if we generated it, so we can track Caps Lock state.
// TODO: Fix magic constants
if ((lParam & 0x00FF0000L) == 0xFF0000L &&
wParam != VK_CAPITAL) {
*pfEaten = FALSE;
}
else {
*pfEaten = _KeymanProcessKeystroke(pContext, wParam, lParam, FALSE, FALSE); // I3588
// SendDebugMessageFormat("pfEaten=%s", *pfEaten ? "TRUE" : "FALSE");
}
*pfEaten = _KeymanProcessKeystroke(pContext, wParam, lParam, FALSE, FALSE); // I3588
SendDebugMessageFormat(L"pfEaten=%s, wParam=%x, lParam=%x", *pfEaten ? L"TRUE" : L"FALSE", wParam, lParam);
// SendDebugMessageFormat("pfEaten=%s", *pfEaten ? "TRUE" : "FALSE");
SendDebugExit();
return S_OK;
}
@ -205,8 +198,9 @@ STDAPI CKMTipTextService::OnKeyDown(ITfContext *pContext, WPARAM wParam, LPARAM
{
SendDebugEntry();
LogKey(1, wParam, lParam);
fEatenBuf[wParam] = *pfEaten = _KeymanProcessKeystroke(pContext, wParam, lParam, TRUE, FALSE); // I3588
// SendDebugMessageFormat("pfEaten=%s", *pfEaten ? "TRUE" : "FALSE");
fEatenBuf[wParam] = *pfEaten = _KeymanProcessKeystroke(pContext, wParam, lParam, TRUE, FALSE); // I3588
SendDebugMessageFormat(L"pfEaten=%s wParam=%x lParam=%x", *pfEaten ? L"TRUE" : L"FALSE", wParam, lParam);
// SendDebugMessageFormat("pfEaten=%s", *pfEaten ? "TRUE" : "FALSE");
SendDebugExit();
return S_OK;
}
@ -222,17 +216,11 @@ STDAPI CKMTipTextService::OnTestKeyUp(ITfContext *pContext, WPARAM wParam, LPARA
{
SendDebugEntry();
LogKey(2, wParam, lParam);
// If the keystroke is a Keyman-generated key, ignore it
// But we need to pass Caps Lock through, even if we generated it, so we can track Caps Lock state.
if ((lParam & 0x00FF0000L) == 0xFF0000L &&
wParam != VK_CAPITAL) { // I3566
*pfEaten = FALSE;
}
else {
_KeymanProcessKeystroke(pContext, wParam, lParam, FALSE, FALSE); // I3588
*pfEaten = fEatenBuf[wParam];
}
// SendDebugMessageFormat("pfEaten=%s", *pfEaten ? "TRUE" : "FALSE");
_KeymanProcessKeystroke(pContext, wParam, lParam, FALSE, FALSE); // I3588
*pfEaten = fEatenBuf[wParam];
// SendDebugMessageFormat("pfEaten=%s", *pfEaten ? "TRUE" : "FALSE");
SendDebugMessageFormat(L"pfEaten=%s wParam=%x lParam=%x", *pfEaten ? L"TRUE" : L"FALSE", wParam, lParam);
SendDebugExit();
return S_OK;
}
@ -251,16 +239,11 @@ STDAPI CKMTipTextService::OnKeyUp(ITfContext *pContext, WPARAM wParam, LPARAM lP
LogKey(3, wParam, lParam);
// If the keystroke is a Keyman-generated key, ignore it
// But we need to pass Caps Lock through, even if we generated it, so we can track Caps Lock state.
if ((lParam & 0x00FF0000L) == 0xFF0000L &&
wParam != VK_CAPITAL) { // I3566 // I3605
*pfEaten = FALSE;
}
else
{
_KeymanProcessKeystroke(pContext, wParam, lParam, TRUE, FALSE); // I3588 // I3605
*pfEaten = fEatenBuf[wParam];
}
// SendDebugMessageFormat("pfEaten=%s", *pfEaten ? "TRUE" : "FALSE");
_KeymanProcessKeystroke(pContext, wParam, lParam, TRUE, FALSE); // I3588 // I3605
*pfEaten = fEatenBuf[wParam];
SendDebugMessageFormat(L"pfEaten=%s wParam=%x lParam=%x", *pfEaten ? L"TRUE" : L"FALSE", wParam, lParam);
SendDebugExit();
return S_OK;
}

View file

@ -102,15 +102,15 @@ BOOL CKMTipTextService::_KeymanProcessKeystroke(ITfContext *pContext, WPARAM wPa
// Don't process Unicode characters injected or ProcessKey events which are generated by Windows
if (wParam == VK_PACKET || wParam == VK_PROCESSKEY) {
SendDebugMessageFormat(L"wParam=%x early return FALSE", wParam);
return FALSE; // I3608 // I4201
}
SendDebugEntry();
SendDebugMessageFormat(L"%x %x %s %s ex=%x", wParam, lParam, fUpdate ? L"update" : L"", fPreserved ? L"preserved" : L"", GetMessageExtraInfo()); // I4378
// Don't process keystrokes generated by Keyman (scan code = 0xFF)
// But we need to pass Caps Lock through, even if we generated it, so we can track Caps Lock state.
// TODO: This is done in multiple places, but we probably only need to do it once
// Don't process keystrokes generated by Keyman (scan code = 0xFF = SCAN_FLAG_KEYMAN_KEY_EVENT)
// But we need to pass Caps Lock through to the keyman engine (but not the core), even if we generated it, so we can track Caps Lock state.
if ((lParam & 0xFF0000) == 0xFF0000 &&
wParam != VK_CAPITAL) {
return_SendDebugExit(FALSE);