KeyModifierMask
CMSWindowsKeyState::pollActiveModifiers() const
{
	KeyModifierMask state = 0;

	// get non-toggle modifiers from our own shadow key state
	for (size_t i = 0; i < sizeof(s_modifiers) / sizeof(s_modifiers[0]); ++i) {
		KeyButton button = virtualKeyToButton(s_modifiers[i].m_vk);
		if (button != 0 && isKeyDown(button)) {
			state |= s_modifiers[i].m_mask;
		}
	}

	// we can get toggle modifiers from the system
	if ((GetKeyState(VK_CAPITAL) & 0x01) != 0) {
		state |= KeyModifierCapsLock;
	}
	if ((GetKeyState(VK_NUMLOCK) & 0x01) != 0) {
		state |= KeyModifierNumLock;
	}
	if ((GetKeyState(VK_SCROLL) & 0x01) != 0) {
		state |= KeyModifierScrollLock;
	}

	return state;
}
Esempio n. 2
0
bool
CMSWindowsKeyState::fakeCtrlAltDel()
{
	if (!m_is95Family) {
		// to fake ctrl+alt+del on the NT family we broadcast a suitable
		// hotkey to all windows on the winlogon desktop.  however, the
		// current thread must be on that desktop to do the broadcast
		// and we can't switch just any thread because some own windows
		// or hooks.  so start a new thread to do the real work.
		HANDLE hEvtSendSas = OpenEvent( EVENT_MODIFY_STATE, FALSE, "Global\\SendSAS" );
		if ( hEvtSendSas ) {
			LOG((CLOG_DEBUG "found the SendSAS event - signaling my launcher to simulate ctrl+alt+del"));
			SetEvent( hEvtSendSas );
			CloseHandle( hEvtSendSas );
		}
		else {
		CThread cad(new CFunctionJob(&CMSWindowsKeyState::ctrlAltDelThread));
		cad.wait();
	}
	}
	else {
		// simulate ctrl+alt+del
		fakeKeyDown(kKeyDelete, KeyModifierControl | KeyModifierAlt,
							virtualKeyToButton(VK_DELETE));
	}
	return true;
}
Esempio n. 3
0
void
MSWindowsKeyState::pollPressedKeys(KeyButtonSet& pressedKeys) const
{
	BYTE keyState[256];
	if (!GetKeyboardState(keyState)) {
		LOG((CLOG_ERR "GetKeyboardState returned false on pollPressedKeys"));
		return;
	}
	for (KeyButton i = 1; i < 256; ++i) {
		if ((keyState[i] & 0x80) != 0) {
			KeyButton keyButton = virtualKeyToButton(i);
			if (keyButton != 0) {
				pressedKeys.insert(keyButton);
			}
		}
	}
}
bool
CMSWindowsKeyState::fakeCtrlAltDel()
{
	if (!m_is95Family) {
		// to fake ctrl+alt+del on the NT family we broadcast a suitable
		// hotkey to all windows on the winlogon desktop.  however, the
		// current thread must be on that desktop to do the broadcast
		// and we can't switch just any thread because some own windows
		// or hooks.  so start a new thread to do the real work.
		CThread cad(new CFunctionJob(&CMSWindowsKeyState::ctrlAltDelThread));
		cad.wait();
	}
	else {
		// simulate ctrl+alt+del
		fakeKeyDown(kKeyDelete, KeyModifierControl | KeyModifierAlt,
							virtualKeyToButton(VK_DELETE));
	}
	return true;
}
void
CMSWindowsKeyState::fixKeys()
{
	// fake key releases for the windows keys if we think they're
	// down but they're really up.  we have to do this because if the
	// user presses and releases a windows key without pressing any
	// other key while it's down then the system will eat the key
	// release.  if we don't detect that and synthesize the release
	// then the client won't take the usual windows key release action
	// (which on windows is to show the start menu).
	//
	// only check on the windows 95 family since the NT family reports
	// the key releases as usual.
	if (!m_is95Family) {
		return;
	}

	KeyButton leftButton  = virtualKeyToButton(VK_LWIN);
	KeyButton rightButton = virtualKeyToButton(VK_RWIN);
	bool leftDown         = isKeyDown(leftButton);
	bool rightDown        = isKeyDown(rightButton);
	bool fix              = (leftDown || rightDown);
	if (fix) {
		// check if either button is not really down
		bool leftAsyncDown  = ((GetAsyncKeyState(VK_LWIN) & 0x8000) != 0);
		bool rightAsyncDown = ((GetAsyncKeyState(VK_RWIN) & 0x8000) != 0);

		if (leftAsyncDown != leftDown || rightAsyncDown != rightDown) {
			KeyModifierMask state = getActiveModifiers();
			if (!leftAsyncDown && !rightAsyncDown) {
				// no win keys are down so remove super modifier
				state &= ~KeyModifierSuper;
			}

			// report up events
			if (leftDown  && !leftAsyncDown) {
				LOG((CLOG_DEBUG1 "event: fake key release left windows key (0x%03x)", leftButton));
				CKeyState::onKey(leftButton, false, state);
				CKeyState::sendKeyEvent(m_eventTarget, false, false,
								kKeySuper_L, state, 1, leftButton);
			}
			if (rightDown && !rightAsyncDown) {
				LOG((CLOG_DEBUG1 "event: fake key release right windows key (0x%03x)", rightButton));
				CKeyState::onKey(rightButton, false, state);
				CKeyState::sendKeyEvent(m_eventTarget, false, false,
								kKeySuper_R, state, 1, rightButton);
			}
		}
	}

	if (fix && m_fixTimer == NULL) {
		// schedule check
		m_fixTimer = EVENTQUEUE->newTimer(0.1, NULL);
		EVENTQUEUE->adoptHandler(CEvent::kTimer, m_fixTimer,
							new TMethodEventJob<CMSWindowsKeyState>(
								this, &CMSWindowsKeyState::handleFixKeys));
	}
	else if (!fix && m_fixTimer != NULL) {
		// remove scheduled check
		EVENTQUEUE->removeHandler(CEvent::kTimer, m_fixTimer);
		EVENTQUEUE->deleteTimer(m_fixTimer);
		m_fixTimer = NULL;
	}
}