void CKeyState::fakeToggle(KeyModifierMask modifier) { const KeyButtons& buttons = m_maskToKeys[getIndexForModifier(modifier)]; if (buttons.empty() || !isToggle(modifier)) { return; } KeyButton button = buttons[0]; // get the sequence of keys to simulate key toggle Keystrokes keys; Keystroke keystroke; keystroke.m_key = button; keystroke.m_press = true; keystroke.m_repeat = false; keys.push_back(keystroke); keystroke.m_press = false; keys.push_back(keystroke); // generate key events fakeKeyEvents(keys, 1); // note the toggle m_keys[button] ^= kToggled; m_mask ^= modifier; }
bool Button::state() const { if ( isToggle() ) return m_button->isChecked(); //was: state() else return m_button->isDown(); }
void CKeyState::updateKeyState(KeyButton serverID, KeyButton localID, bool press, bool fake) { // ignore bogus keys if (serverID == 0 || localID == 0) { return; } // update key state. state doesn't change when auto-repeating. if (press) { m_serverKeyMap[serverID] = localID; m_keys[localID] |= kDown; } else { m_serverKeyMap[serverID] = 0; m_keys[localID] &= ~kDown; } // update modifier state KeyModifierMask mask = m_keyToMask[localID]; if (mask != 0) { if (isToggle(mask)) { // never report half-duplex keys as down if (isHalfDuplex(mask)) { m_keys[localID] &= ~kDown; // half-duplex keys on the primary screen don't send the // usual press/release pairs but instead send the press // when toggling on and the release when toggleing off. // since we normally toggle our shadow state on the press // we need to treat the release as a press on the primary // screen. we know we're on the primary screen if fake is // false. secondary screens always get press/release pairs. if (!fake) { press = true; } } // toggle on the press if (press) { m_keys[localID] ^= kToggled; m_mask ^= mask; } } else { if (press) { m_mask |= mask; } else if (!isModifierActive(mask)) { m_mask &= ~mask; } } LOG((CLOG_DEBUG2 "new mask: 0x%04x", m_mask)); } }
void CKeyState::setToggled(KeyModifierMask modifier) { if (isToggle(modifier)) { const KeyButtons& buttons = m_maskToKeys[getIndexForModifier(modifier)]; for (KeyButtons::const_iterator j = buttons.begin(); j != buttons.end(); ++j) { m_keys[(*j) & kButtonMask] |= kToggled; } } }
void Button::setState( bool state ) { if ( this->state() == state ) return; if ( isToggle() ) m_button->setOn(state); else m_button->setDown(state); slotStateChanged(); }
bool CKeyState::isModifierActive(KeyModifierMask mask) const { const KeyButtons& buttons = m_maskToKeys[getIndexForModifier(mask)]; KeyButtons::const_iterator j = buttons.begin(); if (j != buttons.end()) { if (isToggle(mask)) { // modifier is a toggle if ((m_keys[*j] & kToggled) != 0) { return true; } } else { // modifier is not a toggle for (; j != buttons.end(); ++j) { if ((m_keys[*j] & kDown) != 0) { return true; } } } } return false; }
bool CKeyState::mapModifier(Keystrokes& keys, Keystrokes& undo, KeyModifierMask mask, bool desireActive, bool force) const { // look up modifier const KeyButtons& buttons = m_maskToKeys[getIndexForModifier(mask)]; if (buttons.empty()) { return false; } // ignore if already in desired state if (!force && isModifierActive(mask) == desireActive) { return true; } // initialize keystroke Keystroke keystroke; keystroke.m_repeat = false; // handle toggles if (isToggle(mask)) { keystroke.m_key = buttons[0]; keystroke.m_press = true; keys.push_back(keystroke); keystroke.m_press = false; keys.push_back(keystroke); keystroke.m_press = false; undo.push_back(keystroke); keystroke.m_press = true; undo.push_back(keystroke); } else if (desireActive) { // press keystroke.m_key = buttons[0]; keystroke.m_press = true; keys.push_back(keystroke); keystroke.m_press = false; undo.push_back(keystroke); } else { // releasing a modifier is quite different from pressing one. // when we release a modifier we have to release every keycode that // is assigned to the modifier since the modifier is active if any // one of them is down. when we press a modifier we just have to // press one of those keycodes. for (KeyButtons::const_iterator j = buttons.begin(); j != buttons.end(); ++j) { if (isKeyDown(*j)) { keystroke.m_key = *j; keystroke.m_press = false; keys.push_back(keystroke); keystroke.m_press = true; undo.push_back(keystroke); } } } return true; }