From 74e50877e96e663a7f4f7d984142d51fa462cc04 Mon Sep 17 00:00:00 2001 From: crs Date: Sun, 16 Mar 2003 17:40:56 +0000 Subject: [PATCH] Made releaseKeys() only synthesize key releases for those keys that synergy synthesized a press for, not keys that the user is physically pressing. --- lib/common/Makefile.am | 1 + lib/common/common.dsp | 4 + lib/common/stdbitset.h | 17 ++++ lib/platform/CMSWindowsSecondaryScreen.cpp | 90 ++++++++++++++-------- lib/platform/CMSWindowsSecondaryScreen.h | 5 +- lib/platform/CXWindowsSecondaryScreen.cpp | 43 +++++++---- lib/platform/CXWindowsSecondaryScreen.h | 14 ++-- 7 files changed, 120 insertions(+), 54 deletions(-) create mode 100644 lib/common/stdbitset.h diff --git a/lib/common/Makefile.am b/lib/common/Makefile.am index 4de7af6c..889af930 100644 --- a/lib/common/Makefile.am +++ b/lib/common/Makefile.am @@ -21,6 +21,7 @@ EXTRA_DIST = \ IInterface.h \ Version.h \ common.h \ + stdbitset.h \ stdfstream.h \ stdistream.h \ stdlist.h \ diff --git a/lib/common/common.dsp b/lib/common/common.dsp index dd600c0a..df6b77b4 100644 --- a/lib/common/common.dsp +++ b/lib/common/common.dsp @@ -103,6 +103,10 @@ SOURCE=.\IInterface.h # End Source File # Begin Source File +SOURCE=.\stdbitset.h +# End Source File +# Begin Source File + SOURCE=.\stdfstream.h # End Source File # Begin Source File diff --git a/lib/common/stdbitset.h b/lib/common/stdbitset.h new file mode 100644 index 00000000..529772ca --- /dev/null +++ b/lib/common/stdbitset.h @@ -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 +#include "stdpost.h" diff --git a/lib/platform/CMSWindowsSecondaryScreen.cpp b/lib/platform/CMSWindowsSecondaryScreen.cpp index a1e14d04..f0cb0062 100644 --- a/lib/platform/CMSWindowsSecondaryScreen.cpp +++ b/lib/platform/CMSWindowsSecondaryScreen.cpp @@ -68,21 +68,25 @@ CMSWindowsSecondaryScreen::keyDown(KeyID key, KeyModifierMask mask) doKeystrokes(keys, 1); // note that key is now down - m_keys[virtualKey] |= 0x80; + m_keys[virtualKey] |= 0x80; + m_fakeKeys[virtualKey] |= 0x80; switch (virtualKey) { case VK_LSHIFT: case VK_RSHIFT: - m_keys[VK_SHIFT] |= 0x80; + m_keys[VK_SHIFT] |= 0x80; + m_fakeKeys[VK_SHIFT] |= 0x80; break; case VK_LCONTROL: case VK_RCONTROL: - m_keys[VK_CONTROL] |= 0x80; + m_keys[VK_CONTROL] |= 0x80; + m_fakeKeys[VK_CONTROL] |= 0x80; break; case VK_LMENU: case VK_RMENU: - m_keys[VK_MENU] |= 0x80; + m_keys[VK_MENU] |= 0x80; + m_fakeKeys[VK_MENU] |= 0x80; break; } } @@ -128,41 +132,48 @@ CMSWindowsSecondaryScreen::keyUp(KeyID key, KeyModifierMask mask) doKeystrokes(keys, 1); // note that key is now up - m_keys[virtualKey] &= ~0x80; + m_keys[virtualKey] &= ~0x80; + m_fakeKeys[virtualKey] &= ~0x80; switch (virtualKey) { case VK_LSHIFT: if ((m_keys[VK_RSHIFT] & 0x80) == 0) { - m_keys[VK_SHIFT] &= ~0x80; + m_keys[VK_SHIFT] &= ~0x80; + m_fakeKeys[VK_SHIFT] &= ~0x80; } break; case VK_RSHIFT: if ((m_keys[VK_LSHIFT] & 0x80) == 0) { - m_keys[VK_SHIFT] &= ~0x80; + m_keys[VK_SHIFT] &= ~0x80; + m_fakeKeys[VK_SHIFT] &= ~0x80; } break; case VK_LCONTROL: if ((m_keys[VK_RCONTROL] & 0x80) == 0) { - m_keys[VK_CONTROL] &= ~0x80; + m_keys[VK_CONTROL] &= ~0x80; + m_fakeKeys[VK_CONTROL] &= ~0x80; } break; case VK_RCONTROL: if ((m_keys[VK_LCONTROL] & 0x80) == 0) { - m_keys[VK_CONTROL] &= ~0x80; + m_keys[VK_CONTROL] &= ~0x80; + m_fakeKeys[VK_CONTROL] &= ~0x80; } break; case VK_LMENU: if ((m_keys[VK_RMENU] & 0x80) == 0) { - m_keys[VK_MENU] &= ~0x80; + m_keys[VK_MENU] &= ~0x80; + m_fakeKeys[VK_MENU] &= ~0x80; } break; case VK_RMENU: if ((m_keys[VK_LMENU] & 0x80) == 0) { - m_keys[VK_MENU] &= ~0x80; + m_keys[VK_MENU] &= ~0x80; + m_fakeKeys[VK_MENU] &= ~0x80; } break; } @@ -439,6 +450,7 @@ CMSWindowsSecondaryScreen::updateKeys() { // clear key state memset(m_keys, 0, sizeof(m_keys)); + memset(m_fakeKeys, 0, sizeof(m_keys)); // we only care about the modifier key states m_keys[VK_LSHIFT] = static_cast(GetKeyState(VK_LSHIFT)); @@ -457,6 +469,11 @@ CMSWindowsSecondaryScreen::updateKeys() m_keys[VK_NUMLOCK] = static_cast(GetKeyState(VK_NUMLOCK)); m_keys[VK_SCROLL] = static_cast(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 m_mask = 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 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); m_screen->syncDesktop(); @@ -1020,42 +1041,42 @@ CMSWindowsSecondaryScreen::releaseKeys() // 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 // 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); - m_keys[VK_SHIFT] = 0; - m_keys[VK_LSHIFT] = 0; + m_fakeKeys[VK_SHIFT] = 0; + m_fakeKeys[VK_LSHIFT] = 0; } - if ((m_keys[VK_RSHIFT] & 0x80) != 0) { + if ((m_fakeKeys[VK_RSHIFT] & 0x80) != 0) { sendKeyEvent(VK_RSHIFT, false); - m_keys[VK_SHIFT] = 0; - m_keys[VK_RSHIFT] = 0; + m_fakeKeys[VK_SHIFT] = 0; + m_fakeKeys[VK_RSHIFT] = 0; } - if ((m_keys[VK_LCONTROL] & 0x80) != 0) { + if ((m_fakeKeys[VK_LCONTROL] & 0x80) != 0) { sendKeyEvent(VK_LCONTROL, false); - m_keys[VK_CONTROL] = 0; - m_keys[VK_LCONTROL] = 0; + m_fakeKeys[VK_CONTROL] = 0; + m_fakeKeys[VK_LCONTROL] = 0; } - if ((m_keys[VK_RCONTROL] & 0x80) != 0) { + if ((m_fakeKeys[VK_RCONTROL] & 0x80) != 0) { sendKeyEvent(VK_RCONTROL, false); - m_keys[VK_CONTROL] = 0; - m_keys[VK_RCONTROL] = 0; + m_fakeKeys[VK_CONTROL] = 0; + m_fakeKeys[VK_RCONTROL] = 0; } - if ((m_keys[VK_LMENU] & 0x80) != 0) { + if ((m_fakeKeys[VK_LMENU] & 0x80) != 0) { sendKeyEvent(VK_LMENU, false); - m_keys[VK_MENU] = 0; - m_keys[VK_LMENU] = 0; + m_fakeKeys[VK_MENU] = 0; + m_fakeKeys[VK_LMENU] = 0; } - if ((m_keys[VK_RMENU] & 0x80) != 0) { + if ((m_fakeKeys[VK_RMENU] & 0x80) != 0) { sendKeyEvent(VK_RMENU, false); - m_keys[VK_MENU] = 0; - m_keys[VK_RMENU] = 0; + m_fakeKeys[VK_MENU] = 0; + m_fakeKeys[VK_RMENU] = 0; } // now check all the other keys - for (UInt32 i = 0; i < sizeof(m_keys) / sizeof(m_keys[0]); ++i) { - if ((m_keys[i] & 0x80) != 0) { + for (UInt32 i = 0; i < sizeof(m_fakeKeys) / sizeof(m_fakeKeys[0]); ++i) { + if ((m_fakeKeys[i] & 0x80) != 0) { sendKeyEvent(i, false); - m_keys[i] = 0; + m_fakeKeys[i] = 0; } } } @@ -1068,8 +1089,9 @@ CMSWindowsSecondaryScreen::toggleKey(UINT virtualKey, KeyModifierMask mask) sendKeyEvent(virtualKey, false); // toggle shadow state - m_mask ^= mask; - m_keys[virtualKey & 0xff] ^= 0x01; + m_mask ^= mask; + m_keys[virtualKey & 0xff] ^= 0x01; + m_fakeKeys[virtualKey & 0xff] ^= 0x01; } UINT diff --git a/lib/platform/CMSWindowsSecondaryScreen.h b/lib/platform/CMSWindowsSecondaryScreen.h index acaa10b0..afa26a8c 100644 --- a/lib/platform/CMSWindowsSecondaryScreen.h +++ b/lib/platform/CMSWindowsSecondaryScreen.h @@ -115,9 +115,12 @@ private: // our window HWND m_window; - // virtual key states + // virtual key states as set by us or the user BYTE m_keys[256]; + // virtual key states as set by us + BYTE m_fakeKeys[256]; + // current active modifiers KeyModifierMask m_mask; }; diff --git a/lib/platform/CXWindowsSecondaryScreen.cpp b/lib/platform/CXWindowsSecondaryScreen.cpp index c398d6ac..19f1a6f8 100644 --- a/lib/platform/CXWindowsSecondaryScreen.cpp +++ b/lib/platform/CXWindowsSecondaryScreen.cpp @@ -111,7 +111,8 @@ CXWindowsSecondaryScreen::keyDown(KeyID key, KeyModifierMask mask) doKeystrokes(keys, 1); // note that key is now down - m_keys[keycode] = true; + m_keys[keycode] = true; + m_fakeKeys[keycode] = true; } void @@ -149,7 +150,8 @@ CXWindowsSecondaryScreen::keyUp(KeyID key, KeyModifierMask mask) doKeystrokes(keys, 1); // note that key is now up - m_keys[keycode] = false; + m_keys[keycode] = false; + m_fakeKeys[keycode] = false; } void @@ -251,10 +253,12 @@ CXWindowsSecondaryScreen::onEvent(CEvent* event) // handle event switch (xevent.type) { - case MappingNotify: + case MappingNotify: { // keyboard mapping changed - updateKeys(); + CDisplayLock display(m_screen); + doUpdateKeys(display); return true; + } case LeaveNotify: // mouse moved out of hider window somehow. hide the window. @@ -905,20 +909,19 @@ CXWindowsSecondaryScreen::doReleaseKeys(Display* display) { 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) { - if (m_keys[i]) { + if (m_fakeKeys[i]) { XTestFakeKeyEvent(display, i, False, CurrentTime); - m_keys[i] = false; + m_fakeKeys[i] = false; + m_keys[i] = false; } } } void -CXWindowsSecondaryScreen::updateKeys() +CXWindowsSecondaryScreen::doUpdateKeys(Display* display) { - CDisplayLock display(m_screen); - // query the button mapping UInt32 numButtons = XGetPointerMapping(display, NULL, 0); unsigned char* tmpButtons = new unsigned char[numButtons]; @@ -947,6 +950,17 @@ CXWindowsSecondaryScreen::updateKeys() // clean up 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 char keys[32]; XQueryKeymap(display, keys); @@ -963,10 +977,11 @@ CXWindowsSecondaryScreen::updateKeys() m_keys[j + 7] = ((keys[i] & 0x80) != 0); } - // update mappings and current modifiers - updateModifierMap(display); - updateKeycodeMap(display); - updateModifiers(display); + // we've fake pressed no keys + m_fakeKeys.reset(); + + // update mappings and current modifiers and mouse buttons + doUpdateKeys(display); } void diff --git a/lib/platform/CXWindowsSecondaryScreen.h b/lib/platform/CXWindowsSecondaryScreen.h index 96482f9f..18530130 100644 --- a/lib/platform/CXWindowsSecondaryScreen.h +++ b/lib/platform/CXWindowsSecondaryScreen.h @@ -17,6 +17,7 @@ #include "CSecondaryScreen.h" #include "IScreenEventHandler.h" +#include "stdbitset.h" #include "stdmap.h" #include "stdvector.h" #if defined(X_DISPLAY_MISSING) @@ -78,9 +79,6 @@ private: KeyCodeMask(); public: KeyCode m_keycode[4]; - // FIXME -- don't need masks - unsigned int m_keyMask[4]; - unsigned int m_keyMaskMask[4]; }; class Keystroke { public: @@ -101,6 +99,7 @@ private: void doKeystrokes(const Keystrokes&, SInt32 count); unsigned int maskToX(KeyModifierMask) const; + void doUpdateKeys(Display*); void doReleaseKeys(Display*); void updateKeycodeMap(Display* display); void updateModifiers(Display* display); @@ -125,8 +124,13 @@ private: bool m_numLockHalfDuplex; bool m_capsLockHalfDuplex; - // set entries indicate keys that are pressed. indexed by keycode. - bool m_keys[256]; + // set entries indicate keys that are pressed (by us or by the user). + // 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 // physical button for logical button i+1.