diff options
Diffstat (limited to 'hw/xwin/winkeybd.c')
-rw-r--r-- | hw/xwin/winkeybd.c | 290 |
1 files changed, 36 insertions, 254 deletions
diff --git a/hw/xwin/winkeybd.c b/hw/xwin/winkeybd.c index 00586c25b..3748dc027 100644 --- a/hw/xwin/winkeybd.c +++ b/hw/xwin/winkeybd.c @@ -34,17 +34,24 @@ #ifdef HAVE_XWIN_CONFIG_H #include <xwin-config.h> #endif + #include "win.h" -#include "winkeybd.h" +#include "wmutil/scancodes.h" +#include "wmutil/keyboard.h" #include "winconfig.h" #include "winmsg.h" #include "xkbsrv.h" +#include "dixgrabs.h" /* C does not have a logical XOR operator, so we use a macro instead */ #define LOGICAL_XOR(a,b) ((!(a) && (b)) || ((a) && !(b))) -static Bool g_winKeyState[NUM_KEYCODES]; +#define AltMask Mod1Mask +#define NumLockMask Mod2Mask +#define AltLangMask Mod3Mask +#define KanaMask Mod4Mask +#define ScrollLockMask Mod5Mask /* * Local prototypes @@ -56,68 +63,6 @@ static void static void winKeybdCtrl(DeviceIntPtr pDevice, KeybdCtrl * pCtrl); -/* - * Translate a Windows WM_[SYS]KEY(UP/DOWN) message - * into an ASCII scan code. - * - * We do this ourselves, rather than letting Windows handle it, - * because Windows tends to munge the handling of special keys, - * like AltGr on European keyboards. - */ - -int -winTranslateKey(WPARAM wParam, LPARAM lParam) -{ - int iKeyFixup = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 1]; - int iKeyFixupEx = g_iKeyMap[wParam * WIN_KEYMAP_COLS + 2]; - int iParam = HIWORD(lParam); - int iParamScanCode = LOBYTE(iParam); - int iScanCode; - - winDebug("winTranslateKey: wParam %08x lParam %08x\n", (int)wParam, (int)lParam); - -/* WM_ key messages faked by Vista speech recognition (WSR) don't have a - * scan code. - * - * Vocola 3 (Rick Mohr's supplement to WSR) uses - * System.Windows.Forms.SendKeys.SendWait(), which appears always to give a - * scan code of 1 - */ - if (iParamScanCode <= 1) { - if (VK_PRIOR <= wParam && wParam <= VK_DOWN) - /* Trigger special case table to translate to extended - * keycode, otherwise if num_lock is on, we can get keypad - * numbers instead of navigation keys. */ - iParam |= KF_EXTENDED; - else - iParamScanCode = MapVirtualKeyEx(wParam, - /*MAPVK_VK_TO_VSC */ 0, - GetKeyboardLayout(0)); - } - - /* Branch on special extended, special non-extended, or normal key */ - if ((iParam & KF_EXTENDED) && iKeyFixupEx) - iScanCode = iKeyFixupEx; - else if (iKeyFixup) - iScanCode = iKeyFixup; - else if (wParam == 0 && iParamScanCode == 0x70) - iScanCode = KEY_HKTG; - else - switch (iParamScanCode) { - case 0x70: - iScanCode = KEY_HKTG; - break; - case 0x73: - iScanCode = KEY_BSlash2; - break; - default: - iScanCode = iParamScanCode; - break; - } - - return iScanCode; -} - /* Ring the keyboard bell (system speaker on PCs) */ static void winKeybdBell(int iPercent, DeviceIntPtr pDeviceInt, void *pCtrl, int iClass) @@ -337,209 +282,46 @@ winRestoreModeKeyStates(void) */ } -/* - * Look for the lovely fake Control_L press/release generated by Windows - * when AltGr is pressed/released on a non-U.S. keyboard. - */ - -Bool -winIsFakeCtrl_L(UINT message, WPARAM wParam, LPARAM lParam) -{ - MSG msgNext; - LONG lTime; - Bool fReturn; - - static Bool lastWasControlL = FALSE; - static LONG lastTime; - - /* - * 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) - && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) { - /* Got a Ctrl_L press */ - - /* Get time of current message */ - lTime = GetMessageTime(); - - /* Look for next press message */ - fReturn = PeekMessage(&msgNext, NULL, - WM_KEYDOWN, WM_SYSKEYDOWN, PM_NOREMOVE); - - if (fReturn && msgNext.message != WM_KEYDOWN && - msgNext.message != WM_SYSKEYDOWN) - fReturn = 0; - - if (!fReturn) { - lastWasControlL = TRUE; - 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. - */ - 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. - */ - else if ((message == WM_KEYUP || message == WM_SYSKEYUP) - && wParam == VK_CONTROL && (HIWORD(lParam) & KF_EXTENDED) == 0) { - /* Got a Ctrl_L release */ - - /* Get time of current message */ - lTime = GetMessageTime(); - - /* Look for next release message */ - fReturn = PeekMessage(&msgNext, NULL, - WM_KEYUP, WM_SYSKEYUP, PM_NOREMOVE); - - 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 || msgNext.message == WM_SYSKEYUP) - && msgNext.wParam == VK_MENU - && msgNext.time == lTime - && (HIWORD(msgNext.lParam) & KF_EXTENDED)) { - /* - * Next key release is Alt_R with same timestamp as current - * Ctrl_L message. Therefore, this Ctrl_L release is a fake - * event, so discard it. - */ - 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; -} - -/* - * Lift any modifier keys that are pressed - */ - void -winKeybdReleaseKeys(void) +winSendKeyEventCallback(DWORD dwKey, bool fDown) { - int i; - #ifdef HAS_DEVWINDOWS /* Verify that the mi input system has been initialized */ if (g_fdMessageQueue == WIN_FD_INVALID) return; #endif - /* Loop through all keys */ - for (i = 0; i < NUM_KEYCODES; ++i) { - /* Pop key if pressed */ - if (g_winKeyState[i]) - winSendKeyEvent(i, FALSE); - - /* Reset pressed flag for keys */ - g_winKeyState[i] = FALSE; - } + QueueKeyboardEvents(g_pwinKeyboard, fDown ? KeyPress : KeyRelease, + dwKey); } /* - * Take a raw X key code and send an up or down event for it. - * - * Thanks to VNC for inspiration, though it is a simple function. */ - -void -winSendKeyEvent(DWORD dwKey, Bool fDown) -{ - /* - * When alt-tabing between screens we can get phantom key up messages - * Here we only pass them through it we think we should! - */ - if (g_winKeyState[dwKey] == FALSE && fDown == FALSE) - return; - - /* Update the keyState map */ - g_winKeyState[dwKey] = fDown; - - QueueKeyboardEvents(g_pwinKeyboard, fDown ? KeyPress : KeyRelease, - dwKey + MIN_KEYCODE); - - winDebug("winSendKeyEvent: dwKey: %u, fDown: %u\n", (unsigned int)dwKey, fDown); -} - -BOOL -winCheckKeyPressed(WPARAM wParam, LPARAM lParam) +int +XkbDDXPrivate(DeviceIntPtr dev,KeyCode key,XkbAction *act) { - switch (wParam) { - case VK_CONTROL: - if ((lParam & 0x1ff0000) == 0x11d0000 && g_winKeyState[KEY_RCtrl]) - return TRUE; - if ((lParam & 0x1ff0000) == 0x01d0000 && g_winKeyState[KEY_LCtrl]) - return TRUE; - break; - case VK_SHIFT: - if ((lParam & 0x1ff0000) == 0x0360000 && g_winKeyState[KEY_ShiftR]) - return TRUE; - if ((lParam & 0x1ff0000) == 0x02a0000 && g_winKeyState[KEY_ShiftL]) - return TRUE; - break; - default: - return TRUE; + XkbAnyAction *xf86act = &(act->any); + char msgbuf[XkbAnyActionDataSize+1]; + + if (xf86act->type == XkbSA_XFree86Private) + { + memcpy(msgbuf, xf86act->data, XkbAnyActionDataSize); + msgbuf[XkbAnyActionDataSize]= '\0'; + if (strcasecmp(msgbuf, "prgrbs")==0) { + DeviceIntPtr tmp; + winMsg(X_INFO, "Printing all currently active device grabs:\n"); + for (tmp = inputInfo.devices; tmp; tmp = tmp->next) + if (tmp->deviceGrab.grab) + PrintDeviceGrabInfo(tmp); + winMsg(X_INFO, "End list of active device grabs\n"); + } + else if (strcasecmp(msgbuf, "ungrab")==0) + UngrabAllDevices(FALSE); + else if (strcasecmp(msgbuf, "clsgrb")==0) + UngrabAllDevices(TRUE); + else if (strcasecmp(msgbuf, "prwins")==0) + PrintWindowTree(); } - return FALSE; -} - -/* Only one shift release message is sent even if both are pressed. - * Fix this here - */ -void -winFixShiftKeys(int iScanCode) -{ - if (GetKeyState(VK_SHIFT) & 0x8000) - return; - if (iScanCode == KEY_ShiftL && g_winKeyState[KEY_ShiftR]) - winSendKeyEvent(KEY_ShiftR, FALSE); - if (iScanCode == KEY_ShiftR && g_winKeyState[KEY_ShiftL]) - winSendKeyEvent(KEY_ShiftL, FALSE); + return 0; } |