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.
This commit is contained in:
crs 2004-07-29 22:11:27 +00:00
parent cf3647f7cc
commit 6284286d4f
4 changed files with 162 additions and 6 deletions

View File

@ -458,7 +458,7 @@ const KeyID COSXKeyState::s_virtualKey[] =
COSXKeyState::COSXKeyState() COSXKeyState::COSXKeyState()
{ {
// do nothing setHalfDuplexMask(0);
} }
COSXKeyState::~COSXKeyState() COSXKeyState::~COSXKeyState()
@ -494,6 +494,12 @@ COSXKeyState::sendKeyEvent(void* target,
} }
} }
void
COSXKeyState::setHalfDuplexMask(KeyModifierMask mask)
{
CKeyState::setHalfDuplexMask(mask | KeyModifierCapsLock);
}
bool bool
COSXKeyState::fakeCtrlAltDel() COSXKeyState::fakeCtrlAltDel()
{ {
@ -518,10 +524,33 @@ COSXKeyState::doUpdateKeys()
// FIXME -- this probably needs to be more dynamic to support // FIXME -- this probably needs to be more dynamic to support
// non-english keyboards. also need to map modifiers needed // non-english keyboards. also need to map modifiers needed
// for each KeyID. // 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) { for (UInt32 i = 0; i < sizeof(s_keys) / sizeof(s_keys[0]); ++i) {
m_keyMap.insert(std::make_pair(s_keys[i].m_keyID, m_keyMap.insert(std::make_pair(s_keys[i].m_keyID,
s_keys[i].m_button + 1)); 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 void
@ -529,6 +558,7 @@ COSXKeyState::doFakeKeyEvent(KeyButton button, bool press, bool isAutoRepeat)
{ {
LOG((CLOG_DEBUG2 "doFakeKeyEvent button:%d, press:%d", button, press)); LOG((CLOG_DEBUG2 "doFakeKeyEvent button:%d, press:%d", button, press));
// let system figure out character for us // let system figure out character for us
// FIXME -- subtracting one because we added one in doUpdateKeys.
CGPostKeyboardEvent(0, static_cast<CGKeyCode>(button) - 1, press); CGPostKeyboardEvent(0, static_cast<CGKeyCode>(button) - 1, press);
} }
@ -626,5 +656,59 @@ COSXKeyState::mapKeyFromEvent(EventRef event, KeyModifierMask* maskOut) const
} }
return id; 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);
}

View File

@ -36,13 +36,23 @@ public:
KeyID mapKeyFromEvent(EventRef event, KeyID mapKeyFromEvent(EventRef event,
KeyModifierMask* maskOut) const; 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 // IKeyState overrides
virtual void setHalfDuplexMask(KeyModifierMask);
virtual bool fakeCtrlAltDel(); virtual bool fakeCtrlAltDel();
virtual const char* getKeyName(KeyButton) const; virtual const char* getKeyName(KeyButton) const;
virtual void sendKeyEvent(void* target, virtual void sendKeyEvent(void* target,
bool press, bool isAutoRepeat, bool press, bool isAutoRepeat,
KeyID key, KeyModifierMask mask, KeyID key, KeyModifierMask mask,
SInt32 count, KeyButton button); SInt32 count, KeyButton button);
protected: protected:
// IKeyState overrides // IKeyState overrides
virtual void doUpdateKeys(); virtual void doUpdateKeys();
@ -56,6 +66,8 @@ private:
bool adjustModifiers(Keystrokes& keys, bool adjustModifiers(Keystrokes& keys,
Keystrokes& undo, Keystrokes& undo,
KeyModifierMask desiredMask) const; KeyModifierMask desiredMask) const;
void addKeyButton(KeyButtons& keys, KeyID id) const;
void handleModifierKey(void* target, KeyID id, bool down);
private: private:
typedef std::map<KeyID, KeyButton> CKeyMap; typedef std::map<KeyID, KeyButton> CKeyMap;

View File

@ -303,6 +303,12 @@ COSXScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const
void void
COSXScreen::fakeMouseWheel(SInt32 delta) const 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( CFPropertyListRef pref = ::CFPreferencesCopyValue(
CFSTR("com.apple.scrollwheel.scaling") , CFSTR("com.apple.scrollwheel.scaling") ,
kCFPreferencesAnyApplication, kCFPreferencesAnyApplication,
@ -327,6 +333,8 @@ COSXScreen::fakeMouseWheel(SInt32 delta) const
CFRelease(pref); CFRelease(pref);
} }
// note that we ignore the magnitude of the delta. i think this is to
// avoid local wheel acceleration.
if (delta < 0) { if (delta < 0) {
wheelIncr = -wheelIncr; wheelIncr = -wheelIncr;
} }
@ -799,16 +807,27 @@ COSXScreen::onKey(EventRef event) const
{ {
UInt32 eventKind = GetEventKind(event); UInt32 eventKind = GetEventKind(event);
// get the key
KeyButton button; KeyButton button;
GetEventParameter(event, kEventParamKeyCode, typeUInt32, GetEventParameter(event, kEventParamKeyCode, typeUInt32,
NULL, sizeof(button), NULL, &button); 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 down = (eventKind == kEventRawKeyDown);
bool up = (eventKind == kEventRawKeyUp); bool up = (eventKind == kEventRawKeyUp);
bool isRepeat = (eventKind == kEventRawKeyRepeat); bool isRepeat = (eventKind == kEventRawKeyRepeat);
LOG((CLOG_DEBUG1 "event: Key event kind: %d, keycode=%d", eventKind, button));
if (down) { if (down) {
m_keyState->setKeyDown(button, true); m_keyState->setKeyDown(button, true);
} }
@ -842,6 +861,44 @@ COSXScreen::mapMacButtonToSynergy(UInt16 macButton) const
return kButtonNone; 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 void
COSXScreen::updateButtons() COSXScreen::updateButtons()
{ {

View File

@ -92,6 +92,9 @@ private:
// map mac mouse button to synergy buttons // map mac mouse button to synergy buttons
ButtonID mapMacButtonToSynergy(UInt16) const; ButtonID mapMacButtonToSynergy(UInt16) const;
// map mac modifier mask to synergy modifier mask
KeyModifierMask mapMacModifiersToSynergy(EventRef event) const;
/// Resolution switch callback /// Resolution switch callback
static pascal void displayManagerCallback(void* inUserData, static pascal void displayManagerCallback(void* inUserData,
SInt16 inMessage, void* inNotifyData); SInt16 inMessage, void* inNotifyData);