feat(macos): preserve the left/right side of modifier keys on the client
The macOS client mapped every right-hand modifier (Control_R, Shift_R, Alt_R, Super/Meta_R) to its left-hand virtual key and always emitted the left device-dependent event flags, so a remote right-side modifier arrived on the client as the left one. Apps that distinguish the two (input methods that need Right Shift, hotkeys bound to Right Control, etc.) never saw the right key. Map the right-hand KeyIDs to their macOS right virtual keys, teach isModifier() and setKeyboardModifiers() about them, track which side is held, and emit the matching NX_DEVICER*KEYMASK device flag. This change is client-only; the macOS server key map is unchanged. fixes: #8486 Signed-off-by: rNoz <rnoz.commits@gmail.com>
This commit is contained in:
parent
6740d30051
commit
dd3944cabc
2 changed files with 51 additions and 12 deletions
|
|
@ -26,6 +26,10 @@ static const uint32_t s_controlVK = kVK_Control;
|
||||||
static const uint32_t s_altVK = kVK_Option;
|
static const uint32_t s_altVK = kVK_Option;
|
||||||
static const uint32_t s_superVK = kVK_Command;
|
static const uint32_t s_superVK = kVK_Command;
|
||||||
static const uint32_t s_capsLockVK = kVK_CapsLock;
|
static const uint32_t s_capsLockVK = kVK_CapsLock;
|
||||||
|
static const uint32_t s_shiftRightVK = kVK_RightShift;
|
||||||
|
static const uint32_t s_controlRightVK = kVK_RightControl;
|
||||||
|
static const uint32_t s_altRightVK = kVK_RightOption;
|
||||||
|
static const uint32_t s_superRightVK = kVK_RightCommand;
|
||||||
static const uint32_t s_numLockVK = kVK_ANSI_KeypadClear; // 71
|
static const uint32_t s_numLockVK = kVK_ANSI_KeypadClear; // 71
|
||||||
|
|
||||||
static const uint32_t s_brightnessUp = 144;
|
static const uint32_t s_brightnessUp = 144;
|
||||||
|
|
@ -95,18 +99,18 @@ static const KeyEntry s_controlKeys[] = {
|
||||||
// to map to. also the enter key with numlock on is a modifier but i
|
// to map to. also the enter key with numlock on is a modifier but i
|
||||||
// don't know which.
|
// don't know which.
|
||||||
|
|
||||||
// modifier keys. OS X doesn't seem to support right handed versions
|
// modifier keys. map the left and right variants to their respective
|
||||||
// of modifier keys so we map them to the left handed versions.
|
// macOS virtual keys so the modifier side is preserved on the client.
|
||||||
{kKeyShift_L, s_shiftVK},
|
{kKeyShift_L, s_shiftVK},
|
||||||
{kKeyShift_R, s_shiftVK}, // 60
|
{kKeyShift_R, s_shiftRightVK},
|
||||||
{kKeyControl_L, s_controlVK},
|
{kKeyControl_L, s_controlVK},
|
||||||
{kKeyControl_R, s_controlVK}, // 62
|
{kKeyControl_R, s_controlRightVK},
|
||||||
{kKeyAlt_L, s_altVK},
|
{kKeyAlt_L, s_altVK},
|
||||||
{kKeyAlt_R, s_altVK},
|
{kKeyAlt_R, s_altRightVK},
|
||||||
{kKeySuper_L, s_superVK},
|
{kKeySuper_L, s_superVK},
|
||||||
{kKeySuper_R, s_superVK}, // 61
|
{kKeySuper_R, s_superRightVK},
|
||||||
{kKeyMeta_L, s_superVK},
|
{kKeyMeta_L, s_superVK},
|
||||||
{kKeyMeta_R, s_superVK}, // 61
|
{kKeyMeta_R, s_superRightVK},
|
||||||
|
|
||||||
// toggle modifiers
|
// toggle modifiers
|
||||||
{kKeyNumLock, s_numLockVK},
|
{kKeyNumLock, s_numLockVK},
|
||||||
|
|
@ -168,7 +172,8 @@ io_connect_t getEventDriver()
|
||||||
|
|
||||||
bool isModifier(uint8_t virtualKey)
|
bool isModifier(uint8_t virtualKey)
|
||||||
{
|
{
|
||||||
static std::set<uint8_t> modifiers{s_shiftVK, s_superVK, s_altVK, s_controlVK, s_capsLockVK};
|
static std::set<uint8_t> modifiers{s_shiftVK, s_controlVK, s_altVK, s_superVK, s_capsLockVK,
|
||||||
|
s_shiftRightVK, s_controlRightVK, s_altRightVK, s_superRightVK};
|
||||||
|
|
||||||
return (modifiers.find(virtualKey) != modifiers.end());
|
return (modifiers.find(virtualKey) != modifiers.end());
|
||||||
}
|
}
|
||||||
|
|
@ -228,6 +233,10 @@ void OSXKeyState::init()
|
||||||
m_altPressed = false;
|
m_altPressed = false;
|
||||||
m_superPressed = false;
|
m_superPressed = false;
|
||||||
m_capsPressed = false;
|
m_capsPressed = false;
|
||||||
|
m_shiftRightPressed = false;
|
||||||
|
m_controlRightPressed = false;
|
||||||
|
m_altRightPressed = false;
|
||||||
|
m_superRightPressed = false;
|
||||||
|
|
||||||
// build virtual key map
|
// build virtual key map
|
||||||
for (size_t i = 0; i < sizeof(s_controlKeys) / sizeof(s_controlKeys[0]); ++i) {
|
for (size_t i = 0; i < sizeof(s_controlKeys) / sizeof(s_controlKeys[0]); ++i) {
|
||||||
|
|
@ -549,19 +558,19 @@ CGEventFlags OSXKeyState::getDeviceDependedFlags() const
|
||||||
CGEventFlags modifiers = 0;
|
CGEventFlags modifiers = 0;
|
||||||
|
|
||||||
if (m_shiftPressed) {
|
if (m_shiftPressed) {
|
||||||
modifiers |= NX_DEVICELSHIFTKEYMASK;
|
modifiers |= m_shiftRightPressed ? NX_DEVICERSHIFTKEYMASK : NX_DEVICELSHIFTKEYMASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_controlPressed) {
|
if (m_controlPressed) {
|
||||||
modifiers |= NX_DEVICELCTLKEYMASK;
|
modifiers |= m_controlRightPressed ? NX_DEVICERCTLKEYMASK : NX_DEVICELCTLKEYMASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_altPressed) {
|
if (m_altPressed) {
|
||||||
modifiers |= NX_DEVICELALTKEYMASK;
|
modifiers |= m_altRightPressed ? NX_DEVICERALTKEYMASK : NX_DEVICELALTKEYMASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_superPressed) {
|
if (m_superPressed) {
|
||||||
modifiers |= NX_DEVICELCMDKEYMASK;
|
modifiers |= m_superRightPressed ? NX_DEVICERCMDKEYMASK : NX_DEVICELCMDKEYMASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
return modifiers;
|
return modifiers;
|
||||||
|
|
@ -585,15 +594,39 @@ void OSXKeyState::setKeyboardModifiers(CGKeyCode virtualKey, bool keyDown)
|
||||||
switch (virtualKey) {
|
switch (virtualKey) {
|
||||||
case s_shiftVK:
|
case s_shiftVK:
|
||||||
m_shiftPressed = keyDown;
|
m_shiftPressed = keyDown;
|
||||||
|
if (keyDown)
|
||||||
|
m_shiftRightPressed = false;
|
||||||
|
break;
|
||||||
|
case s_shiftRightVK:
|
||||||
|
m_shiftPressed = keyDown;
|
||||||
|
m_shiftRightPressed = keyDown;
|
||||||
break;
|
break;
|
||||||
case s_controlVK:
|
case s_controlVK:
|
||||||
m_controlPressed = keyDown;
|
m_controlPressed = keyDown;
|
||||||
|
if (keyDown)
|
||||||
|
m_controlRightPressed = false;
|
||||||
|
break;
|
||||||
|
case s_controlRightVK:
|
||||||
|
m_controlPressed = keyDown;
|
||||||
|
m_controlRightPressed = keyDown;
|
||||||
break;
|
break;
|
||||||
case s_altVK:
|
case s_altVK:
|
||||||
m_altPressed = keyDown;
|
m_altPressed = keyDown;
|
||||||
|
if (keyDown)
|
||||||
|
m_altRightPressed = false;
|
||||||
|
break;
|
||||||
|
case s_altRightVK:
|
||||||
|
m_altPressed = keyDown;
|
||||||
|
m_altRightPressed = keyDown;
|
||||||
break;
|
break;
|
||||||
case s_superVK:
|
case s_superVK:
|
||||||
m_superPressed = keyDown;
|
m_superPressed = keyDown;
|
||||||
|
if (keyDown)
|
||||||
|
m_superRightPressed = false;
|
||||||
|
break;
|
||||||
|
case s_superRightVK:
|
||||||
|
m_superPressed = keyDown;
|
||||||
|
m_superRightPressed = keyDown;
|
||||||
break;
|
break;
|
||||||
case s_capsLockVK:
|
case s_capsLockVK:
|
||||||
m_capsPressed = keyDown;
|
m_capsPressed = keyDown;
|
||||||
|
|
|
||||||
|
|
@ -162,4 +162,10 @@ private:
|
||||||
bool m_altPressed;
|
bool m_altPressed;
|
||||||
bool m_superPressed;
|
bool m_superPressed;
|
||||||
bool m_capsPressed;
|
bool m_capsPressed;
|
||||||
|
// track whether the right-hand variant of a modifier is held so the
|
||||||
|
// device-dependent event flags report the correct side.
|
||||||
|
bool m_shiftRightPressed;
|
||||||
|
bool m_controlRightPressed;
|
||||||
|
bool m_altRightPressed;
|
||||||
|
bool m_superRightPressed;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue