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:
crs 2003-03-16 17:40:56 +00:00
parent de64342292
commit 74e50877e9
7 changed files with 120 additions and 54 deletions

View File

@ -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 \

View File

@ -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

17
lib/common/stdbitset.h Normal file
View 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"

View File

@ -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

View File

@ -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;
}; };

View File

@ -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

View File

@ -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.