[Windows] Serialized input: don't trigger on console windows

This commit is contained in:
Marc Durdin 2018-10-05 14:40:57 +10:00
parent e8ef3d0e23
commit 56115da652
4 changed files with 52 additions and 4 deletions

View file

@ -1,5 +1,8 @@
# Keyman Desktop Version History
## 2018-10-05 11.0 alpha
* Rework keyboard input to serialize input queue to resolve modifier key stickiness (#1229)
## 2018-06-28 10.0.1200 stable
* 10.0 stable release

View file

@ -407,7 +407,10 @@ void DebugMessage(LPMSG msg, WPARAM wParam) // I2908
else if(msg->message == wm_keymankeyup)
wsprintf(ds, "DebugMessage(%x, wm_keymankeyup: %s lParam: %X) [message flags: %x time: %d]", msg->hwnd,
Debug_VirtualKey((WORD) msg->wParam), msg->lParam, wParam, msg->time);
else if(msg->message == WM_KEYDOWN || msg->message == WM_KEYUP || msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSKEYUP)
else if (msg->message == wm_keyman_keyevent)
wsprintf(ds, "DebugMessage(%x, wm_keyman_keyevent: %s lParam: %X) [message flags: %x time: %d]", msg->hwnd,
Debug_VirtualKey((WORD)msg->wParam), msg->lParam, wParam, msg->time);
else if(msg->message == WM_KEYDOWN || msg->message == WM_KEYUP || msg->message == WM_SYSKEYDOWN || msg->message == WM_SYSKEYUP)
wsprintf(ds, "DebugMessage(%x, %s, wParam: %s, lParam: %X) [message flags: %x time: %d extra: %x]",
msg->hwnd,
msgnames[msg->message-WM_KEYDOWN],

View file

@ -66,6 +66,30 @@ LPARAM LLKHFFlagstoWMKeymanKeyEventFlags(PKBDLLHOOKSTRUCT hs) {
((hs->flags & LLKHF_UP) ? KEYEVENTF_KEYUP : 0);
}
/*
We don't attempt to serialize input to the console windows because they
behave somewhat differently to normal windows. For now, this should be
sufficient. In the future, we may want to find a way to interrogate the
focused process to find out which window actually has focus for posting
messages, because we appear to post the messages to the wrong thread
for console windows.
*/
BOOL IsConsoleWindow(HWND hwnd) {
static HWND last_hwnd = 0;
static BOOL last_isConsoleWindow = FALSE;
if (last_hwnd == hwnd) {
return last_isConsoleWindow;
}
char buf[64];
last_hwnd = hwnd;
last_isConsoleWindow = GetClassName(hwnd, buf, 64) && !strcmp(buf, "ConsoleWindowClass");
return last_isConsoleWindow;
}
LRESULT _kmnLowLevelKeyboardProc(
_In_ int nCode,
_In_ WPARAM wParam,
@ -162,8 +186,24 @@ LRESULT _kmnLowLevelKeyboardProc(
*/
if (flag_ShouldSerializeInput) {
PostThreadMessage(GetWindowThreadProcessId(GetForegroundWindow(), NULL), wm_keyman_keyevent, hs->vkCode, LLKHFFlagstoWMKeymanKeyEventFlags(hs));
return 1;
GUITHREADINFO gui = { 0 };
gui.cbSize = sizeof(GUITHREADINFO);
if (GetGUIThreadInfo(NULL, &gui)) {
SendDebugMessageFormat(0, sdmGlobal, 0, "LowLevelHook: Active=%x Focus=%x Key=%s flags=%x",
gui.hwndActive, gui.hwndFocus, Debug_VirtualKey((WORD)hs->vkCode), LLKHFFlagstoWMKeymanKeyEventFlags(hs));
HWND hwnd = gui.hwndFocus ? gui.hwndFocus : gui.hwndActive;
if (!IsConsoleWindow(hwnd)) {
PostThreadMessage(GetWindowThreadProcessId(hwnd, NULL), wm_keyman_keyevent, hs->vkCode, LLKHFFlagstoWMKeymanKeyEventFlags(hs));
return 1;
}
else {
SendDebugMessageFormat(0, sdmGlobal, 0, "LowLevelHook: console window, not serializing");
}
}
else {
SendDebugMessageFormat(0, sdmGlobal, 0, "LowLevelHook: Failed to get Gui thread info with error %d", GetLastError());
}
}
return CallNextHookEx(Globals::get_hhookLowLevelKeyboardProc(), nCode, wParam, lParam);

View file

@ -141,7 +141,9 @@ LRESULT _kmnGetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
if(!InitialiseProcess(mp->hwnd)) return CallNextHookEx(Globals::get_hhookGetMessage(), nCode, wParam, lParam);
}
if (mp->message >= WM_KEYFIRST && mp->message <= WM_KEYLAST && ShouldDebug(sdmMessage)) {
if (((mp->message >= WM_KEYFIRST && mp->message <= WM_KEYLAST) || mp->message == wm_keymankeydown || mp->message == wm_keymankeyup ||
mp->message == wm_keyman_keyevent)
&& ShouldDebug(sdmMessage)) {
DebugMessage(mp, wParam);
}