aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/xwin/winkeybd.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/xwin/winkeybd.c')
-rw-r--r--xorg-server/hw/xwin/winkeybd.c130
1 files changed, 81 insertions, 49 deletions
diff --git a/xorg-server/hw/xwin/winkeybd.c b/xorg-server/hw/xwin/winkeybd.c
index a3112fffe..a02e22d74 100644
--- a/xorg-server/hw/xwin/winkeybd.c
+++ b/xorg-server/hw/xwin/winkeybd.c
@@ -160,13 +160,13 @@ winKeybdProc (DeviceIntPtr pDeviceInt, int iState)
/* FIXME: Maybe we should use winGetKbdLeds () here? */
defaultKeyboardControl.leds = g_winInfo.keyboard.leds;
- winErrorFVerb(2, "Rules = \"%s\" Model = \"%s\" Layout = \"%s\""
- " Variant = \"%s\" Options = \"%s\"\n",
- g_winInfo.xkb.rules ? g_winInfo.xkb.rules : "none",
- g_winInfo.xkb.model ? g_winInfo.xkb.model : "none",
- g_winInfo.xkb.layout ? g_winInfo.xkb.layout : "none",
- g_winInfo.xkb.variant ? g_winInfo.xkb.variant : "none",
- g_winInfo.xkb.options ? g_winInfo.xkb.options : "none");
+ winDebug("Rules = \"%s\" Model = \"%s\" Layout = \"%s\""
+ " Variant = \"%s\" Options = \"%s\"\n",
+ g_winInfo.xkb.rules ? g_winInfo.xkb.rules : "none",
+ g_winInfo.xkb.model ? g_winInfo.xkb.model : "none",
+ g_winInfo.xkb.layout ? g_winInfo.xkb.layout : "none",
+ g_winInfo.xkb.variant ? g_winInfo.xkb.variant : "none",
+ g_winInfo.xkb.options ? g_winInfo.xkb.options : "none");
InitKeyboardDeviceStruct (pDeviceInt,
&g_winInfo.xkb,
@@ -182,7 +182,7 @@ winKeybdProc (DeviceIntPtr pDeviceInt, int iState)
}
else
{
- winErrorFVerb (1, "winKeybdProc - Error initializing keyboard AutoRepeat\n");
+ winDebug ("winKeybdProc - Error initializing keyboard AutoRepeat\n");
}
break;
@@ -276,6 +276,21 @@ winRestoreModeKeyStates (void)
internalKeyStates = XkbStateFieldFromRec(&inputInfo.keyboard->key->xkbInfo->state);
winDebug("winRestoreModeKeyStates: state %d\n", internalKeyStates);
+ {
+ /* Make sure the message queue is empty, otherwise the GetKeyState will not always
+ return the correct state of the numlock key, capslock key, ...
+ This is mainly because this function is called from the WM_SETFOCUS handler.
+ From MSDN GetKeyState: The key status returned from this function changes as a thread
+ reads key messages from its message queue.*/
+ MSG msg;
+
+ /* Process all messages on our queue */
+ while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
+ {
+ DispatchMessage (&msg);
+ }
+ }
+
/*
* NOTE: The C XOR operator, ^, will not work here because it is
* a bitwise operator, not a logical operator. C does not
@@ -328,8 +343,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 +360,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 +392,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 +429,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);
-
- /* 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,7 +455,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;
}