From 6284286d4f67c1c3415cf255730b14567b109b2e Mon Sep 17 00:00:00 2001 From: crs Date: Thu, 29 Jul 2004 22:11:27 +0000 Subject: [PATCH] Fixed handling of modifier keys on OS X. Also made OS X client ignore small mouse wheel events (which seem to get sent by some win32 systems). Other platforms were already ignoring them. --- lib/platform/COSXKeyState.cpp | 90 +++++++++++++++++++++++++++++++++-- lib/platform/COSXKeyState.h | 12 +++++ lib/platform/COSXScreen.cpp | 63 ++++++++++++++++++++++-- lib/platform/COSXScreen.h | 3 ++ 4 files changed, 162 insertions(+), 6 deletions(-) diff --git a/lib/platform/COSXKeyState.cpp b/lib/platform/COSXKeyState.cpp index ed9d295f..e1cd57a1 100644 --- a/lib/platform/COSXKeyState.cpp +++ b/lib/platform/COSXKeyState.cpp @@ -458,7 +458,7 @@ const KeyID COSXKeyState::s_virtualKey[] = COSXKeyState::COSXKeyState() { - // do nothing + setHalfDuplexMask(0); } COSXKeyState::~COSXKeyState() @@ -494,6 +494,12 @@ COSXKeyState::sendKeyEvent(void* target, } } +void +COSXKeyState::setHalfDuplexMask(KeyModifierMask mask) +{ + CKeyState::setHalfDuplexMask(mask | KeyModifierCapsLock); +} + bool COSXKeyState::fakeCtrlAltDel() { @@ -518,10 +524,33 @@ COSXKeyState::doUpdateKeys() // FIXME -- this probably needs to be more dynamic to support // non-english keyboards. also need to map modifiers needed // for each KeyID. + // FIXME -- add one so we don't use KeyButton 0 (reserved to be no key) for (UInt32 i = 0; i < sizeof(s_keys) / sizeof(s_keys[0]); ++i) { m_keyMap.insert(std::make_pair(s_keys[i].m_keyID, s_keys[i].m_button + 1)); } + + // add modifiers + KeyButtons keys; + addKeyButton(keys, kKeyShift_L); + addKeyButton(keys, kKeyShift_R); + addModifier(KeyModifierShift, keys); + keys.clear(); + addKeyButton(keys, kKeyControl_L); + addKeyButton(keys, kKeyControl_R); + addModifier(KeyModifierControl, keys); + keys.clear(); + addKeyButton(keys, kKeyAlt_L); + addKeyButton(keys, kKeyAlt_R); + addModifier(KeyModifierAlt, keys); + keys.clear(); + addKeyButton(keys, kKeySuper_L); + addKeyButton(keys, kKeySuper_R); + addModifier(KeyModifierSuper, keys); + keys.clear(); + addKeyButton(keys, kKeyCapsLock); + addModifier(KeyModifierCapsLock, keys); + keys.clear(); } void @@ -529,6 +558,7 @@ COSXKeyState::doFakeKeyEvent(KeyButton button, bool press, bool isAutoRepeat) { LOG((CLOG_DEBUG2 "doFakeKeyEvent button:%d, press:%d", button, press)); // let system figure out character for us + // FIXME -- subtracting one because we added one in doUpdateKeys. CGPostKeyboardEvent(0, static_cast(button) - 1, press); } @@ -618,7 +648,7 @@ COSXKeyState::mapKeyFromEvent(EventRef event, KeyModifierMask* maskOut) const if (id != kKeyNone && c != 0) { // FIXME } - + // map modifier key if (maskOut != NULL) { activeMask &= ~KeyModifierModeSwitch; @@ -626,5 +656,59 @@ COSXKeyState::mapKeyFromEvent(EventRef event, KeyModifierMask* maskOut) const } return id; - } + +void +COSXKeyState::addKeyButton(KeyButtons& keys, KeyID id) const +{ + CKeyMap::const_iterator keyIndex = m_keyMap.find(id); + if (keyIndex == m_keyMap.end()) { + return; + } + // XXX -- subtract one because added one in doUpdateKeys + keys.push_back(keyIndex->second - 1); +} + +void +COSXKeyState::handleModifierKeys(void* target, + KeyModifierMask oldMask, KeyModifierMask newMask) +{ + // compute changed modifiers + KeyModifierMask changed = (oldMask ^ newMask); + + // synthesize changed modifier keys + if ((changed & KeyModifierShift) != 0) { + handleModifierKey(target, kKeyShift_L, + (newMask & KeyModifierShift) != 0); + } + if ((changed & KeyModifierControl) != 0) { + handleModifierKey(target, kKeyControl_L, + (newMask & KeyModifierControl) != 0); + } + if ((changed & KeyModifierAlt) != 0) { + handleModifierKey(target, kKeyAlt_L, + (newMask & KeyModifierAlt) != 0); + } + if ((changed & KeyModifierSuper) != 0) { + handleModifierKey(target, kKeySuper_L, + (newMask & KeyModifierSuper) != 0); + } + if ((changed & KeyModifierCapsLock) != 0) { + handleModifierKey(target, kKeyCapsLock, + (newMask & KeyModifierCapsLock) != 0); + } +} + +void +COSXKeyState::handleModifierKey(void* target, KeyID id, bool down) +{ + CKeyMap::const_iterator keyIndex = m_keyMap.find(id); + if (keyIndex == m_keyMap.end()) { + return; + } + // FIXME -- subtract one because we added one in doUpdateKeys + KeyButton button = keyIndex->second - 1; + setKeyDown(button, down); + sendKeyEvent(target, down, false, id, getActiveModifiers(), 0, button); +} + diff --git a/lib/platform/COSXKeyState.h b/lib/platform/COSXKeyState.h index 94e98f07..f83ec07d 100644 --- a/lib/platform/COSXKeyState.h +++ b/lib/platform/COSXKeyState.h @@ -36,13 +36,23 @@ public: KeyID mapKeyFromEvent(EventRef event, KeyModifierMask* maskOut) const; + //! Handle modifier key change + /*! + Determines which modifier keys have changed and updates the modifier + state and sends key events as appropriate. + */ + void handleModifierKeys(void* target, + KeyModifierMask oldMask, KeyModifierMask newMask); + // IKeyState overrides + virtual void setHalfDuplexMask(KeyModifierMask); virtual bool fakeCtrlAltDel(); virtual const char* getKeyName(KeyButton) const; virtual void sendKeyEvent(void* target, bool press, bool isAutoRepeat, KeyID key, KeyModifierMask mask, SInt32 count, KeyButton button); + protected: // IKeyState overrides virtual void doUpdateKeys(); @@ -56,6 +66,8 @@ private: bool adjustModifiers(Keystrokes& keys, Keystrokes& undo, KeyModifierMask desiredMask) const; + void addKeyButton(KeyButtons& keys, KeyID id) const; + void handleModifierKey(void* target, KeyID id, bool down); private: typedef std::map CKeyMap; diff --git a/lib/platform/COSXScreen.cpp b/lib/platform/COSXScreen.cpp index 2cd002a1..d9dd62f8 100644 --- a/lib/platform/COSXScreen.cpp +++ b/lib/platform/COSXScreen.cpp @@ -303,6 +303,12 @@ COSXScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const void COSXScreen::fakeMouseWheel(SInt32 delta) const { + // synergy uses a wheel step size of 120. the mac uses a step size of 1. + delta /= 120; + if (delta == 0) { + return; + } + CFPropertyListRef pref = ::CFPreferencesCopyValue( CFSTR("com.apple.scrollwheel.scaling") , kCFPreferencesAnyApplication, @@ -327,6 +333,8 @@ COSXScreen::fakeMouseWheel(SInt32 delta) const CFRelease(pref); } + // note that we ignore the magnitude of the delta. i think this is to + // avoid local wheel acceleration. if (delta < 0) { wheelIncr = -wheelIncr; } @@ -799,15 +807,26 @@ COSXScreen::onKey(EventRef event) const { UInt32 eventKind = GetEventKind(event); + // get the key KeyButton button; GetEventParameter(event, kEventParamKeyCode, typeUInt32, NULL, sizeof(button), NULL, &button); - + LOG((CLOG_DEBUG1 "event: Key event kind: %d, keycode=%d", eventKind, button)); + + // sadly, OS X doesn't report the button for modifier keys. button will + // be zero for modifier keys. since that's not good enough we'll have + // to figure out what the key was. + if (button == 0 && eventKind == kEventRawKeyModifiersChanged) { + // get old and new modifier state + KeyModifierMask oldMask = getActiveModifiers(); + KeyModifierMask newMask = mapMacModifiersToSynergy(event); + m_keyState->handleModifierKeys(getEventTarget(), oldMask, newMask); + return true; + } + bool down = (eventKind == kEventRawKeyDown); bool up = (eventKind == kEventRawKeyUp); bool isRepeat = (eventKind == kEventRawKeyRepeat); - - LOG((CLOG_DEBUG1 "event: Key event kind: %d, keycode=%d", eventKind, button)); if (down) { m_keyState->setKeyDown(button, true); @@ -842,6 +861,44 @@ COSXScreen::mapMacButtonToSynergy(UInt16 macButton) const return kButtonNone; } +KeyModifierMask +COSXScreen::mapMacModifiersToSynergy(EventRef event) const +{ + // get native bit mask + UInt32 macMask; + GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, + NULL, sizeof(macMask), NULL, &macMask); + + // convert + KeyModifierMask outMask = 0; + if ((macMask & shiftKey) != 0) { + outMask |= KeyModifierShift; + } + if ((macMask & rightShiftKey) != 0) { + outMask |= KeyModifierShift; + } + if ((macMask & controlKey) != 0) { + outMask |= KeyModifierControl; + } + if ((macMask & rightControlKey) != 0) { + outMask |= KeyModifierControl; + } + if ((macMask & cmdKey) != 0) { + outMask |= KeyModifierAlt; + } + if ((macMask & optionKey) != 0) { + outMask |= KeyModifierSuper; + } + if ((macMask & rightOptionKey) != 0) { + outMask |= KeyModifierSuper; + } + if ((macMask & alphaLock) != 0) { + outMask |= KeyModifierCapsLock; + } + + return outMask; +} + void COSXScreen::updateButtons() { diff --git a/lib/platform/COSXScreen.h b/lib/platform/COSXScreen.h index dc61af3e..292c1a40 100644 --- a/lib/platform/COSXScreen.h +++ b/lib/platform/COSXScreen.h @@ -91,6 +91,9 @@ private: // map mac mouse button to synergy buttons ButtonID mapMacButtonToSynergy(UInt16) const; + + // map mac modifier mask to synergy modifier mask + KeyModifierMask mapMacModifiersToSynergy(EventRef event) const; /// Resolution switch callback static pascal void displayManagerCallback(void* inUserData,