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;
|
LONG lTime;
|
||||||
Bool fReturn;
|
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.
|
* with the same timestamp as the Ctrl_L press.
|
||||||
*/
|
*/
|
||||||
if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
|
if ((message == WM_KEYDOWN || message == WM_SYSKEYDOWN)
|
||||||
|
@ -341,34 +345,31 @@ winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
/* Get time of current message */
|
/* Get time of current message */
|
||||||
lTime = GetMessageTime ();
|
lTime = GetMessageTime ();
|
||||||
|
|
||||||
/* Look for fake Ctrl_L preceeding an Alt_R press. */
|
/* Look for next press message */
|
||||||
fReturn = PeekMessage (&msgNext, NULL,
|
fReturn = PeekMessage (&msgNext, NULL,
|
||||||
WM_KEYDOWN, WM_SYSKEYDOWN,
|
WM_KEYDOWN, WM_SYSKEYDOWN,
|
||||||
PM_NOREMOVE);
|
PM_NOREMOVE);
|
||||||
|
|
||||||
/*
|
if (fReturn && msgNext.message != WM_KEYDOWN && msgNext.message != WM_SYSKEYDOWN)
|
||||||
* 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)
|
|
||||||
fReturn = 0;
|
fReturn = 0;
|
||||||
|
|
||||||
|
if (!fReturn)
|
||||||
|
{
|
||||||
|
lastWasControlL = TRUE;
|
||||||
|
lastMessage = message;
|
||||||
|
lastTime = lTime;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastWasControlL = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* Is next press an Alt_R with the same timestamp? */
|
/* Is next press an Alt_R with the same timestamp? */
|
||||||
if (fReturn && msgNext.wParam == VK_MENU
|
if (fReturn && msgNext.wParam == VK_MENU
|
||||||
&& msgNext.time == lTime
|
&& msgNext.time == lTime
|
||||||
&& (HIWORD (msgNext.lParam) & KF_EXTENDED))
|
&& (HIWORD (msgNext.lParam) & KF_EXTENDED))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Next key press is Alt_R with same timestamp as current
|
* Next key press is Alt_R with same timestamp as current
|
||||||
* Ctrl_L message. Therefore, this Ctrl_L press is a fake
|
* Ctrl_L message. Therefore, this Ctrl_L press is a fake
|
||||||
* event, so discard it.
|
* event, so discard it.
|
||||||
|
@ -376,12 +377,35 @@ winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
return TRUE;
|
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
|
* Fake Ctrl_L releases will be followed by an Alt_R release
|
||||||
* with the same timestamp as the Ctrl_L 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
|
&& wParam == VK_CONTROL
|
||||||
&& (HIWORD (lParam) & KF_EXTENDED) == 0)
|
&& (HIWORD (lParam) & KF_EXTENDED) == 0)
|
||||||
{
|
{
|
||||||
|
@ -390,29 +414,16 @@ winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
/* Get time of current message */
|
/* Get time of current message */
|
||||||
lTime = GetMessageTime ();
|
lTime = GetMessageTime ();
|
||||||
|
|
||||||
/* Look for fake Ctrl_L release preceeding an Alt_R release. */
|
/* Look for next release message */
|
||||||
fReturn = PeekMessage (&msgNext, NULL,
|
fReturn = PeekMessage (&msgNext, NULL,
|
||||||
WM_KEYUP, WM_SYSKEYUP,
|
WM_KEYUP, WM_SYSKEYUP,
|
||||||
PM_NOREMOVE);
|
PM_NOREMOVE);
|
||||||
|
|
||||||
/*
|
if (fReturn && msgNext.message != WM_KEYUP && msgNext.message != WM_SYSKEYUP)
|
||||||
* 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)
|
|
||||||
fReturn = 0;
|
fReturn = 0;
|
||||||
|
|
||||||
|
lastWasControlL = FALSE;
|
||||||
|
|
||||||
/* Is next press an Alt_R with the same timestamp? */
|
/* Is next press an Alt_R with the same timestamp? */
|
||||||
if (fReturn
|
if (fReturn
|
||||||
&& (msgNext.message == WM_KEYUP
|
&& (msgNext.message == WM_KEYUP
|
||||||
|
@ -429,7 +440,13 @@ winIsFakeCtrl_L (UINT message, WPARAM wParam, LPARAM lParam)
|
||||||
return TRUE;
|
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 */
|
/* Not a fake control left press/release */
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1060,6 +1060,10 @@ winWindowProc (HWND hwnd, UINT message,
|
||||||
if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
|
if ((wParam == VK_LWIN || wParam == VK_RWIN) && !g_fKeyboardHookLL)
|
||||||
break;
|
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
|
* 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 */
|
/* Translate Windows key code to X scan code */
|
||||||
winTranslateKey (wParam, lParam, &iScanCode);
|
winTranslateKey (wParam, lParam, &iScanCode);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user