示例#1
0
void
CKeyState::updateKeyState()
{
	// reset our state
	memset(&m_keys, 0, sizeof(m_keys));
	memset(&m_syntheticKeys, 0, sizeof(m_syntheticKeys));
	memset(&m_keyClientData, 0, sizeof(m_keyClientData));
	memset(&m_serverKeys, 0, sizeof(m_serverKeys));
	m_activeModifiers.clear();

	// get the current keyboard state
	KeyButtonSet keysDown;
	pollPressedKeys(keysDown);
	for (KeyButtonSet::const_iterator i = keysDown.begin();
								i != keysDown.end(); ++i) {
		m_keys[*i] = 1;
	}

	// get the current modifier state
	m_mask = pollActiveModifiers();

	// set active modifiers
	CAddActiveModifierContext addModifierContext(pollActiveGroup(), m_mask,
												m_activeModifiers);
	m_keyMap.foreachKey(&CKeyState::addActiveModifierCB, &addModifierContext);

	LOG((CLOG_DEBUG1 "modifiers on update: 0x%04x", m_mask));
}
示例#2
0
bool
OSXKeyState::mapSynergyHotKeyToMac(KeyID key, KeyModifierMask mask,
				UInt32 &macVirtualKey, UInt32 &macModifierMask) const
{
	// look up button for key
	KeyButton button = getButton(key, pollActiveGroup());
	if (button == 0 && key != kKeyNone) {
		return false;
	}
	macVirtualKey = mapKeyButtonToVirtualKey(button);
	
	// calculate modifier mask
	macModifierMask = 0;
	if ((mask & KeyModifierShift) != 0) {
		macModifierMask |= shiftKey;
	}
	if ((mask & KeyModifierControl) != 0) {
		macModifierMask |= controlKey;
	}
	if ((mask & KeyModifierAlt) != 0) {
		macModifierMask |= cmdKey;
	}
	if ((mask & KeyModifierSuper) != 0) {
		macModifierMask |= optionKey;
	}
	if ((mask & KeyModifierCapsLock) != 0) {
		macModifierMask |= alphaLock;
	}
	if ((mask & KeyModifierNumLock) != 0) {
		macModifierMask |= s_osxNumLock;
	}
	
	return true;
}
示例#3
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);
}
void
CMSWindowsKeyState::fakeKey(const Keystroke& keystroke)
{
	switch (keystroke.m_type) {
	case Keystroke::kButton: {
		LOG((CLOG_DEBUG1 "  %03x (%08x) %s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client, keystroke.m_data.m_button.m_press ? "down" : "up"));
		KeyButton button = keystroke.m_data.m_button.m_button;

		// windows doesn't send key ups for key repeats
		if (keystroke.m_data.m_button.m_repeat &&
			!keystroke.m_data.m_button.m_press) {
			LOG((CLOG_DEBUG1 "  discard key repeat release"));
			break;
		}

		// get the virtual key for the button
		UINT vk = keystroke.m_data.m_button.m_client;

		// special handling of VK_SNAPSHOT
		if (vk == VK_SNAPSHOT) {
			if ((getActiveModifiers() & KeyModifierAlt) != 0) {
				// snapshot active window
				button = 1;
			}
			else {
				// snapshot full screen
				button = 0;
			}
		}

		// synthesize event
		m_desks->fakeKeyEvent(button, vk,
								keystroke.m_data.m_button.m_press,
								keystroke.m_data.m_button.m_repeat);
		break;
	}

	case Keystroke::kGroup:
		// we don't restore the group.  we'd like to but we can't be
		// sure the restoring group change will be processed after the
		// key events.
		if (!keystroke.m_data.m_group.m_restore) {
			if (keystroke.m_data.m_group.m_absolute) {
				LOG((CLOG_DEBUG1 "  group %d", keystroke.m_data.m_group.m_group));
				setWindowGroup(keystroke.m_data.m_group.m_group);
			}
			else {
				LOG((CLOG_DEBUG1 "  group %+d", keystroke.m_data.m_group.m_group));
				setWindowGroup(getEffectiveGroup(pollActiveGroup(),
									keystroke.m_data.m_group.m_group));
			}
		}
		break;
	}
}
示例#5
0
void
XWindowsKeyState::fakeKey(const Keystroke& keystroke)
{
	switch (keystroke.m_type) {
	case Keystroke::kButton:
		LOG((CLOG_DEBUG1 "  %03x (%08x) %s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client, keystroke.m_data.m_button.m_press ? "down" : "up"));
		if (keystroke.m_data.m_button.m_repeat) {
			int c = keystroke.m_data.m_button.m_button;
			int i = (c >> 3);
			int b = 1 << (c & 7);
			if (m_keyboardState.global_auto_repeat == AutoRepeatModeOff ||
				(c!=113 && c!=116 && (m_keyboardState.auto_repeats[i] & b) == 0)) {
				LOG((CLOG_DEBUG1 "  discard autorepeat"));
				break;
			}
		}
		XTestFakeKeyEvent(m_display, keystroke.m_data.m_button.m_button,
							keystroke.m_data.m_button.m_press ? True : False,
							CurrentTime);
		break;

	case Keystroke::kGroup:
		if (keystroke.m_data.m_group.m_absolute) {
			LOG((CLOG_DEBUG1 "  group %d", keystroke.m_data.m_group.m_group));
#if HAVE_XKB_EXTENSION
			if (m_xkb != NULL) {
				if (XkbLockGroup(m_display, XkbUseCoreKbd,
							keystroke.m_data.m_group.m_group) == False) {
					LOG((CLOG_DEBUG1 "XkbLockGroup request not sent"));
				}
			}
			else
#endif
			{
				LOG((CLOG_DEBUG1 "  ignored"));
			}
		}
		else {
			LOG((CLOG_DEBUG1 "  group %+d", keystroke.m_data.m_group.m_group));
#if HAVE_XKB_EXTENSION
			if (m_xkb != NULL) {
				if (XkbLockGroup(m_display, XkbUseCoreKbd,
							getEffectiveGroup(pollActiveGroup(),
								keystroke.m_data.m_group.m_group)) == False) {
					LOG((CLOG_DEBUG1 "XkbLockGroup request not sent"));
				}
			}
			else
#endif
			{
				LOG((CLOG_DEBUG1 "  ignored"));
			}
		}
		break;
	}
示例#6
0
void
KeyState::fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton serverID)
{
    // if this server key is already down then this is probably a
    // mis-reported autorepeat.
    serverID &= kButtonMask;
    if (m_serverKeys[serverID] != 0) {
        fakeKeyRepeat(id, mask, 1, serverID);
        return;
    }

    // ignore certain keys
    if (isIgnoredKey(id, mask)) {
        LOG((CLOG_DEBUG1 "ignored key %04x %04x", id, mask));
        return;
    }

    // get keys for key press
    Keystrokes keys;
    ModifierToKeys oldActiveModifiers = m_activeModifiers;
    const barrier::KeyMap::KeyItem* keyItem =
        m_keyMap.mapKey(keys, id, pollActiveGroup(), m_activeModifiers,
                                getActiveModifiersRValue(), mask, false);
    if (keyItem == NULL) {
        // a media key won't be mapped on mac, so we need to fake it in a
        // special way
        if (id == kKeyAudioDown || id == kKeyAudioUp ||
            id == kKeyAudioMute || id == kKeyAudioPlay ||
            id == kKeyAudioPrev || id == kKeyAudioNext ||
            id == kKeyBrightnessDown || id == kKeyBrightnessUp
            ) {
            LOG((CLOG_DEBUG1 "emulating media key"));
            fakeMediaKey(id);
        }
        
        return;
    }
    
    KeyButton localID = (KeyButton)(keyItem->m_button & kButtonMask);
    updateModifierKeyState(localID, oldActiveModifiers, m_activeModifiers);
    if (localID != 0) {
        // note keys down
        ++m_keys[localID];
        ++m_syntheticKeys[localID];
        m_keyClientData[localID] = keyItem->m_client;
        m_serverKeys[serverID]   = localID;
    }

    // generate key events
    fakeKeys(keys, 1);
}
示例#7
0
void
XWindowsKeyState::setActiveGroup(SInt32 group)
{
	if (group == kGroupPollAndSet) {
		// we need to set the group to -1 in order for pollActiveGroup() to
		// actually poll for the group
		m_group = -1;
		m_group = pollActiveGroup();
	}
	else if (group == kGroupPoll) {
		m_group = -1;
	}
	else {
		assert(group >= 0);
		m_group = group;
	}
}
示例#8
0
void
CKeyState::fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton serverID)
{
	// ignore key if serverID is bogus
	serverID &= kButtonMask;
	if (serverID == 0) {
		LOG((CLOG_DEBUG1 "ignored fake key for %04x with serverID of 0", id));
		return;
	}

	// if this server key is already down then this is probably a
	// mis-reported autorepeat.
	if (m_serverKeys[serverID] != 0) {
		fakeKeyRepeat(id, mask, 1, serverID);
		return;
	}

	// ignore certain keys
	if (isIgnoredKey(id, mask)) {
		LOG((CLOG_DEBUG1 "ignored key %04x %04x", id, mask));
		return;
	}

	// get keys for key press
	Keystrokes keys;
	ModifierToKeys oldActiveModifiers = m_activeModifiers;
	const CKeyMap::KeyItem* keyItem =
		m_keyMap.mapKey(keys, id, pollActiveGroup(),
								m_activeModifiers, m_mask, mask, false);
	if (keyItem == NULL) {
		return;
	}
	KeyButton localID = (KeyButton)(keyItem->m_button & kButtonMask);
	if (localID != 0) {
		// 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, 1);
}
示例#9
0
void
OSXKeyState::fakeKey(const Keystroke& keystroke)
{
	switch (keystroke.m_type) {
	case Keystroke::kButton: {
		
		KeyButton button = keystroke.m_data.m_button.m_button;
		bool keyDown = keystroke.m_data.m_button.m_press;
		UInt32 client = keystroke.m_data.m_button.m_client;
		CGEventSourceRef source = 0;
		CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button);
		
		LOG((CLOG_DEBUG1
			"  button=0x%04x virtualKey=0x%04x keyDown=%s client=0x%04x",
			button, virtualKey, keyDown ? "down" : "up", client));

		CGEventRef ref = CGEventCreateKeyboardEvent(
			source, virtualKey, keyDown);
		
		if (ref == NULL) {
			LOG((CLOG_CRIT "unable to create keyboard event for keystroke"));
			return;
		}

		// persist modifier state.
		if (virtualKey == s_shiftVK) {
			m_shiftPressed = keyDown;
		}
		
		if (virtualKey == s_controlVK) {
			m_controlPressed = keyDown;
		}
		
		if (virtualKey == s_altVK) {
			m_altPressed = keyDown;
		}
		
		if (virtualKey == s_superVK) {
			m_superPressed = keyDown;
		}
		
		if (virtualKey == s_capsLockVK) {
			m_capsPressed = keyDown;
		}

		// set the event flags for special keys
		// http://tinyurl.com/pxl742y
		CGEventFlags modifiers = 0;
		
		if (m_shiftPressed) {
			modifiers |= kCGEventFlagMaskShift;
		}
		
		if (m_controlPressed) {
			modifiers |= kCGEventFlagMaskControl;
		}
		
		if (m_altPressed) {
			modifiers |= kCGEventFlagMaskAlternate;
		}
		
		if (m_superPressed) {
			modifiers |= kCGEventFlagMaskCommand;
		}
		
		if (m_capsPressed) {
			modifiers |= kCGEventFlagMaskAlphaShift;
		}
		
		CGEventSetFlags(ref, modifiers);
		CGEventPost(kCGHIDEventTap, ref);
		CFRelease(ref);

		// add a delay if client data isn't zero
		// FIXME -- why?
		if (client != 0) {
			ARCH->sleep(0.01);
		}
		break;
	}

	case Keystroke::kGroup: {
		SInt32 group = keystroke.m_data.m_group.m_group;
		if (keystroke.m_data.m_group.m_absolute) {
			LOG((CLOG_DEBUG1 "  group %d", group));
			setGroup(group);
		}
		else {
			LOG((CLOG_DEBUG1 "  group %+d", group));
			setGroup(getEffectiveGroup(pollActiveGroup(), group));
		}
		break;
	}
	}
}
示例#10
0
void
COSXKeyState::fakeKey(const Keystroke& keystroke)
{
	CGEventRef ref;

	switch (keystroke.m_type) {
	case Keystroke::kButton:
		{
			LOG((CLOG_DEBUG1 "  %03x (%08x) %s", keystroke.m_data.m_button.m_button, keystroke.m_data.m_button.m_client, keystroke.m_data.m_button.m_press ? "down" : "up"));

		// let system figure out character for us
		ref = CGEventCreateKeyboardEvent(0, mapKeyButtonToVirtualKey(
									keystroke.m_data.m_button.m_button),
								keystroke.m_data.m_button.m_press);
		if (ref == NULL) {
			LOG((CLOG_CRIT "unable to create keyboard event for keystroke"));
		}

			UInt32 vk = mapKeyButtonToVirtualKey(keystroke.m_data.m_button.m_button);
			UInt32 modifierDown = keystroke.m_data.m_button.m_press;

			// check the key for specials and store the value (persistent until changed)
			if (vk == s_shiftVK)    shiftPressed=modifierDown;
			if (vk == s_controlVK)  controlPressed=modifierDown;
			if (vk == s_altVK)      altPressed=modifierDown;
			if (vk == s_superVK)    superPressed=modifierDown;
			if (vk == s_capsLockVK) capsPressed=modifierDown;

			//Set the event flags for special keys - see following link:
			//http://stackoverflow.com/questions/2008126/cgeventpost-possible-bug-when-simulating-keyboard-events
			CGEventFlags modifiers = 0;
			if (shiftPressed)   modifiers |= kCGEventFlagMaskShift;
			if (controlPressed) modifiers |= kCGEventFlagMaskControl;
			if (altPressed)     modifiers |= kCGEventFlagMaskAlternate;
			if (superPressed)   modifiers |= kCGEventFlagMaskCommand;
			if (capsPressed)    modifiers |= kCGEventFlagMaskAlphaShift;
			
			CGEventSetFlags(ref, modifiers);
			
			CGEventPost(kCGHIDEventTap, ref);

			// add a delay if client data isn't zero
			if (keystroke.m_data.m_button.m_client) {
				ARCH->sleep(0.01);
			}
		}
		break;

	case Keystroke::kGroup:
		if (keystroke.m_data.m_group.m_absolute) {
			LOG((CLOG_DEBUG1 "  group %d", keystroke.m_data.m_group.m_group));
			setGroup(keystroke.m_data.m_group.m_group);
		}
		else {
			LOG((CLOG_DEBUG1 "  group %+d", keystroke.m_data.m_group.m_group));
			setGroup(getEffectiveGroup(pollActiveGroup(),
									keystroke.m_data.m_group.m_group));
		}
		break;
	}
}