static spif_bool_t action_check_modifiers(spif_ushort_t mod, int x_mod) { spif_uint32_t m = (AltMask | MetaMask | NumLockMask); /* When we do have to check the modifiers, we do so in this order to eliminate the most popular choices first. If any test fails, we return FALSE. */ D_ACTIONS(("Checking modifier set 0x%08x (%c%c%c%c) vs. X modifier set 0x%08x (%c%c%c%c)\n", mod, SHOW_MODS(mod), x_mod, SHOW_X_MODS(x_mod))); if (mod != ETERM_MOD_ANY) { /* LOGICAL_XOR() returns true if either the first parameter or the second parameter is true, but not both...just like XOR. If the mask we're looking for is set in mod but not in x_mod, or set in x_mod but not in mod, we don't have a match. */ if (LOGICAL_XOR((mod & ETERM_MOD_CTRL), (x_mod & ControlMask))) { return FALSE; } if (LOGICAL_XOR((mod & ETERM_MOD_SHIFT), (x_mod & ShiftMask))) { return FALSE; } if (MetaMask != AltMask) { if (LOGICAL_XOR((mod & ETERM_MOD_ALT), (x_mod & AltMask))) { return FALSE; } if (LOGICAL_XOR((mod & ETERM_MOD_META), (x_mod & MetaMask))) { return FALSE; } } else { if (LOGICAL_XOR((mod & (ETERM_MOD_META | ETERM_MOD_ALT)), (x_mod & (MetaMask | AltMask)))) { return FALSE; } } if (LOGICAL_XOR((mod & ETERM_MOD_LOCK), (x_mod & LockMask))) { return FALSE; } /* These tests can't use LOGICAL_XOR because the second test has an additional restriction that the Mod?Mask cannot be set in m; i.e., we want to ignore any Mod?Mask assigned to Alt, Meta, or the NumLock On state. */ if (((mod & ETERM_MOD_MOD1) && !(x_mod & Mod1Mask)) || (!(mod & ETERM_MOD_MOD1) && (x_mod & Mod1Mask) && !(Mod1Mask & m))) { return FALSE; } if (((mod & ETERM_MOD_MOD2) && !(x_mod & Mod2Mask)) || (!(mod & ETERM_MOD_MOD2) && (x_mod & Mod2Mask) && !(Mod2Mask & m))) { return FALSE; } if (((mod & ETERM_MOD_MOD3) && !(x_mod & Mod3Mask)) || (!(mod & ETERM_MOD_MOD3) && (x_mod & Mod3Mask) && !(Mod3Mask & m))) { return FALSE; } if (((mod & ETERM_MOD_MOD4) && !(x_mod & Mod4Mask)) || (!(mod & ETERM_MOD_MOD4) && (x_mod & Mod4Mask) && !(Mod4Mask & m))) { return FALSE; } if (((mod & ETERM_MOD_MOD5) && !(x_mod & Mod5Mask)) || (!(mod & ETERM_MOD_MOD5) && (x_mod & Mod5Mask) && !(Mod5Mask & m))) { return FALSE; } } D_ACTIONS(("Modifier match confirmed.\n")); return TRUE; }
void winRestoreModeKeyStates(void) { DWORD dwKeyState; BOOL processEvents = TRUE; unsigned short internalKeyStates; /* X server is being initialized */ if (!inputInfo.keyboard) return; /* Only process events if the rootwindow is mapped. The keyboard events * will cause segfaults otherwise */ if (screenInfo.screens[0]->root && screenInfo.screens[0]->root->mapped == FALSE) processEvents = FALSE; /* Force to process all pending events in the mi event queue */ if (processEvents) mieqProcessInputEvents(); /* Read the mode key states of our X server */ /* (stored in the virtual core keyboard) */ 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); } } /* Check if modifier keys are pressed, and if so, fake a press */ { BOOL ctrl = (GetAsyncKeyState(VK_CONTROL) < 0); BOOL shift = (GetAsyncKeyState(VK_SHIFT) < 0); BOOL alt = (GetAsyncKeyState(VK_LMENU) < 0); BOOL altgr = (GetAsyncKeyState(VK_RMENU) < 0); if (ctrl && altgr) ctrl = FALSE; if (LOGICAL_XOR(internalKeyStates & ControlMask, ctrl)) winSendKeyEvent(KEY_LCtrl, ctrl); if (LOGICAL_XOR(internalKeyStates & ShiftMask, shift)) winSendKeyEvent(KEY_ShiftL, shift); if (LOGICAL_XOR(internalKeyStates & Mod1Mask, alt)) winSendKeyEvent(KEY_Alt, alt); if (LOGICAL_XOR(internalKeyStates & Mod5Mask, altgr)) winSendKeyEvent(KEY_AltLang, altgr); } /* Check if latching modifier key states have changed, and if so, fake a press and a release to toggle the modifier to the correct state */ dwKeyState = GetKeyState(VK_NUMLOCK) & 0x0001; if (LOGICAL_XOR(internalKeyStates & NumLockMask, dwKeyState)) { winSendKeyEvent(KEY_NumLock, TRUE); winSendKeyEvent(KEY_NumLock, FALSE); } dwKeyState = GetKeyState(VK_CAPITAL) & 0x0001; if (LOGICAL_XOR(internalKeyStates & LockMask, dwKeyState)) { winSendKeyEvent(KEY_CapsLock, TRUE); winSendKeyEvent(KEY_CapsLock, FALSE); } dwKeyState = GetKeyState(VK_SCROLL) & 0x0001; if (LOGICAL_XOR(internalKeyStates & ScrollLockMask, dwKeyState)) { winSendKeyEvent(KEY_ScrollLock, TRUE); winSendKeyEvent(KEY_ScrollLock, FALSE); } dwKeyState = GetKeyState(VK_KANA) & 0x0001; if (LOGICAL_XOR(internalKeyStates & KanaMask, dwKeyState)) { winSendKeyEvent(KEY_HKTG, TRUE); winSendKeyEvent(KEY_HKTG, FALSE); } }
void winRestoreModeKeyStates(void) { DWORD dwKeyState; BOOL processEvents = TRUE; unsigned short internalKeyStates; /* X server is being initialized */ if (!inputInfo.keyboard) return; /* Only process events if the rootwindow is mapped. The keyboard events * will cause segfaults otherwise */ if (screenInfo.screens[0]->root && screenInfo.screens[0]->root->mapped == FALSE) processEvents = FALSE; /* Force to process all pending events in the mi event queue */ if (processEvents) mieqProcessInputEvents(); /* Read the mode key states of our X server */ /* (stored in the virtual core keyboard) */ internalKeyStates = XkbStateFieldFromRec(&inputInfo.keyboard->key->xkbInfo->state); winDebug("winRestoreModeKeyStates: state %d\n", internalKeyStates); /* Check if modifier keys are pressed, and if so, fake a press */ { BOOL lctrl = (GetAsyncKeyState(VK_LCONTROL) < 0); BOOL rctrl = (GetAsyncKeyState(VK_RCONTROL) < 0); BOOL lshift = (GetAsyncKeyState(VK_LSHIFT) < 0); BOOL rshift = (GetAsyncKeyState(VK_RSHIFT) < 0); BOOL alt = (GetAsyncKeyState(VK_LMENU) < 0); BOOL altgr = (GetAsyncKeyState(VK_RMENU) < 0); /* If AltGr and CtrlL appear to be pressed, assume the CtrL is a fake one */ if (lctrl && altgr) lctrl = FALSE; if (lctrl) winSendKeyEvent(KEY_LCtrl, TRUE); if (rctrl) winSendKeyEvent(KEY_RCtrl, TRUE); if (lshift) winSendKeyEvent(KEY_ShiftL, TRUE); if (rshift) winSendKeyEvent(KEY_ShiftL, TRUE); if (alt) winSendKeyEvent(KEY_Alt, TRUE); if (altgr) winSendKeyEvent(KEY_AltLang, TRUE); } /* Check if latching modifier key states have changed, and if so, fake a press and a release to toggle the modifier to the correct state */ dwKeyState = GetKeyState(VK_NUMLOCK) & 0x0001; if (LOGICAL_XOR(internalKeyStates & NumLockMask, dwKeyState)) { winSendKeyEvent(KEY_NumLock, TRUE); winSendKeyEvent(KEY_NumLock, FALSE); } dwKeyState = GetKeyState(VK_CAPITAL) & 0x0001; if (LOGICAL_XOR(internalKeyStates & LockMask, dwKeyState)) { winSendKeyEvent(KEY_CapsLock, TRUE); winSendKeyEvent(KEY_CapsLock, FALSE); } dwKeyState = GetKeyState(VK_SCROLL) & 0x0001; if (LOGICAL_XOR(internalKeyStates & ScrollLockMask, dwKeyState)) { winSendKeyEvent(KEY_ScrollLock, TRUE); winSendKeyEvent(KEY_ScrollLock, FALSE); } dwKeyState = GetKeyState(VK_KANA) & 0x0001; if (LOGICAL_XOR(internalKeyStates & KanaMask, dwKeyState)) { winSendKeyEvent(KEY_HKTG, TRUE); winSendKeyEvent(KEY_HKTG, FALSE); } /* For strict correctness, we should also press any non-modifier keys which are already down when we gain focus, but nobody has complained yet :-) */ }