diff options
Diffstat (limited to 'xorg-server/hw/xwin/winkeybd.c')
-rw-r--r-- | xorg-server/hw/xwin/winkeybd.c | 130 |
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; } |