diff options
author | Oliver Schmidt <oschmidt-mailinglists@gmx.de> | 2011-09-05 13:32:01 +0100 |
---|---|---|
committer | Jon TURNEY <jon.turney@dronecode.org.uk> | 2012-01-26 14:40:28 +0000 |
commit | b8b0b841a0e7cfcecaf0b6a5aa67e1b4499374d9 (patch) | |
tree | bdea7387f718a98f3f2ae855662894945c39d03d | |
parent | 3d3114d55a2a323f8d49c3549a0dfdf9d4acf89d (diff) |
hw/xwin: Fix AltGr key sometimes firing an additional Ctrl-L key
I also had problems with the AltGr key. These could reliably
be reproduced by holding the AltGr for some seconds (causing
Windows generating auto repeat events)
I discovered that the mechanism in winkeybd.c function
winIsFakeCtrl_L had a problem if PeekMessage cannot obtain
the next Alt_R message because it is not there yet.
I prepared a patch that remembers the last Ctrl_L event and
reacts on a later Alt_R.
It was also necessary to alter the order in winWindowProc() in
winwndproc.c: the invocation of winIsFakeCtrl_L had to be done
before discarding auto-repeated key presses, as winIsFakeCtrl_L()
now has an internal state which must be updated by all key events.
Reviewed-by: Jon TURNEY <jon.turney@dronecode.org.uk>
Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
-rw-r--r-- | hw/xwin/winkeybd.c | 95 | ||||
-rw-r--r-- | hw/xwin/winwndproc.c | 8 |
2 files changed, 60 insertions, 43 deletions
diff --git a/hw/xwin/winkeybd.c b/hw/xwin/winkeybd.c index a3112fffe..0496c40ab 100644 --- a/hw/xwin/winkeybd.c +++ b/hw/xwin/winkeybd.c @@ -328,8 +328,12 @@ winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam) LONG lTime; Bool fReturn; + static Bool lastWasControlL = FALSE; + static UINT lastMessage; + static LONG lastTime; + /* - * Fake Ctrl_L presses will be followed by an Alt_R keypress + * Fake Ctrl_L presses will be followed by an Alt_R press * with the same timestamp as the Ctrl_L press. */ if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN) @@ -341,34 +345,31 @@ winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam) /* Get time of current message */ lTime = GetMessageTime (); - /* Look for fake Ctrl_L preceeding an Alt_R press. */ + /* Look for next press message */ fReturn = PeekMessage (&msgNext, NULL, WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE); - /* - * Try again if the first call fails. - * NOTE: This usually happens when TweakUI is enabled. - */ - if (!fReturn) - { - /* Voodoo to make sure that the Alt_R message has posted */ - Sleep (0); - - /* Look for fake Ctrl_L preceeding an Alt_R press. */ - fReturn = PeekMessage (&msgNext, NULL, - WM_KEYDOWN, WM_SYSKEYDOWN, - PM_NOREMOVE); - } - if (msgNext.message != WM_KEYDOWN && msgNext.message != WM_SYSKEYDOWN) + if (fReturn && msgNext.message != WM_KEYDOWN && msgNext.message != WM_SYSKEYDOWN) fReturn = 0; + if (!fReturn) + { + lastWasControlL = TRUE; + lastMessage = message; + lastTime = lTime; + } + else + { + lastWasControlL = FALSE; + } + /* Is next press an Alt_R with the same timestamp? */ if (fReturn && msgNext.wParam == VK_MENU && msgNext.time == lTime && (HIWORD (msgNext.lParam) & KF_EXTENDED)) { - /* + /* * Next key press is Alt_R with same timestamp as current * Ctrl_L message. Therefore, this Ctrl_L press is a fake * event, so discard it. @@ -376,12 +377,35 @@ winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam) return TRUE; } } + /* + * Sometimes, the Alt_R press message is not yet posted when the + * fake Ctrl_L press message arrives (even though it has the + * same timestamp), so check for an Alt_R press message that has + * arrived since the last Ctrl_L message. + */ + else if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN) + && wParam == VK_MENU + && (HIWORD (lParam) & KF_EXTENDED)) + { + /* Got a Alt_R press */ - /* + if (lastWasControlL) + { + lTime = GetMessageTime (); + + if (lastTime == lTime) + { + /* Undo the fake Ctrl_L press by sending a fake Ctrl_L release */ + winSendKeyEvent (KEY_LCtrl, FALSE); + } + lastWasControlL = FALSE; + } + } + /* * Fake Ctrl_L releases will be followed by an Alt_R release * with the same timestamp as the Ctrl_L release. */ - if ((message == WM_KEYUP || message == WM_SYSKEYUP) + else if ((message == WM_KEYUP || message == WM_SYSKEYUP) && wParam == VK_CONTROL && (HIWORD (lParam) & KF_EXTENDED) == 0) { @@ -390,29 +414,16 @@ winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam) /* Get time of current message */ lTime = GetMessageTime (); - /* Look for fake Ctrl_L release preceeding an Alt_R release. */ + /* Look for next release message */ fReturn = PeekMessage (&msgNext, NULL, - WM_KEYUP, WM_SYSKEYUP, + WM_KEYUP, WM_SYSKEYUP, PM_NOREMOVE); - /* - * Try again if the first call fails. - * NOTE: This usually happens when TweakUI is enabled. - */ - if (!fReturn) - { - /* Voodoo to make sure that the Alt_R message has posted */ - Sleep (0); + if (fReturn && msgNext.message != WM_KEYUP && msgNext.message != WM_SYSKEYUP) + fReturn = 0; - /* Look for fake Ctrl_L release preceeding an Alt_R release. */ - fReturn = PeekMessage (&msgNext, NULL, - WM_KEYUP, WM_SYSKEYUP, - PM_NOREMOVE); - } + lastWasControlL = FALSE; - if (msgNext.message != WM_KEYUP && msgNext.message != WM_SYSKEYUP) - fReturn = 0; - /* Is next press an Alt_R with the same timestamp? */ if (fReturn && (msgNext.message == WM_KEYUP @@ -429,7 +440,13 @@ winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam) return TRUE; } } - + else + { + /* On any other press or release message, we don't have a + potentially fake Ctrl_L to worry about anymore... */ + lastWasControlL = FALSE; + } + /* Not a fake control left press/release */ return FALSE; } diff --git a/hw/xwin/winwndproc.c b/hw/xwin/winwndproc.c index a89857a14..ae284b7ad 100644 --- a/hw/xwin/winwndproc.c +++ b/hw/xwin/winwndproc.c @@ -1060,6 +1060,10 @@ winWindowProc (HWND hwnd, UINT message, if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL) break; + /* Discard fake Ctrl_L events that precede AltGR on non-US keyboards */ + if (winIsFakeCtrl_L (message, wParam, lParam)) + return 0; + /* * Discard presses generated from Windows auto-repeat */ @@ -1080,10 +1084,6 @@ winWindowProc (HWND hwnd, UINT message, } } - /* Discard fake Ctrl_L presses that precede AltGR on non-US keyboards */ - if (winIsFakeCtrl_L (message, wParam, lParam)) - return 0; - /* Translate Windows key code to X scan code */ winTranslateKey (wParam, lParam, &iScanCode); |