Made releaseKeys() only synthesize key releases for those keys
that synergy synthesized a press for, not keys that the user is physically pressing.
This commit is contained in:
parent
de64342292
commit
74e50877e9
|
@ -21,6 +21,7 @@ EXTRA_DIST = \
|
||||||
IInterface.h \
|
IInterface.h \
|
||||||
Version.h \
|
Version.h \
|
||||||
common.h \
|
common.h \
|
||||||
|
stdbitset.h \
|
||||||
stdfstream.h \
|
stdfstream.h \
|
||||||
stdistream.h \
|
stdistream.h \
|
||||||
stdlist.h \
|
stdlist.h \
|
||||||
|
|
|
@ -103,6 +103,10 @@ SOURCE=.\IInterface.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\stdbitset.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
SOURCE=.\stdfstream.h
|
SOURCE=.\stdfstream.h
|
||||||
# End Source File
|
# End Source File
|
||||||
# Begin Source File
|
# Begin Source File
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
* synergy -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2002 Chris Schoeneman
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file COPYING that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "stdpre.h"
|
||||||
|
#include <bitset>
|
||||||
|
#include "stdpost.h"
|
|
@ -68,21 +68,25 @@ CMSWindowsSecondaryScreen::keyDown(KeyID key, KeyModifierMask mask)
|
||||||
doKeystrokes(keys, 1);
|
doKeystrokes(keys, 1);
|
||||||
|
|
||||||
// note that key is now down
|
// note that key is now down
|
||||||
m_keys[virtualKey] |= 0x80;
|
m_keys[virtualKey] |= 0x80;
|
||||||
|
m_fakeKeys[virtualKey] |= 0x80;
|
||||||
switch (virtualKey) {
|
switch (virtualKey) {
|
||||||
case VK_LSHIFT:
|
case VK_LSHIFT:
|
||||||
case VK_RSHIFT:
|
case VK_RSHIFT:
|
||||||
m_keys[VK_SHIFT] |= 0x80;
|
m_keys[VK_SHIFT] |= 0x80;
|
||||||
|
m_fakeKeys[VK_SHIFT] |= 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VK_LCONTROL:
|
case VK_LCONTROL:
|
||||||
case VK_RCONTROL:
|
case VK_RCONTROL:
|
||||||
m_keys[VK_CONTROL] |= 0x80;
|
m_keys[VK_CONTROL] |= 0x80;
|
||||||
|
m_fakeKeys[VK_CONTROL] |= 0x80;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VK_LMENU:
|
case VK_LMENU:
|
||||||
case VK_RMENU:
|
case VK_RMENU:
|
||||||
m_keys[VK_MENU] |= 0x80;
|
m_keys[VK_MENU] |= 0x80;
|
||||||
|
m_fakeKeys[VK_MENU] |= 0x80;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -128,41 +132,48 @@ CMSWindowsSecondaryScreen::keyUp(KeyID key, KeyModifierMask mask)
|
||||||
doKeystrokes(keys, 1);
|
doKeystrokes(keys, 1);
|
||||||
|
|
||||||
// note that key is now up
|
// note that key is now up
|
||||||
m_keys[virtualKey] &= ~0x80;
|
m_keys[virtualKey] &= ~0x80;
|
||||||
|
m_fakeKeys[virtualKey] &= ~0x80;
|
||||||
switch (virtualKey) {
|
switch (virtualKey) {
|
||||||
case VK_LSHIFT:
|
case VK_LSHIFT:
|
||||||
if ((m_keys[VK_RSHIFT] & 0x80) == 0) {
|
if ((m_keys[VK_RSHIFT] & 0x80) == 0) {
|
||||||
m_keys[VK_SHIFT] &= ~0x80;
|
m_keys[VK_SHIFT] &= ~0x80;
|
||||||
|
m_fakeKeys[VK_SHIFT] &= ~0x80;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VK_RSHIFT:
|
case VK_RSHIFT:
|
||||||
if ((m_keys[VK_LSHIFT] & 0x80) == 0) {
|
if ((m_keys[VK_LSHIFT] & 0x80) == 0) {
|
||||||
m_keys[VK_SHIFT] &= ~0x80;
|
m_keys[VK_SHIFT] &= ~0x80;
|
||||||
|
m_fakeKeys[VK_SHIFT] &= ~0x80;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VK_LCONTROL:
|
case VK_LCONTROL:
|
||||||
if ((m_keys[VK_RCONTROL] & 0x80) == 0) {
|
if ((m_keys[VK_RCONTROL] & 0x80) == 0) {
|
||||||
m_keys[VK_CONTROL] &= ~0x80;
|
m_keys[VK_CONTROL] &= ~0x80;
|
||||||
|
m_fakeKeys[VK_CONTROL] &= ~0x80;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VK_RCONTROL:
|
case VK_RCONTROL:
|
||||||
if ((m_keys[VK_LCONTROL] & 0x80) == 0) {
|
if ((m_keys[VK_LCONTROL] & 0x80) == 0) {
|
||||||
m_keys[VK_CONTROL] &= ~0x80;
|
m_keys[VK_CONTROL] &= ~0x80;
|
||||||
|
m_fakeKeys[VK_CONTROL] &= ~0x80;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VK_LMENU:
|
case VK_LMENU:
|
||||||
if ((m_keys[VK_RMENU] & 0x80) == 0) {
|
if ((m_keys[VK_RMENU] & 0x80) == 0) {
|
||||||
m_keys[VK_MENU] &= ~0x80;
|
m_keys[VK_MENU] &= ~0x80;
|
||||||
|
m_fakeKeys[VK_MENU] &= ~0x80;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VK_RMENU:
|
case VK_RMENU:
|
||||||
if ((m_keys[VK_LMENU] & 0x80) == 0) {
|
if ((m_keys[VK_LMENU] & 0x80) == 0) {
|
||||||
m_keys[VK_MENU] &= ~0x80;
|
m_keys[VK_MENU] &= ~0x80;
|
||||||
|
m_fakeKeys[VK_MENU] &= ~0x80;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -439,6 +450,7 @@ CMSWindowsSecondaryScreen::updateKeys()
|
||||||
{
|
{
|
||||||
// clear key state
|
// clear key state
|
||||||
memset(m_keys, 0, sizeof(m_keys));
|
memset(m_keys, 0, sizeof(m_keys));
|
||||||
|
memset(m_fakeKeys, 0, sizeof(m_keys));
|
||||||
|
|
||||||
// we only care about the modifier key states
|
// we only care about the modifier key states
|
||||||
m_keys[VK_LSHIFT] = static_cast<BYTE>(GetKeyState(VK_LSHIFT));
|
m_keys[VK_LSHIFT] = static_cast<BYTE>(GetKeyState(VK_LSHIFT));
|
||||||
|
@ -457,6 +469,11 @@ CMSWindowsSecondaryScreen::updateKeys()
|
||||||
m_keys[VK_NUMLOCK] = static_cast<BYTE>(GetKeyState(VK_NUMLOCK));
|
m_keys[VK_NUMLOCK] = static_cast<BYTE>(GetKeyState(VK_NUMLOCK));
|
||||||
m_keys[VK_SCROLL] = static_cast<BYTE>(GetKeyState(VK_SCROLL));
|
m_keys[VK_SCROLL] = static_cast<BYTE>(GetKeyState(VK_SCROLL));
|
||||||
|
|
||||||
|
// copy over lock states to m_fakeKeys
|
||||||
|
m_fakeKeys[VK_CAPITAL] = (m_keys[VK_CAPITAL] & 0x01);
|
||||||
|
m_fakeKeys[VK_NUMLOCK] = (m_keys[VK_NUMLOCK] & 0x01);
|
||||||
|
m_fakeKeys[VK_SCROLL] = (m_keys[VK_SCROLL] & 0x01);
|
||||||
|
|
||||||
// update active modifier mask
|
// update active modifier mask
|
||||||
m_mask = 0;
|
m_mask = 0;
|
||||||
if ((m_keys[VK_LSHIFT] & 0x80) != 0 || (m_keys[VK_RSHIFT] & 0x80) != 0) {
|
if ((m_keys[VK_LSHIFT] & 0x80) != 0 || (m_keys[VK_RSHIFT] & 0x80) != 0) {
|
||||||
|
@ -1012,6 +1029,10 @@ CMSWindowsSecondaryScreen::doKeystrokes(const Keystrokes& keys, SInt32 count)
|
||||||
void
|
void
|
||||||
CMSWindowsSecondaryScreen::releaseKeys()
|
CMSWindowsSecondaryScreen::releaseKeys()
|
||||||
{
|
{
|
||||||
|
// release keys that we've synthesized a press for and only those
|
||||||
|
// keys. we don't want to synthesize a release on a key the user
|
||||||
|
// is still physically pressing.
|
||||||
|
|
||||||
CLock lock(&m_mutex);
|
CLock lock(&m_mutex);
|
||||||
|
|
||||||
m_screen->syncDesktop();
|
m_screen->syncDesktop();
|
||||||
|
@ -1020,42 +1041,42 @@ CMSWindowsSecondaryScreen::releaseKeys()
|
||||||
// support them then they won't be set and the non-side-distinuishing
|
// support them then they won't be set and the non-side-distinuishing
|
||||||
// key will retain its state. if the platform does support them then
|
// key will retain its state. if the platform does support them then
|
||||||
// the non-side-distinguishing will be reset.
|
// the non-side-distinguishing will be reset.
|
||||||
if ((m_keys[VK_LSHIFT] & 0x80) != 0) {
|
if ((m_fakeKeys[VK_LSHIFT] & 0x80) != 0) {
|
||||||
sendKeyEvent(VK_LSHIFT, false);
|
sendKeyEvent(VK_LSHIFT, false);
|
||||||
m_keys[VK_SHIFT] = 0;
|
m_fakeKeys[VK_SHIFT] = 0;
|
||||||
m_keys[VK_LSHIFT] = 0;
|
m_fakeKeys[VK_LSHIFT] = 0;
|
||||||
}
|
}
|
||||||
if ((m_keys[VK_RSHIFT] & 0x80) != 0) {
|
if ((m_fakeKeys[VK_RSHIFT] & 0x80) != 0) {
|
||||||
sendKeyEvent(VK_RSHIFT, false);
|
sendKeyEvent(VK_RSHIFT, false);
|
||||||
m_keys[VK_SHIFT] = 0;
|
m_fakeKeys[VK_SHIFT] = 0;
|
||||||
m_keys[VK_RSHIFT] = 0;
|
m_fakeKeys[VK_RSHIFT] = 0;
|
||||||
}
|
}
|
||||||
if ((m_keys[VK_LCONTROL] & 0x80) != 0) {
|
if ((m_fakeKeys[VK_LCONTROL] & 0x80) != 0) {
|
||||||
sendKeyEvent(VK_LCONTROL, false);
|
sendKeyEvent(VK_LCONTROL, false);
|
||||||
m_keys[VK_CONTROL] = 0;
|
m_fakeKeys[VK_CONTROL] = 0;
|
||||||
m_keys[VK_LCONTROL] = 0;
|
m_fakeKeys[VK_LCONTROL] = 0;
|
||||||
}
|
}
|
||||||
if ((m_keys[VK_RCONTROL] & 0x80) != 0) {
|
if ((m_fakeKeys[VK_RCONTROL] & 0x80) != 0) {
|
||||||
sendKeyEvent(VK_RCONTROL, false);
|
sendKeyEvent(VK_RCONTROL, false);
|
||||||
m_keys[VK_CONTROL] = 0;
|
m_fakeKeys[VK_CONTROL] = 0;
|
||||||
m_keys[VK_RCONTROL] = 0;
|
m_fakeKeys[VK_RCONTROL] = 0;
|
||||||
}
|
}
|
||||||
if ((m_keys[VK_LMENU] & 0x80) != 0) {
|
if ((m_fakeKeys[VK_LMENU] & 0x80) != 0) {
|
||||||
sendKeyEvent(VK_LMENU, false);
|
sendKeyEvent(VK_LMENU, false);
|
||||||
m_keys[VK_MENU] = 0;
|
m_fakeKeys[VK_MENU] = 0;
|
||||||
m_keys[VK_LMENU] = 0;
|
m_fakeKeys[VK_LMENU] = 0;
|
||||||
}
|
}
|
||||||
if ((m_keys[VK_RMENU] & 0x80) != 0) {
|
if ((m_fakeKeys[VK_RMENU] & 0x80) != 0) {
|
||||||
sendKeyEvent(VK_RMENU, false);
|
sendKeyEvent(VK_RMENU, false);
|
||||||
m_keys[VK_MENU] = 0;
|
m_fakeKeys[VK_MENU] = 0;
|
||||||
m_keys[VK_RMENU] = 0;
|
m_fakeKeys[VK_RMENU] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now check all the other keys
|
// now check all the other keys
|
||||||
for (UInt32 i = 0; i < sizeof(m_keys) / sizeof(m_keys[0]); ++i) {
|
for (UInt32 i = 0; i < sizeof(m_fakeKeys) / sizeof(m_fakeKeys[0]); ++i) {
|
||||||
if ((m_keys[i] & 0x80) != 0) {
|
if ((m_fakeKeys[i] & 0x80) != 0) {
|
||||||
sendKeyEvent(i, false);
|
sendKeyEvent(i, false);
|
||||||
m_keys[i] = 0;
|
m_fakeKeys[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1068,8 +1089,9 @@ CMSWindowsSecondaryScreen::toggleKey(UINT virtualKey, KeyModifierMask mask)
|
||||||
sendKeyEvent(virtualKey, false);
|
sendKeyEvent(virtualKey, false);
|
||||||
|
|
||||||
// toggle shadow state
|
// toggle shadow state
|
||||||
m_mask ^= mask;
|
m_mask ^= mask;
|
||||||
m_keys[virtualKey & 0xff] ^= 0x01;
|
m_keys[virtualKey & 0xff] ^= 0x01;
|
||||||
|
m_fakeKeys[virtualKey & 0xff] ^= 0x01;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT
|
UINT
|
||||||
|
|
|
@ -115,9 +115,12 @@ private:
|
||||||
// our window
|
// our window
|
||||||
HWND m_window;
|
HWND m_window;
|
||||||
|
|
||||||
// virtual key states
|
// virtual key states as set by us or the user
|
||||||
BYTE m_keys[256];
|
BYTE m_keys[256];
|
||||||
|
|
||||||
|
// virtual key states as set by us
|
||||||
|
BYTE m_fakeKeys[256];
|
||||||
|
|
||||||
// current active modifiers
|
// current active modifiers
|
||||||
KeyModifierMask m_mask;
|
KeyModifierMask m_mask;
|
||||||
};
|
};
|
||||||
|
|
|
@ -111,7 +111,8 @@ CXWindowsSecondaryScreen::keyDown(KeyID key, KeyModifierMask mask)
|
||||||
doKeystrokes(keys, 1);
|
doKeystrokes(keys, 1);
|
||||||
|
|
||||||
// note that key is now down
|
// note that key is now down
|
||||||
m_keys[keycode] = true;
|
m_keys[keycode] = true;
|
||||||
|
m_fakeKeys[keycode] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -149,7 +150,8 @@ CXWindowsSecondaryScreen::keyUp(KeyID key, KeyModifierMask mask)
|
||||||
doKeystrokes(keys, 1);
|
doKeystrokes(keys, 1);
|
||||||
|
|
||||||
// note that key is now up
|
// note that key is now up
|
||||||
m_keys[keycode] = false;
|
m_keys[keycode] = false;
|
||||||
|
m_fakeKeys[keycode] = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -251,10 +253,12 @@ CXWindowsSecondaryScreen::onEvent(CEvent* event)
|
||||||
|
|
||||||
// handle event
|
// handle event
|
||||||
switch (xevent.type) {
|
switch (xevent.type) {
|
||||||
case MappingNotify:
|
case MappingNotify: {
|
||||||
// keyboard mapping changed
|
// keyboard mapping changed
|
||||||
updateKeys();
|
CDisplayLock display(m_screen);
|
||||||
|
doUpdateKeys(display);
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
case LeaveNotify:
|
case LeaveNotify:
|
||||||
// mouse moved out of hider window somehow. hide the window.
|
// mouse moved out of hider window somehow. hide the window.
|
||||||
|
@ -905,20 +909,19 @@ CXWindowsSecondaryScreen::doReleaseKeys(Display* display)
|
||||||
{
|
{
|
||||||
assert(display != NULL);
|
assert(display != NULL);
|
||||||
|
|
||||||
// key up for each key that's down
|
// key release for each key that we faked a press for
|
||||||
for (UInt32 i = 0; i < 256; ++i) {
|
for (UInt32 i = 0; i < 256; ++i) {
|
||||||
if (m_keys[i]) {
|
if (m_fakeKeys[i]) {
|
||||||
XTestFakeKeyEvent(display, i, False, CurrentTime);
|
XTestFakeKeyEvent(display, i, False, CurrentTime);
|
||||||
m_keys[i] = false;
|
m_fakeKeys[i] = false;
|
||||||
|
m_keys[i] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsSecondaryScreen::updateKeys()
|
CXWindowsSecondaryScreen::doUpdateKeys(Display* display)
|
||||||
{
|
{
|
||||||
CDisplayLock display(m_screen);
|
|
||||||
|
|
||||||
// query the button mapping
|
// query the button mapping
|
||||||
UInt32 numButtons = XGetPointerMapping(display, NULL, 0);
|
UInt32 numButtons = XGetPointerMapping(display, NULL, 0);
|
||||||
unsigned char* tmpButtons = new unsigned char[numButtons];
|
unsigned char* tmpButtons = new unsigned char[numButtons];
|
||||||
|
@ -947,6 +950,17 @@ CXWindowsSecondaryScreen::updateKeys()
|
||||||
// clean up
|
// clean up
|
||||||
delete[] tmpButtons;
|
delete[] tmpButtons;
|
||||||
|
|
||||||
|
// update mappings and current modifiers
|
||||||
|
updateModifierMap(display);
|
||||||
|
updateKeycodeMap(display);
|
||||||
|
updateModifiers(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CXWindowsSecondaryScreen::updateKeys()
|
||||||
|
{
|
||||||
|
CDisplayLock display(m_screen);
|
||||||
|
|
||||||
// ask server which keys are pressed
|
// ask server which keys are pressed
|
||||||
char keys[32];
|
char keys[32];
|
||||||
XQueryKeymap(display, keys);
|
XQueryKeymap(display, keys);
|
||||||
|
@ -963,10 +977,11 @@ CXWindowsSecondaryScreen::updateKeys()
|
||||||
m_keys[j + 7] = ((keys[i] & 0x80) != 0);
|
m_keys[j + 7] = ((keys[i] & 0x80) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update mappings and current modifiers
|
// we've fake pressed no keys
|
||||||
updateModifierMap(display);
|
m_fakeKeys.reset();
|
||||||
updateKeycodeMap(display);
|
|
||||||
updateModifiers(display);
|
// update mappings and current modifiers and mouse buttons
|
||||||
|
doUpdateKeys(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "CSecondaryScreen.h"
|
#include "CSecondaryScreen.h"
|
||||||
#include "IScreenEventHandler.h"
|
#include "IScreenEventHandler.h"
|
||||||
|
#include "stdbitset.h"
|
||||||
#include "stdmap.h"
|
#include "stdmap.h"
|
||||||
#include "stdvector.h"
|
#include "stdvector.h"
|
||||||
#if defined(X_DISPLAY_MISSING)
|
#if defined(X_DISPLAY_MISSING)
|
||||||
|
@ -78,9 +79,6 @@ private:
|
||||||
KeyCodeMask();
|
KeyCodeMask();
|
||||||
public:
|
public:
|
||||||
KeyCode m_keycode[4];
|
KeyCode m_keycode[4];
|
||||||
// FIXME -- don't need masks
|
|
||||||
unsigned int m_keyMask[4];
|
|
||||||
unsigned int m_keyMaskMask[4];
|
|
||||||
};
|
};
|
||||||
class Keystroke {
|
class Keystroke {
|
||||||
public:
|
public:
|
||||||
|
@ -101,6 +99,7 @@ private:
|
||||||
void doKeystrokes(const Keystrokes&, SInt32 count);
|
void doKeystrokes(const Keystrokes&, SInt32 count);
|
||||||
unsigned int maskToX(KeyModifierMask) const;
|
unsigned int maskToX(KeyModifierMask) const;
|
||||||
|
|
||||||
|
void doUpdateKeys(Display*);
|
||||||
void doReleaseKeys(Display*);
|
void doReleaseKeys(Display*);
|
||||||
void updateKeycodeMap(Display* display);
|
void updateKeycodeMap(Display* display);
|
||||||
void updateModifiers(Display* display);
|
void updateModifiers(Display* display);
|
||||||
|
@ -125,8 +124,13 @@ private:
|
||||||
bool m_numLockHalfDuplex;
|
bool m_numLockHalfDuplex;
|
||||||
bool m_capsLockHalfDuplex;
|
bool m_capsLockHalfDuplex;
|
||||||
|
|
||||||
// set entries indicate keys that are pressed. indexed by keycode.
|
// set entries indicate keys that are pressed (by us or by the user).
|
||||||
bool m_keys[256];
|
// indexed by keycode.
|
||||||
|
std::bitset<256> m_keys;
|
||||||
|
|
||||||
|
// set entries indicate keys that are synthetically pressed by us.
|
||||||
|
// this is normally the same as m_keys.
|
||||||
|
std::bitset<256> m_fakeKeys;
|
||||||
|
|
||||||
// logical to physical button mapping. m_buttons[i] gives the
|
// logical to physical button mapping. m_buttons[i] gives the
|
||||||
// physical button for logical button i+1.
|
// physical button for logical button i+1.
|
||||||
|
|
Loading…
Reference in New Issue