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>
This commit is contained in:
parent
3d3114d55a
commit
b8b0b841a0
|
@ -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,28 +345,25 @@ 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
|
||||
|
@ -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,
|
||||
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 release preceeding an Alt_R release. */
|
||||
fReturn = PeekMessage (&msgNext, NULL,
|
||||
WM_KEYUP, WM_SYSKEYUP,
|
||||
PM_NOREMOVE);
|
||||
}
|
||||
|
||||
if (msgNext.message != WM_KEYUP && msgNext.message != WM_SYSKEYUP)
|
||||
if (fReturn && msgNext.message != WM_KEYUP && msgNext.message != WM_SYSKEYUP)
|
||||
fReturn = 0;
|
||||
|
||||
lastWasControlL = FALSE;
|
||||
|
||||
/* Is next press an Alt_R with the same timestamp? */
|
||||
if (fReturn
|
||||
&& (msgNext.message == WM_KEYUP
|
||||
|
@ -429,6 +440,12 @@ 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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user