void CKeyState::fakeKeyEvents(const Keystrokes& keys, UInt32 count) { // do nothing if no keys or no repeats if (count == 0 || keys.empty()) { return; } // generate key events LOG((CLOG_DEBUG2 "keystrokes:")); for (Keystrokes::const_iterator k = keys.begin(); k != keys.end(); ) { if (k->m_repeat) { // repeat from here up to but not including the next key // with m_repeat == false count times. Keystrokes::const_iterator start = k; while (count-- > 0) { // send repeating events for (k = start; k != keys.end() && k->m_repeat; ++k) { fakeKeyEvent(k->m_key, k->m_press, true); } } // note -- k is now on the first non-repeat key after the // repeat keys, exactly where we'd like to continue from. } else { // send event fakeKeyEvent(k->m_key, k->m_press, false); // next key ++k; } } }
void CKeyState::fakeKeyRepeat( KeyID id, KeyModifierMask mask, SInt32 count, KeyButton button) { button &= kButtonMask; // if we haven't seen this button go down then ignore it KeyButton oldLocalID = m_serverKeyMap[button]; if (oldLocalID == 0) { return; } // get the sequence of keys to simulate key repeat and the final // modifier state. Keystrokes keys; KeyButton localID = (KeyButton)(mapKey(keys, id, mask, true) & kButtonMask); if (localID == 0) { LOG((CLOG_DEBUG2 "cannot map key 0x%08x", id)); return; } if (keys.empty()) { // do nothing if there are no associated keys return; } // if the keycode for the auto-repeat is not the same as for the // initial press then mark the initial key as released and the new // key as pressed. this can happen when we auto-repeat after a // dead key. for example, a dead accent followed by 'a' will // generate an 'a with accent' followed by a repeating 'a'. the // keycodes for the two keysyms might be different. if (localID != oldLocalID) { // replace key up with previous key id but leave key down // alone so it uses the new keycode. for (Keystrokes::iterator index = keys.begin(); index != keys.end(); ++index) { if (index->m_key == localID) { index->m_key = oldLocalID; break; } } // note that old key is now up m_keys[oldLocalID] &= ~kDown; // map server key to new key m_serverKeyMap[button] = localID; // note that new key is now down m_keys[localID] |= kDown; } // generate key events fakeKeyEvents(keys, count); }
void CKeyState::fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton button) { // get the sequence of keys to simulate key press and the final // modifier state. Keystrokes keys; KeyButton localID = (KeyButton)(mapKey(keys, id, mask, false) & kButtonMask); if (keys.empty()) { // do nothing if there are no associated keys LOG((CLOG_DEBUG2 "cannot map key 0x%08x", id)); return; } // generate key events fakeKeyEvents(keys, 1); // note that key is down updateKeyState((KeyButton)(button & kButtonMask), localID, true, true); }