예제 #1
0
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;
		}
	}
}
예제 #2
0
void
CKeyState::fakeKeyRepeat(
				KeyID id, KeyModifierMask mask,
				SInt32 count, KeyButton serverID)
{
	serverID &= kButtonMask;

	// if we haven't seen this button go down then ignore it
	KeyButton oldLocalID = m_serverKeys[serverID];
	if (oldLocalID == 0) {
		return;
	}

	// get keys for key repeat
	Keystrokes keys;
	ModifierToKeys oldActiveModifiers = m_activeModifiers;
	const CKeyMap::KeyItem* keyItem =
		m_keyMap.mapKey(keys, id, pollActiveGroup(),
								m_activeModifiers, m_mask, mask, true);
	if (keyItem == NULL) {
		return;
	}
	KeyButton localID = (KeyButton)(keyItem->m_button & kButtonMask);
	if (localID == 0) {
		return;
	}

	// if the KeyButton 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
	// KeyButtons for the two KeyIDs might be different.
	if (localID != oldLocalID) {
		// replace key up with previous KeyButton but leave key down
		// alone so it uses the new KeyButton.
		for (Keystrokes::iterator index = keys.begin();
								index != keys.end(); ++index) {
			if (index->m_type == Keystroke::kButton &&
				index->m_data.m_button.m_button == localID) {
				index->m_data.m_button.m_button = oldLocalID;
				break;
			}
		}

		// note that old key is now up
		--m_keys[oldLocalID];
		--m_syntheticKeys[oldLocalID];

		// note keys down
		updateModifierKeyState(localID, oldActiveModifiers, m_activeModifiers);
		++m_keys[localID];
		++m_syntheticKeys[localID];
		m_keyClientData[localID] = keyItem->m_client;
		m_serverKeys[serverID]   = localID;
	}

	// generate key events
	fakeKeys(keys, count);
}
예제 #3
0
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);
}