From f65d53d06a84cfbe04ad418d7066e123189a76c4 Mon Sep 17 00:00:00 2001 From: crs Date: Sun, 24 Oct 2004 18:18:01 +0000 Subject: [PATCH] Fixed dead key and AltGr+shift handling on X windows. Also fixed bug with decomposing characters that have no direct key mapping but do have a direct key mapping for the character with the opposite case. --- lib/platform/CXWindowsKeyState.cpp | 114 ++++++++++++++++------------- lib/synergy/CKeyState.cpp | 4 +- lib/synergy/CKeyState.h | 19 +++-- 3 files changed, 78 insertions(+), 59 deletions(-) diff --git a/lib/platform/CXWindowsKeyState.cpp b/lib/platform/CXWindowsKeyState.cpp index b4efddcb..c0ec6f75 100644 --- a/lib/platform/CXWindowsKeyState.cpp +++ b/lib/platform/CXWindowsKeyState.cpp @@ -95,7 +95,7 @@ #if defined(HAVE_X11_XF86KEYSYM_H) static const KeySym g_mapE000[] = { - /* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, + /* 0x00 */ 0, XF86XK_Eject, 0, 0, 0, 0, 0, 0, /* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0, @@ -278,6 +278,45 @@ CXWindowsKeyState::mapKey(Keystrokes& keys, KeyID id, // get the mapping for this keysym KeySymIndex keyIndex = m_keysymMap.find(keysym); + if (keyIndex != m_keysymMap.end()) { + // the keysym is mapped to some keycode. create the keystrokes + // for this keysym. + return mapToKeystrokes(keys, keyIndex, isAutoRepeat); + } + + // we can't find the keysym mapped to any keycode. this doesn't + // necessarily mean we can't generate the keysym, though. if the + // keysym can be created by combining keysyms then we may still + // be okay. + CXWindowsUtil::KeySyms decomposition; + if (CXWindowsUtil::decomposeKeySym(keysym, decomposition)) { + LOG((CLOG_DEBUG2 "decomposed keysym 0x%08x into %d keysyms", keysym, decomposition.size())); + + // map each decomposed keysym to keystrokes. we want the mask + // and the keycode from the last keysym (which should be the + // only non-dead key). the dead keys are not sensitive to + // anything but shift and mode switch. + KeyButton keycode = 0; + for (CXWindowsUtil::KeySyms::const_iterator i = decomposition.begin(); + i != decomposition.end(); ++i) { + // lookup the key + keysym = *i; + keyIndex = m_keysymMap.find(keysym); + if (keyIndex == m_keysymMap.end()) { + // missing a required keysym + LOG((CLOG_DEBUG2 "can't map keysym %d: 0x%04x", i - decomposition.begin(), keysym)); + return 0; + } + + // the keysym is mapped to some keycode + keycode = mapToKeystrokes(keys, keyIndex, isAutoRepeat); + if (keycode == 0) { + return 0; + } + } + + return keycode; + } // if the mapping isn't found and keysym is caps lock sensitive // then convert the case of the keysym and try again. @@ -292,47 +331,14 @@ CXWindowsKeyState::mapKey(Keystrokes& keys, KeyID id, keyIndex = m_keysymMap.find(lKey); } } - } - - if (keyIndex != m_keysymMap.end()) { - // the keysym is mapped to some keycode. create the keystrokes - // for this keysym. - return mapToKeystrokes(keys, keyIndex, isAutoRepeat); - } - - // we can't find the keysym mapped to any keycode. this doesn't - // necessarily mean we can't generate the keysym, though. if the - // keysym can be created by combining keysyms then we may still - // be okay. - CXWindowsUtil::KeySyms decomposition; - if (!CXWindowsUtil::decomposeKeySym(keysym, decomposition)) { - return 0; - } - LOG((CLOG_DEBUG2 "decomposed keysym 0x%08x into %d keysyms", keysym, decomposition.size())); - - // map each decomposed keysym to keystrokes. we want the mask - // and the keycode from the last keysym (which should be the - // only non-dead key). the dead keys are not sensitive to - // anything but shift and mode switch. - KeyButton keycode = 0; - for (CXWindowsUtil::KeySyms::const_iterator i = decomposition.begin(); - i != decomposition.end(); ++i) { - // lookup the key - keysym = *i; - keyIndex = m_keysymMap.find(keysym); - if (keyIndex == m_keysymMap.end()) { - // missing a required keysym - return 0; - } - - // the keysym is mapped to some keycode - keycode = mapToKeystrokes(keys, keyIndex, isAutoRepeat); - if (keycode == 0) { - return 0; + if (keyIndex != m_keysymMap.end()) { + // the keysym is mapped to some keycode. create the keystrokes + // for this keysym. + return mapToKeystrokes(keys, keyIndex, isAutoRepeat); } } - return keycode; + return 0; } void @@ -794,6 +800,7 @@ CXWindowsKeyState::mapToKeystrokes(Keystrokes& keys, if (isAutoRepeat && (m_keyControl.auto_repeats[keycode >> 3] & static_cast(1 << (keycode & 7))) == 0) { + LOG((CLOG_DEBUG2 "non-autorepeating")); return 0; } @@ -923,24 +930,34 @@ CXWindowsKeyState::adjustModifiers(Keystrokes& keys, // get mode switch set correctly. do this before shift because // mode switch may be sensitive to the shift modifier and will // set/reset it as necessary. - const bool wantModeSwitch = ((desiredMask & KeyModifierModeSwitch) != 0); - const bool haveModeSwitch = ((currentMask & KeyModifierModeSwitch) != 0); + bool forceShift = false; + bool wantShift = ((desiredMask & KeyModifierShift) != 0); + bool wantModeSwitch = ((desiredMask & KeyModifierModeSwitch) != 0); + bool haveModeSwitch = ((currentMask & KeyModifierModeSwitch) != 0); if (wantModeSwitch != haveModeSwitch) { LOG((CLOG_DEBUG2 "fix mode switch")); - // adjust shift if necessary + // adjust shift if necessary (i.e. turn it off it's on and mode + // shift is sensitive to the shift key) KeySymIndex modeSwitchIndex = m_keysymMap.find(m_modeSwitchKeysym); assert(modeSwitchIndex != m_keysymMap.end()); if (modeSwitchIndex->second.m_shiftSensitive[0]) { - const bool wantShift = false; - const bool haveShift = ((currentMask & KeyModifierShift) != 0); - if (wantShift != haveShift) { + bool haveShift = ((currentMask & KeyModifierShift) != 0); + if (haveShift) { // add shift keystrokes LOG((CLOG_DEBUG2 "fix shift for mode switch")); - if (!mapModifier(keys, undo, KeyModifierShift, wantShift)) { + if (!mapModifier(keys, undo, KeyModifierShift, false, true)) { return false; } + + // our local concept of shift has flipped currentMask ^= KeyModifierShift; + + // force shift to get turned on below if we had to turn + // off here and shift is desired. if we didn't force it + // then mapModifier would think shift is already down + // and ignore the request. + forceShift = wantShift; } } @@ -952,12 +969,11 @@ CXWindowsKeyState::adjustModifiers(Keystrokes& keys, } // get shift set correctly - const bool wantShift = ((desiredMask & KeyModifierShift) != 0); - const bool haveShift = ((currentMask & KeyModifierShift) != 0); + bool haveShift = ((currentMask & KeyModifierShift) != 0); if (wantShift != haveShift) { // add shift keystrokes LOG((CLOG_DEBUG2 "fix shift")); - if (!mapModifier(keys, undo, KeyModifierShift, wantShift)) { + if (!mapModifier(keys, undo, KeyModifierShift, wantShift, forceShift)) { return false; } currentMask ^= KeyModifierShift; diff --git a/lib/synergy/CKeyState.cpp b/lib/synergy/CKeyState.cpp index 41a859d9..481354fe 100644 --- a/lib/synergy/CKeyState.cpp +++ b/lib/synergy/CKeyState.cpp @@ -295,7 +295,7 @@ CKeyState::addModifier(KeyModifierMask modifier, const KeyButtons& buttons) bool CKeyState::mapModifier(Keystrokes& keys, Keystrokes& undo, - KeyModifierMask mask, bool desireActive) const + KeyModifierMask mask, bool desireActive, bool force) const { // look up modifier const KeyButtons& buttons = m_maskToKeys[getIndexForModifier(mask)]; @@ -304,7 +304,7 @@ CKeyState::mapModifier(Keystrokes& keys, Keystrokes& undo, } // ignore if already in desired state - if (isModifierActive(mask) == desireActive) { + if (!force && isModifierActive(mask) == desireActive) { return true; } diff --git a/lib/synergy/CKeyState.h b/lib/synergy/CKeyState.h index a003b78a..2e8c44b4 100644 --- a/lib/synergy/CKeyState.h +++ b/lib/synergy/CKeyState.h @@ -102,16 +102,19 @@ protected: //! Get key events to change modifier state /*! - Retrieves the key events necessary to activate (\c desireActive is true) - or deactivate (\c desireActive is false) the modifier given by \c mask - by pushing them onto the back of \c keys. \c mask must specify exactly - one modifier. \c undo receives the key events necessary to restore the - modifier's previous state. They're pushed onto \c undo in the reverse - order they should be executed. Returns true if the modifier can be - adjusted, false otherwise. + Retrieves the key events necessary to activate (\p desireActive is true) + or deactivate (\p desireActive is false) the modifier given by \p mask + by pushing them onto the back of \p keys. \p mask must specify exactly + one modifier. \p undo receives the key events necessary to restore the + modifier's previous state. They're pushed onto \p undo in the reverse + order they should be executed. If \p force is false then \p keys and + \p undo are only changed if the modifier is not currently in the + desired state. If \p force is true then \p keys and \p undo are always + changed. Returns true if the modifier can be adjusted, false otherwise. */ bool mapModifier(Keystrokes& keys, Keystrokes& undo, - KeyModifierMask mask, bool desireActive) const; + KeyModifierMask mask, bool desireActive, + bool force = false) const; //! Update the key state /*!