mirror of
https://github.com/debauchee/barrier.git
synced 2026-06-10 06:06:36 +08:00
Restored lost files and changes in version 1.3.1 to depot.
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "CMSWindowsKeyState.h"
|
||||
#include "CMSWindowsScreenSaver.h"
|
||||
#include "CClipboard.h"
|
||||
#include "CKeyMap.h"
|
||||
#include "XScreen.h"
|
||||
#include "CLock.h"
|
||||
#include "CThread.h"
|
||||
@@ -54,8 +55,8 @@
|
||||
#define WM_NCXBUTTONDOWN 0x00AB
|
||||
#define WM_NCXBUTTONUP 0x00AC
|
||||
#define WM_NCXBUTTONDBLCLK 0x00AD
|
||||
#define MOUSEEVENTF_XDOWN 0x0100
|
||||
#define MOUSEEVENTF_XUP 0x0200
|
||||
#define MOUSEEVENTF_XDOWN 0x0080
|
||||
#define MOUSEEVENTF_XUP 0x0100
|
||||
#define XBUTTON1 0x0001
|
||||
#define XBUTTON2 0x0002
|
||||
#endif
|
||||
@@ -76,8 +77,7 @@
|
||||
HINSTANCE CMSWindowsScreen::s_instance = NULL;
|
||||
CMSWindowsScreen* CMSWindowsScreen::s_screen = NULL;
|
||||
|
||||
CMSWindowsScreen::CMSWindowsScreen(bool isPrimary,
|
||||
IJob* suspend, IJob* resume) :
|
||||
CMSWindowsScreen::CMSWindowsScreen(bool isPrimary) :
|
||||
m_isPrimary(isPrimary),
|
||||
m_is95Family(CArchMiscWindows::isWindows95Family()),
|
||||
m_isOnScreen(m_isPrimary),
|
||||
@@ -90,8 +90,8 @@ CMSWindowsScreen::CMSWindowsScreen(bool isPrimary,
|
||||
m_sequenceNumber(0),
|
||||
m_mark(0),
|
||||
m_markReceived(0),
|
||||
m_keyLayout(NULL),
|
||||
m_fixTimer(NULL),
|
||||
m_keyLayout(NULL),
|
||||
m_screensaver(NULL),
|
||||
m_screensaverNotify(false),
|
||||
m_screensaverActive(false),
|
||||
@@ -106,8 +106,6 @@ CMSWindowsScreen::CMSWindowsScreen(bool isPrimary,
|
||||
m_setZone(NULL),
|
||||
m_setMode(NULL),
|
||||
m_keyState(NULL),
|
||||
m_suspend(suspend),
|
||||
m_resume(resume),
|
||||
m_hasMouse(GetSystemMetrics(SM_MOUSEPRESENT) != 0),
|
||||
m_showingMouse(false)
|
||||
{
|
||||
@@ -124,7 +122,7 @@ CMSWindowsScreen::CMSWindowsScreen(bool isPrimary,
|
||||
m_hookLibrary, m_screensaver,
|
||||
new TMethodJob<CMSWindowsScreen>(this,
|
||||
&CMSWindowsScreen::updateKeysCB));
|
||||
m_keyState = new CMSWindowsKeyState(m_desks);
|
||||
m_keyState = new CMSWindowsKeyState(m_desks, getEventTarget());
|
||||
updateScreenShape();
|
||||
m_class = createWindowClass();
|
||||
m_window = createWindow(m_class, "Synergy");
|
||||
@@ -139,8 +137,6 @@ CMSWindowsScreen::CMSWindowsScreen(bool isPrimary,
|
||||
destroyWindow(m_window);
|
||||
destroyClass(m_class);
|
||||
closeHookLibrary(m_hookLibrary);
|
||||
delete m_suspend;
|
||||
delete m_resume;
|
||||
s_screen = NULL;
|
||||
throw;
|
||||
}
|
||||
@@ -167,8 +163,6 @@ CMSWindowsScreen::~CMSWindowsScreen()
|
||||
destroyWindow(m_window);
|
||||
destroyClass(m_class);
|
||||
closeHookLibrary(m_hookLibrary);
|
||||
delete m_suspend;
|
||||
delete m_resume;
|
||||
s_screen = NULL;
|
||||
}
|
||||
|
||||
@@ -192,6 +186,12 @@ CMSWindowsScreen::enable()
|
||||
{
|
||||
assert(m_isOnScreen == m_isPrimary);
|
||||
|
||||
// we need to poll some things to fix them
|
||||
m_fixTimer = EVENTQUEUE->newTimer(1.0, NULL);
|
||||
EVENTQUEUE->adoptHandler(CEvent::kTimer, m_fixTimer,
|
||||
new TMethodEventJob<CMSWindowsScreen>(this,
|
||||
&CMSWindowsScreen::handleFixes));
|
||||
|
||||
// install our clipboard snooper
|
||||
m_nextClipboardWindow = SetClipboardViewer(m_window);
|
||||
|
||||
@@ -232,17 +232,20 @@ CMSWindowsScreen::disable()
|
||||
CArchMiscWindows::kDISPLAY);
|
||||
}
|
||||
|
||||
// uninstall fix key timer
|
||||
// tell key state
|
||||
m_keyState->disable();
|
||||
|
||||
// stop snooping the clipboard
|
||||
ChangeClipboardChain(m_window, m_nextClipboardWindow);
|
||||
m_nextClipboardWindow = NULL;
|
||||
|
||||
// uninstall fix timer
|
||||
if (m_fixTimer != NULL) {
|
||||
EVENTQUEUE->removeHandler(CEvent::kTimer, m_fixTimer);
|
||||
EVENTQUEUE->deleteTimer(m_fixTimer);
|
||||
m_fixTimer = NULL;
|
||||
}
|
||||
|
||||
// stop snooping the clipboard
|
||||
ChangeClipboardChain(m_window, m_nextClipboardWindow);
|
||||
m_nextClipboardWindow = NULL;
|
||||
|
||||
m_isOnScreen = m_isPrimary;
|
||||
forceShowCursor();
|
||||
}
|
||||
@@ -292,6 +295,10 @@ CMSWindowsScreen::leave()
|
||||
// all messages prior to now are invalid
|
||||
nextMark();
|
||||
|
||||
// remember the modifier state. this is the modifier state
|
||||
// reflected in the internal keyboard state.
|
||||
m_keyState->saveModifiers();
|
||||
|
||||
// capture events
|
||||
m_setMode(kHOOK_RELAY_EVENTS);
|
||||
}
|
||||
@@ -388,13 +395,13 @@ CMSWindowsScreen::screensaver(bool activate)
|
||||
void
|
||||
CMSWindowsScreen::resetOptions()
|
||||
{
|
||||
// no options
|
||||
m_desks->resetOptions();
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::setOptions(const COptionsList&)
|
||||
CMSWindowsScreen::setOptions(const COptionsList& options)
|
||||
{
|
||||
// no options
|
||||
m_desks->setOptions(options);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -467,6 +474,130 @@ CMSWindowsScreen::warpCursor(SInt32 x, SInt32 y)
|
||||
m_yCursor = y;
|
||||
}
|
||||
|
||||
UInt32
|
||||
CMSWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
|
||||
{
|
||||
// only allow certain modifiers
|
||||
if ((mask & ~(KeyModifierShift | KeyModifierControl |
|
||||
KeyModifierAlt | KeyModifierSuper)) != 0) {
|
||||
LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fail if no keys
|
||||
if (key == kKeyNone && mask == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// convert to win32
|
||||
UINT modifiers = 0;
|
||||
if ((mask & KeyModifierShift) != 0) {
|
||||
modifiers |= MOD_SHIFT;
|
||||
}
|
||||
if ((mask & KeyModifierControl) != 0) {
|
||||
modifiers |= MOD_CONTROL;
|
||||
}
|
||||
if ((mask & KeyModifierAlt) != 0) {
|
||||
modifiers |= MOD_ALT;
|
||||
}
|
||||
if ((mask & KeyModifierSuper) != 0) {
|
||||
modifiers |= MOD_WIN;
|
||||
}
|
||||
UINT vk = m_keyState->mapKeyToVirtualKey(key);
|
||||
if (key != kKeyNone && vk == 0) {
|
||||
// can't map key
|
||||
LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// choose hotkey id
|
||||
UInt32 id;
|
||||
if (!m_oldHotKeyIDs.empty()) {
|
||||
id = m_oldHotKeyIDs.back();
|
||||
m_oldHotKeyIDs.pop_back();
|
||||
}
|
||||
else {
|
||||
id = m_hotKeys.size() + 1;
|
||||
}
|
||||
|
||||
// if this hot key has modifiers only then we'll handle it specially
|
||||
bool err;
|
||||
if (key == kKeyNone) {
|
||||
// check if already registered
|
||||
err = (m_hotKeyToIDMap.count(CHotKeyItem(vk, modifiers)) > 0);
|
||||
}
|
||||
else {
|
||||
// register with OS
|
||||
err = (RegisterHotKey(NULL, id, modifiers, vk) == 0);
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
m_hotKeys.insert(std::make_pair(id, CHotKeyItem(vk, modifiers)));
|
||||
m_hotKeyToIDMap[CHotKeyItem(vk, modifiers)] = id;
|
||||
}
|
||||
else {
|
||||
m_oldHotKeyIDs.push_back(id);
|
||||
m_hotKeys.erase(id);
|
||||
LOG((CLOG_WARN "failed to register hotkey %s (id=%04x mask=%04x)", CKeyMap::formatKey(key, mask).c_str(), key, mask));
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOG((CLOG_DEBUG "registered hotkey %s (id=%04x mask=%04x) as id=%d", CKeyMap::formatKey(key, mask).c_str(), key, mask, id));
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::unregisterHotKey(UInt32 id)
|
||||
{
|
||||
// look up hotkey
|
||||
HotKeyMap::iterator i = m_hotKeys.find(id);
|
||||
if (i == m_hotKeys.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// unregister with OS
|
||||
bool err;
|
||||
if (i->second.getVirtualKey() != 0) {
|
||||
err = !UnregisterHotKey(NULL, id);
|
||||
}
|
||||
else {
|
||||
err = false;
|
||||
}
|
||||
if (err) {
|
||||
LOG((CLOG_WARN "failed to unregister hotkey id=%d", id));
|
||||
}
|
||||
else {
|
||||
LOG((CLOG_DEBUG "unregistered hotkey id=%d", id));
|
||||
}
|
||||
|
||||
// discard hot key from map and record old id for reuse
|
||||
m_hotKeyToIDMap.erase(i->second);
|
||||
m_hotKeys.erase(i);
|
||||
m_oldHotKeyIDs.push_back(id);
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::fakeInputBegin()
|
||||
{
|
||||
assert(m_isPrimary);
|
||||
|
||||
if (!m_isOnScreen) {
|
||||
m_keyState->useSavedModifiers(true);
|
||||
}
|
||||
m_desks->fakeInputBegin();
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::fakeInputEnd()
|
||||
{
|
||||
assert(m_isPrimary);
|
||||
|
||||
m_desks->fakeInputEnd();
|
||||
if (!m_isOnScreen) {
|
||||
m_keyState->useSavedModifiers(false);
|
||||
}
|
||||
}
|
||||
|
||||
SInt32
|
||||
CMSWindowsScreen::getJumpZoneSize() const
|
||||
{
|
||||
@@ -521,9 +652,9 @@ CMSWindowsScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::fakeMouseWheel(SInt32 delta) const
|
||||
CMSWindowsScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
|
||||
{
|
||||
m_desks->fakeMouseWheel(delta);
|
||||
m_desks->fakeMouseWheel(xDelta, yDelta);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -556,9 +687,9 @@ CMSWindowsScreen::fakeKeyUp(KeyButton button)
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::fakeToggle(KeyModifierMask modifier)
|
||||
CMSWindowsScreen::fakeAllKeysUp()
|
||||
{
|
||||
CPlatformScreen::fakeToggle(modifier);
|
||||
CPlatformScreen::fakeAllKeysUp();
|
||||
updateForceShowCursor();
|
||||
}
|
||||
|
||||
@@ -776,7 +907,8 @@ CMSWindowsScreen::onPreDispatchPrimary(HWND,
|
||||
static_cast<SInt32>(lParam));
|
||||
|
||||
case SYNERGY_MSG_MOUSE_WHEEL:
|
||||
return onMouseWheel(static_cast<SInt32>(wParam));
|
||||
// XXX -- support x-axis scrolling
|
||||
return onMouseWheel(0, static_cast<SInt32>(wParam));
|
||||
|
||||
case SYNERGY_MSG_PRE_WARP:
|
||||
{
|
||||
@@ -800,6 +932,13 @@ CMSWindowsScreen::onPreDispatchPrimary(HWND,
|
||||
case SYNERGY_MSG_POST_WARP:
|
||||
LOG((CLOG_WARN "unmatched post warp"));
|
||||
return true;
|
||||
|
||||
case WM_HOTKEY:
|
||||
// we discard these messages. we'll catch the hot key in the
|
||||
// regular key event handling, where we can detect both key
|
||||
// press and release. we only register the hot key so no other
|
||||
// app will act on the key combination.
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -827,8 +966,6 @@ CMSWindowsScreen::onEvent(HWND, UINT msg,
|
||||
break;
|
||||
|
||||
case WM_DRAWCLIPBOARD:
|
||||
LOG((CLOG_DEBUG "clipboard was taken"));
|
||||
|
||||
// first pass on the message
|
||||
if (m_nextClipboardWindow != NULL) {
|
||||
SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
|
||||
@@ -843,7 +980,6 @@ CMSWindowsScreen::onEvent(HWND, UINT msg,
|
||||
LOG((CLOG_DEBUG "clipboard chain: new next: 0x%08x", m_nextClipboardWindow));
|
||||
}
|
||||
else if (m_nextClipboardWindow != NULL) {
|
||||
LOG((CLOG_DEBUG "clipboard chain: forward: %d 0x%08x 0x%08x", msg, wParam, lParam));
|
||||
SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
|
||||
}
|
||||
return true;
|
||||
@@ -856,15 +992,15 @@ CMSWindowsScreen::onEvent(HWND, UINT msg,
|
||||
case PBT_APMRESUMEAUTOMATIC:
|
||||
case PBT_APMRESUMECRITICAL:
|
||||
case PBT_APMRESUMESUSPEND:
|
||||
if (m_resume != NULL) {
|
||||
m_resume->run();
|
||||
}
|
||||
EVENTQUEUE->addEvent(CEvent(IScreen::getResumeEvent(),
|
||||
getEventTarget(), NULL,
|
||||
CEvent::kDeliverImmediately));
|
||||
break;
|
||||
|
||||
case PBT_APMSUSPEND:
|
||||
if (m_suspend != NULL) {
|
||||
m_suspend->run();
|
||||
}
|
||||
EVENTQUEUE->addEvent(CEvent(IScreen::getSuspendEvent(),
|
||||
getEventTarget(), NULL,
|
||||
CEvent::kDeliverImmediately));
|
||||
break;
|
||||
}
|
||||
*result = TRUE;
|
||||
@@ -894,62 +1030,70 @@ CMSWindowsScreen::onMark(UInt32 mark)
|
||||
bool
|
||||
CMSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, lParam=0x%08x", (wParam & 0xff00u) >> 8, wParam & 0xffu, lParam));
|
||||
static const KeyModifierMask s_ctrlAlt =
|
||||
KeyModifierControl | KeyModifierAlt;
|
||||
|
||||
// fix up key state
|
||||
fixKeys();
|
||||
LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, nagr=%d, lParam=0x%08x", (wParam & 0xff00u) >> 8, wParam & 0xffu, (wParam & 0x10000u) ? 1 : 0, lParam));
|
||||
|
||||
// get key info
|
||||
KeyButton button = (KeyButton)((lParam & 0x01ff0000) >> 16);
|
||||
bool down = ((lParam & 0xc0000000u) == 0x00000000u);
|
||||
bool up = ((lParam & 0x80000000u) == 0x80000000u);
|
||||
bool wasDown = isKeyDown(button);
|
||||
// get event info
|
||||
KeyButton button = (KeyButton)((lParam & 0x01ff0000) >> 16);
|
||||
bool down = ((lParam & 0x80000000u) == 0x00000000u);
|
||||
bool wasDown = isKeyDown(button);
|
||||
KeyModifierMask oldState = pollActiveModifiers();
|
||||
|
||||
// the windows keys are a royal pain on the windows 95 family.
|
||||
// the system eats the key up events if and only if the windows
|
||||
// key wasn't combined with another key, i.e. it was tapped.
|
||||
// fixKeys() and scheduleFixKeys() are all about synthesizing
|
||||
// the missing key up. but even windows itself gets a little
|
||||
// confused and sets bit 30 in lParam if you tap the windows
|
||||
// key twice. that bit means the key was previously down and
|
||||
// that makes some sense since the up event was missing.
|
||||
// anyway, on the windows 95 family we forget about windows
|
||||
// key repeats and treat anything that's not a key down as a
|
||||
// key up.
|
||||
if (m_is95Family &&
|
||||
((wParam & 0xffu) == VK_LWIN || (wParam & 0xffu) == VK_RWIN)) {
|
||||
down = !up;
|
||||
// check for autorepeat
|
||||
if (m_keyState->testAutoRepeat(down, (lParam & 0x40000000u) == 1, button)) {
|
||||
lParam |= 0x40000000u;
|
||||
}
|
||||
|
||||
// update key state. ignore key repeats.
|
||||
if (down) {
|
||||
m_keyState->setKeyDown(button, true);
|
||||
}
|
||||
else if (up) {
|
||||
m_keyState->setKeyDown(button, false);
|
||||
// if the button is zero then guess what the button should be.
|
||||
// these are badly synthesized key events and logitech software
|
||||
// that maps mouse buttons to keys is known to do this.
|
||||
// alternatively, we could just throw these events out.
|
||||
if (button == 0) {
|
||||
button = m_keyState->virtualKeyToButton(wParam & 0xffu);
|
||||
if (button == 0) {
|
||||
return true;
|
||||
}
|
||||
wasDown = isKeyDown(button);
|
||||
}
|
||||
|
||||
// schedule a timer if we need to fix keys later
|
||||
scheduleFixKeys();
|
||||
// record keyboard state
|
||||
m_keyState->onKey(button, down, oldState);
|
||||
|
||||
// special case: we detect ctrl+alt+del being pressed on some
|
||||
// systems but we don't detect the release of those keys. so
|
||||
// if ctrl, alt, and del are down then mark them up.
|
||||
KeyModifierMask mask = getActiveModifiers();
|
||||
bool ctrlAlt = ((mask & (KeyModifierControl | KeyModifierAlt)) ==
|
||||
(KeyModifierControl | KeyModifierAlt));
|
||||
if (down && ctrlAlt &&
|
||||
isKeyDown(m_keyState->virtualKeyToButton(VK_DELETE))) {
|
||||
m_keyState->setKeyDown(
|
||||
m_keyState->virtualKeyToButton(VK_LCONTROL), false);
|
||||
m_keyState->setKeyDown(
|
||||
m_keyState->virtualKeyToButton(VK_RCONTROL), false);
|
||||
m_keyState->setKeyDown(
|
||||
m_keyState->virtualKeyToButton(VK_LMENU), false);
|
||||
m_keyState->setKeyDown(
|
||||
m_keyState->virtualKeyToButton(VK_RMENU), false);
|
||||
m_keyState->setKeyDown(
|
||||
m_keyState->virtualKeyToButton(VK_DELETE), false);
|
||||
// windows doesn't tell us the modifier key state on mouse or key
|
||||
// events so we have to figure it out. most apps would use
|
||||
// GetKeyState() or even GetAsyncKeyState() for that but we can't
|
||||
// because our hook doesn't pass on key events for several modifiers.
|
||||
// it can't otherwise the system would interpret them normally on
|
||||
// the primary screen even when on a secondary screen. so tapping
|
||||
// alt would activate menus and tapping the windows key would open
|
||||
// the start menu. if you don't pass those events on in the hook
|
||||
// then GetKeyState() understandably doesn't reflect the effect of
|
||||
// the event. curiously, neither does GetAsyncKeyState(), which is
|
||||
// surprising.
|
||||
//
|
||||
// so anyway, we have to track the modifier state ourselves for
|
||||
// at least those modifiers we don't pass on. pollActiveModifiers()
|
||||
// does that but we have to update the keyboard state before calling
|
||||
// pollActiveModifiers() to get the right answer. but the only way
|
||||
// to set the modifier state or to set the up/down state of a key
|
||||
// is via onKey(). so we have to call onKey() twice.
|
||||
KeyModifierMask state = pollActiveModifiers();
|
||||
m_keyState->onKey(button, down, state);
|
||||
|
||||
// check for hot keys
|
||||
if (oldState != state) {
|
||||
// modifier key was pressed/released
|
||||
if (onHotKey(0, lParam)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// non-modifier was pressed/released
|
||||
if (onHotKey(wParam, lParam)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ignore message if posted prior to last mark change
|
||||
@@ -957,20 +1101,23 @@ CMSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
||||
// check for ctrl+alt+del. we do not want to pass that to the
|
||||
// client. the user can use ctrl+alt+pause to emulate it.
|
||||
UINT virtKey = (wParam & 0xffu);
|
||||
if (virtKey == VK_DELETE && ctrlAlt) {
|
||||
if (virtKey == VK_DELETE && (state & s_ctrlAlt) == s_ctrlAlt) {
|
||||
LOG((CLOG_DEBUG "discard ctrl+alt+del"));
|
||||
return true;
|
||||
}
|
||||
|
||||
// check for ctrl+alt+del emulation
|
||||
if ((virtKey == VK_PAUSE || virtKey == VK_CANCEL) && ctrlAlt) {
|
||||
if ((virtKey == VK_PAUSE || virtKey == VK_CANCEL) &&
|
||||
(state & s_ctrlAlt) == s_ctrlAlt) {
|
||||
LOG((CLOG_DEBUG "emulate ctrl+alt+del"));
|
||||
// switch wParam and lParam to be as if VK_DELETE was
|
||||
// pressed or released
|
||||
wParam = VK_DELETE;
|
||||
// pressed or released. when mapping the key we require that
|
||||
// we not use AltGr (the 0x10000 flag in wParam) and we not
|
||||
// use the keypad delete key (the 0x01000000 flag in lParam).
|
||||
wParam = VK_DELETE | 0x00010000u;
|
||||
lParam &= 0xfe000000;
|
||||
lParam |= m_keyState->virtualKeyToButton(wParam) << 16;
|
||||
lParam |= 0x00000001;
|
||||
lParam |= m_keyState->virtualKeyToButton(wParam & 0xffu) << 16;
|
||||
lParam |= 0x01000001;
|
||||
}
|
||||
|
||||
// process key
|
||||
@@ -978,28 +1125,28 @@ CMSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
||||
KeyID key = m_keyState->mapKeyFromEvent(wParam, lParam, &mask);
|
||||
button = static_cast<KeyButton>((lParam & 0x01ff0000u) >> 16);
|
||||
if (key != kKeyNone) {
|
||||
// fix up key. if the key isn't down according to
|
||||
// fix key up. if the key isn't down according to
|
||||
// our table then we never got the key press event
|
||||
// for it. if it's not a modifier key then we'll
|
||||
// synthesize the press first. only do this on
|
||||
// the windows 95 family, which eats certain special
|
||||
// keys like alt+tab, ctrl+esc, etc.
|
||||
if (m_is95Family && !wasDown && up) {
|
||||
if (m_is95Family && !wasDown && !down) {
|
||||
switch (virtKey) {
|
||||
case VK_SHIFT:
|
||||
case VK_LSHIFT:
|
||||
case VK_RSHIFT:
|
||||
case VK_SHIFT:
|
||||
case VK_CONTROL:
|
||||
case VK_LCONTROL:
|
||||
case VK_RCONTROL:
|
||||
case VK_CONTROL:
|
||||
case VK_MENU:
|
||||
case VK_LMENU:
|
||||
case VK_RMENU:
|
||||
case VK_MENU:
|
||||
case VK_LWIN:
|
||||
case VK_RWIN:
|
||||
case VK_CAPITAL:
|
||||
case VK_NUMLOCK:
|
||||
case VK_SCROLL:
|
||||
case VK_LWIN:
|
||||
case VK_RWIN:
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1012,17 +1159,64 @@ CMSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
||||
// do it
|
||||
m_keyState->sendKeyEvent(getEventTarget(),
|
||||
((lParam & 0x80000000u) == 0),
|
||||
((lParam & 0x40000000u) == 1),
|
||||
((lParam & 0x40000000u) != 0),
|
||||
key, mask, (SInt32)(lParam & 0xffff), button);
|
||||
}
|
||||
else {
|
||||
LOG((CLOG_DEBUG2 "event: cannot map key"));
|
||||
LOG((CLOG_DEBUG1 "cannot map key"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CMSWindowsScreen::onHotKey(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// get the key info
|
||||
KeyModifierMask state = getActiveModifiers();
|
||||
UINT virtKey = (wParam & 0xffu);
|
||||
UINT modifiers = 0;
|
||||
if ((state & KeyModifierShift) != 0) {
|
||||
modifiers |= MOD_SHIFT;
|
||||
}
|
||||
if ((state & KeyModifierControl) != 0) {
|
||||
modifiers |= MOD_CONTROL;
|
||||
}
|
||||
if ((state & KeyModifierAlt) != 0) {
|
||||
modifiers |= MOD_ALT;
|
||||
}
|
||||
if ((state & KeyModifierSuper) != 0) {
|
||||
modifiers |= MOD_WIN;
|
||||
}
|
||||
|
||||
// find the hot key id
|
||||
HotKeyToIDMap::const_iterator i =
|
||||
m_hotKeyToIDMap.find(CHotKeyItem(virtKey, modifiers));
|
||||
if (i == m_hotKeyToIDMap.end()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// find what kind of event
|
||||
CEvent::Type type;
|
||||
if ((lParam & 0x80000000u) == 0u) {
|
||||
if ((lParam & 0x40000000u) != 0u) {
|
||||
// ignore key repeats but it counts as a hot key
|
||||
return true;
|
||||
}
|
||||
type = getHotKeyDownEvent();
|
||||
}
|
||||
else {
|
||||
type = getHotKeyUpEvent();
|
||||
}
|
||||
|
||||
// generate event
|
||||
EVENTQUEUE->addEvent(CEvent(type, getEventTarget(),
|
||||
CHotKeyInfo::alloc(i->second)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CMSWindowsScreen::onMouseButton(WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
@@ -1042,16 +1236,19 @@ CMSWindowsScreen::onMouseButton(WPARAM wParam, LPARAM lParam)
|
||||
|
||||
// ignore message if posted prior to last mark change
|
||||
if (!ignore()) {
|
||||
KeyModifierMask mask = m_keyState->getActiveModifiers();
|
||||
if (pressed) {
|
||||
LOG((CLOG_DEBUG1 "event: button press button=%d", button));
|
||||
if (button != kButtonNone) {
|
||||
sendEvent(getButtonDownEvent(), CButtonInfo::alloc(button));
|
||||
sendEvent(getButtonDownEvent(),
|
||||
CButtonInfo::alloc(button, mask));
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG((CLOG_DEBUG1 "event: button release button=%d", button));
|
||||
if (button != kButtonNone) {
|
||||
sendEvent(getButtonUpEvent(), CButtonInfo::alloc(button));
|
||||
sendEvent(getButtonUpEvent(),
|
||||
CButtonInfo::alloc(button, mask));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1109,12 +1306,12 @@ CMSWindowsScreen::onMouseMove(SInt32 mx, SInt32 my)
|
||||
}
|
||||
|
||||
bool
|
||||
CMSWindowsScreen::onMouseWheel(SInt32 delta)
|
||||
CMSWindowsScreen::onMouseWheel(SInt32 xDelta, SInt32 yDelta)
|
||||
{
|
||||
// ignore message if posted prior to last mark change
|
||||
if (!ignore()) {
|
||||
LOG((CLOG_DEBUG1 "event: button wheel delta=%d", delta));
|
||||
sendEvent(getWheelEvent(), CWheelInfo::alloc(delta));
|
||||
LOG((CLOG_DEBUG1 "event: button wheel delta=%+d,%+d", xDelta, yDelta));
|
||||
sendEvent(getWheelEvent(), CWheelInfo::alloc(xDelta, yDelta));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1197,7 +1394,6 @@ CMSWindowsScreen::onClipboardChange()
|
||||
// now notify client that somebody changed the clipboard (unless
|
||||
// we're the owner).
|
||||
if (!CMSWindowsClipboard::isOwnedBySynergy()) {
|
||||
LOG((CLOG_DEBUG "clipboard changed: foreign owned"));
|
||||
if (m_ownClipboard) {
|
||||
LOG((CLOG_DEBUG "clipboard changed: lost ownership"));
|
||||
m_ownClipboard = false;
|
||||
@@ -1205,7 +1401,7 @@ CMSWindowsScreen::onClipboardChange()
|
||||
sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection);
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (!m_ownClipboard) {
|
||||
LOG((CLOG_DEBUG "clipboard changed: synergy owned"));
|
||||
m_ownClipboard = true;
|
||||
}
|
||||
@@ -1282,6 +1478,34 @@ CMSWindowsScreen::updateScreenShape()
|
||||
m_desks->setShape(m_x, m_y, m_w, m_h, m_xCenter, m_yCenter, m_multimon);
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::handleFixes(const CEvent&, void*)
|
||||
{
|
||||
// fix clipboard chain
|
||||
fixClipboardViewer();
|
||||
|
||||
// update keys if keyboard layouts have changed
|
||||
if (m_keyState->didGroupsChange()) {
|
||||
updateKeys();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::fixClipboardViewer()
|
||||
{
|
||||
// XXX -- disable this code for now. somehow it can cause an infinite
|
||||
// recursion in the WM_DRAWCLIPBOARD handler. either we're sending
|
||||
// the message to our own window or some window farther down the chain
|
||||
// forwards the message to our window or a window farther up the chain.
|
||||
// i'm not sure how that could happen. the m_nextClipboardWindow = NULL
|
||||
// was not in the code that infinite loops and may fix the bug but i
|
||||
// doubt it.
|
||||
return;
|
||||
ChangeClipboardChain(m_window, m_nextClipboardWindow);
|
||||
m_nextClipboardWindow = NULL;
|
||||
m_nextClipboardWindow = SetClipboardViewer(m_window);
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::enableSpecialKeys(bool enable) const
|
||||
{
|
||||
@@ -1387,63 +1611,37 @@ CMSWindowsScreen::mapPressFromEvent(WPARAM msg, LPARAM) const
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::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) {
|
||||
m_keyState->fixKey(getEventTarget(), VK_LWIN);
|
||||
m_keyState->fixKey(getEventTarget(), VK_RWIN);
|
||||
|
||||
// check if we need the fix timer anymore
|
||||
scheduleFixKeys();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::scheduleFixKeys()
|
||||
{
|
||||
if (m_is95Family) {
|
||||
// see if any keys that need fixing are down
|
||||
bool fix =
|
||||
(m_keyState->isKeyDown(m_keyState->virtualKeyToButton(VK_LWIN)) ||
|
||||
m_keyState->isKeyDown(m_keyState->virtualKeyToButton(VK_RWIN)));
|
||||
|
||||
// start or stop fix timer
|
||||
if (fix && m_fixTimer == NULL) {
|
||||
m_fixTimer = EVENTQUEUE->newTimer(0.1, NULL);
|
||||
EVENTQUEUE->adoptHandler(CEvent::kTimer, m_fixTimer,
|
||||
new TMethodEventJob<CMSWindowsScreen>(
|
||||
this, &CMSWindowsScreen::handleFixKeys));
|
||||
}
|
||||
else if (!fix && m_fixTimer != NULL) {
|
||||
EVENTQUEUE->removeHandler(CEvent::kTimer, m_fixTimer);
|
||||
EVENTQUEUE->deleteTimer(m_fixTimer);
|
||||
m_fixTimer = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::handleFixKeys(const CEvent&, void*)
|
||||
{
|
||||
fixKeys();
|
||||
}
|
||||
|
||||
void
|
||||
CMSWindowsScreen::updateKeysCB(void*)
|
||||
{
|
||||
m_keyState->updateKeys();
|
||||
updateButtons();
|
||||
// record which keys we think are down
|
||||
bool down[IKeyState::kNumButtons];
|
||||
bool sendFixes = (isPrimary() && !m_isOnScreen);
|
||||
if (sendFixes) {
|
||||
for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) {
|
||||
down[i] = m_keyState->isKeyDown(i);
|
||||
}
|
||||
}
|
||||
|
||||
// update layouts if necessary
|
||||
if (m_keyState->didGroupsChange()) {
|
||||
CPlatformScreen::updateKeyMap();
|
||||
}
|
||||
|
||||
// now update the keyboard state
|
||||
CPlatformScreen::updateKeyState();
|
||||
|
||||
// now see which keys we thought were down but now think are up.
|
||||
// send key releases for these keys to the active client.
|
||||
if (sendFixes) {
|
||||
KeyModifierMask mask = pollActiveModifiers();
|
||||
for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) {
|
||||
if (down[i] && !m_keyState->isKeyDown(i)) {
|
||||
m_keyState->sendKeyEvent(getEventTarget(),
|
||||
false, false, kKeyNone, mask, 1, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1512,3 +1710,28 @@ CMSWindowsScreen::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CMSWindowsScreen::CHotKeyItem
|
||||
//
|
||||
|
||||
CMSWindowsScreen::CHotKeyItem::CHotKeyItem(UINT keycode, UINT mask) :
|
||||
m_keycode(keycode),
|
||||
m_mask(mask)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
UINT
|
||||
CMSWindowsScreen::CHotKeyItem::getVirtualKey() const
|
||||
{
|
||||
return m_keycode;
|
||||
}
|
||||
|
||||
bool
|
||||
CMSWindowsScreen::CHotKeyItem::operator<(const CHotKeyItem& x) const
|
||||
{
|
||||
return (m_keycode < x.m_keycode ||
|
||||
(m_keycode == x.m_keycode && m_mask < x.m_mask));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user