ctrl+alt+del emulation checkpoint.
This commit is contained in:
parent
921526ab56
commit
784ab183ae
|
@ -521,15 +521,29 @@ CMSWindowsPrimaryScreen::onPreDispatch(const CEvent* event)
|
||||||
case SYNERGY_MSG_KEY:
|
case SYNERGY_MSG_KEY:
|
||||||
// ignore message if posted prior to last mark change
|
// ignore message if posted prior to last mark change
|
||||||
if (!ignore()) {
|
if (!ignore()) {
|
||||||
|
WPARAM wParam = msg->wParam;
|
||||||
|
LPARAM lParam = msg->lParam;
|
||||||
|
|
||||||
|
// check for ctrl+alt+del emulation
|
||||||
|
if ((wParam == VK_PAUSE || wParam == VK_CANCEL) &&
|
||||||
|
(m_keys[VK_CONTROL] & 0x80) != 0 &&
|
||||||
|
(m_keys[VK_MENU] & 0x80) != 0) {
|
||||||
|
LOG((CLOG_DEBUG "emulate ctrl+alt+del"));
|
||||||
|
wParam = VK_DELETE;
|
||||||
|
lParam &= 0xffff0000;
|
||||||
|
lParam |= 0x00000001;
|
||||||
|
}
|
||||||
|
|
||||||
|
// process key normally
|
||||||
KeyModifierMask mask;
|
KeyModifierMask mask;
|
||||||
const KeyID key = mapKey(msg->wParam, msg->lParam, &mask);
|
const KeyID key = mapKey(wParam, lParam, &mask);
|
||||||
KeyButton button = static_cast<KeyButton>(
|
KeyButton button = static_cast<KeyButton>(
|
||||||
(msg->lParam & 0x00ff0000u) >> 16);
|
(lParam & 0x00ff0000u) >> 16);
|
||||||
if (key != kKeyNone && key != kKeyMultiKey) {
|
if (key != kKeyNone && key != kKeyMultiKey) {
|
||||||
if ((msg->lParam & 0x80000000) == 0) {
|
if ((lParam & 0x80000000) == 0) {
|
||||||
// key press
|
// key press
|
||||||
const bool wasDown = ((msg->lParam & 0x40000000) != 0);
|
const bool wasDown = ((lParam & 0x40000000) != 0);
|
||||||
const SInt32 repeat = (SInt32)(msg->lParam & 0xffff);
|
const SInt32 repeat = (SInt32)(lParam & 0xffff);
|
||||||
if (repeat >= 2 || wasDown) {
|
if (repeat >= 2 || wasDown) {
|
||||||
LOG((CLOG_DEBUG1 "event: key repeat key=%d mask=0x%04x count=%d button=0x%04x", key, mask, repeat, button));
|
LOG((CLOG_DEBUG1 "event: key repeat key=%d mask=0x%04x count=%d button=0x%04x", key, mask, repeat, button));
|
||||||
m_receiver->onKeyRepeat(key, mask, repeat, button);
|
m_receiver->onKeyRepeat(key, mask, repeat, button);
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include "CMSWindowsScreen.h"
|
#include "CMSWindowsScreen.h"
|
||||||
#include "XScreen.h"
|
#include "XScreen.h"
|
||||||
#include "CLock.h"
|
#include "CLock.h"
|
||||||
|
#include "CThread.h"
|
||||||
|
#include "CFunctionJob.h"
|
||||||
#include "CLog.h"
|
#include "CLog.h"
|
||||||
#include "CArchMiscWindows.h"
|
#include "CArchMiscWindows.h"
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
@ -94,6 +96,14 @@ CMSWindowsSecondaryScreen::keyDown(KeyID key,
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
m_screen->syncDesktop();
|
m_screen->syncDesktop();
|
||||||
|
|
||||||
|
// check for ctrl+alt+del emulation
|
||||||
|
if (key == kKeyDelete &&
|
||||||
|
(mask & (KeyModifierControl | KeyModifierAlt)) ==
|
||||||
|
(KeyModifierControl | KeyModifierAlt)) {
|
||||||
|
synthesizeCtrlAltDel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// get the sequence of keys to simulate key press and the final
|
// get the sequence of keys to simulate key press and the final
|
||||||
// modifier state.
|
// modifier state.
|
||||||
m_mask = mapKey(keys, virtualKey, key, mask, kPress);
|
m_mask = mapKey(keys, virtualKey, key, mask, kPress);
|
||||||
|
@ -1517,3 +1527,52 @@ CMSWindowsSecondaryScreen::getCodePageFromLangID(LANGID langid) const
|
||||||
|
|
||||||
return codePage;
|
return codePage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsSecondaryScreen::synthesizeCtrlAltDel()
|
||||||
|
{
|
||||||
|
LOG((CLOG_DEBUG "emulating ctrl+alt+del"));
|
||||||
|
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, we
|
||||||
|
// 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(
|
||||||
|
&CMSWindowsSecondaryScreen::ctrlAltDelThread));
|
||||||
|
cad.wait();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Keystrokes keys;
|
||||||
|
UINT virtualKey;
|
||||||
|
KeyID key = kKeyDelete;
|
||||||
|
KeyModifierMask mask = KeyModifierControl | KeyModifierAlt;
|
||||||
|
|
||||||
|
// get the sequence of keys to simulate ctrl+alt+del
|
||||||
|
mapKey(keys, virtualKey, key, mask, kPress);
|
||||||
|
if (!keys.empty()) {
|
||||||
|
// generate key events
|
||||||
|
doKeystrokes(keys, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CMSWindowsSecondaryScreen::ctrlAltDelThread(void*)
|
||||||
|
{
|
||||||
|
// get the Winlogon desktop at whatever privilege we can
|
||||||
|
HDESK desk = OpenDesktop("Winlogon", 0, FALSE, MAXIMUM_ALLOWED);
|
||||||
|
if (desk != NULL) {
|
||||||
|
if (SetThreadDesktop(desk)) {
|
||||||
|
PostMessage(HWND_BROADCAST, WM_HOTKEY, 0,
|
||||||
|
MAKELPARAM(MOD_CONTROL | MOD_ALT, VK_DELETE));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG((CLOG_DEBUG "can't switch to Winlogon desk: %d", GetLastError()));
|
||||||
|
}
|
||||||
|
CloseDesktop(desk);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG((CLOG_DEBUG "can't open Winlogon desk: %d", GetLastError()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -122,6 +122,12 @@ private:
|
||||||
|
|
||||||
UINT getCodePageFromLangID(LANGID) const;
|
UINT getCodePageFromLangID(LANGID) const;
|
||||||
|
|
||||||
|
// generate a fake ctrl+alt+del
|
||||||
|
void synthesizeCtrlAltDel();
|
||||||
|
|
||||||
|
// thread that generates fake ctrl+alt+del
|
||||||
|
static void ctrlAltDelThread(void*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CMutex m_mutex;
|
CMutex m_mutex;
|
||||||
CMSWindowsScreen* m_screen;
|
CMSWindowsScreen* m_screen;
|
||||||
|
|
|
@ -239,8 +239,18 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||||
{
|
{
|
||||||
LOG((CLOG_DEBUG1 "event: KeyPress code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
LOG((CLOG_DEBUG1 "event: KeyPress code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
||||||
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
|
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
|
||||||
const KeyID key = mapKey(&xevent.xkey);
|
KeyID key = mapKey(&xevent.xkey);
|
||||||
if (key != kKeyNone) {
|
if (key != kKeyNone) {
|
||||||
|
// check for ctrl+alt+del emulation
|
||||||
|
if ((key == kKeyPause || key == kKeyCancel) &&
|
||||||
|
(mask & (KeyModifierControl | KeyModifierAlt)) ==
|
||||||
|
(KeyModifierControl | KeyModifierAlt)) {
|
||||||
|
// pretend it's ctrl+alt+del
|
||||||
|
LOG((CLOG_DEBUG "emulate ctrl+alt+del"));
|
||||||
|
key = kKeyDelete;
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle key
|
||||||
m_receiver->onKeyDown(key, mask,
|
m_receiver->onKeyDown(key, mask,
|
||||||
static_cast<KeyButton>(xevent.xkey.keycode));
|
static_cast<KeyButton>(xevent.xkey.keycode));
|
||||||
if (key == kKeyCapsLock && m_capsLockHalfDuplex) {
|
if (key == kKeyCapsLock && m_capsLockHalfDuplex) {
|
||||||
|
@ -258,7 +268,7 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||||
case KeyRelease:
|
case KeyRelease:
|
||||||
{
|
{
|
||||||
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
|
const KeyModifierMask mask = mapModifier(xevent.xkey.state);
|
||||||
const KeyID key = mapKey(&xevent.xkey);
|
KeyID key = mapKey(&xevent.xkey);
|
||||||
if (key != kKeyNone) {
|
if (key != kKeyNone) {
|
||||||
// check if this is a key repeat by getting the next
|
// check if this is a key repeat by getting the next
|
||||||
// KeyPress event that has the same key and time as
|
// KeyPress event that has the same key and time as
|
||||||
|
@ -279,6 +289,18 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event)
|
||||||
&CXWindowsPrimaryScreen::findKeyEvent,
|
&CXWindowsPrimaryScreen::findKeyEvent,
|
||||||
(XPointer)&filter) == True);
|
(XPointer)&filter) == True);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check for ctrl+alt+del emulation
|
||||||
|
if ((key == kKeyPause || key == kKeyCancel) &&
|
||||||
|
(mask & (KeyModifierControl | KeyModifierAlt)) ==
|
||||||
|
(KeyModifierControl | KeyModifierAlt)) {
|
||||||
|
// pretend it's ctrl+alt+del and ignore autorepeat
|
||||||
|
LOG((CLOG_DEBUG "emulate ctrl+alt+del"));
|
||||||
|
key = kKeyDelete;
|
||||||
|
hasPress = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!hasPress) {
|
if (!hasPress) {
|
||||||
// no press event follows so it's a plain release
|
// no press event follows so it's a plain release
|
||||||
LOG((CLOG_DEBUG1 "event: KeyRelease code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
LOG((CLOG_DEBUG1 "event: KeyRelease code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state));
|
||||||
|
|
|
@ -117,6 +117,17 @@ CXWindowsSecondaryScreen::keyDown(KeyID key,
|
||||||
Keystrokes keys;
|
Keystrokes keys;
|
||||||
KeyCode keycode;
|
KeyCode keycode;
|
||||||
|
|
||||||
|
// check for ctrl+alt+del emulation
|
||||||
|
if ((mask & (KeyModifierControl | KeyModifierAlt)) ==
|
||||||
|
(KeyModifierControl | KeyModifierAlt) &&
|
||||||
|
key == XK_Up - 0xff00 + 0xef00) {
|
||||||
|
// just convert the key to Delete and synthesize the key
|
||||||
|
// normally. the X server/window manager will do the right
|
||||||
|
// thing (or, at least XFree86/KDE will).
|
||||||
|
LOG((CLOG_DEBUG "ctrl+alt+del emulation"));
|
||||||
|
key = XK_Delete - 0xff00u + 0xef00u;
|
||||||
|
}
|
||||||
|
|
||||||
// get the sequence of keys to simulate key press and the final
|
// get the sequence of keys to simulate key press and the final
|
||||||
// modifier state.
|
// modifier state.
|
||||||
m_mask = mapKey(keys, keycode, key, mask, kPress);
|
m_mask = mapKey(keys, keycode, key, mask, kPress);
|
||||||
|
|
Loading…
Reference in New Issue