summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver Schmidt <oschmidt-mailinglists@gmx.de>2011-09-05 13:32:01 +0100
committerJon TURNEY <jon.turney@dronecode.org.uk>2012-01-26 14:40:28 +0000
commitb8b0b841a0e7cfcecaf0b6a5aa67e1b4499374d9 (patch)
treebdea7387f718a98f3f2ae855662894945c39d03d
parent3d3114d55a2a323f8d49c3549a0dfdf9d4acf89d (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.c95
-rw-r--r--hw/xwin/winwndproc.c8
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);