fix(apple): resolve macOS modifiers by keyCode — Control was silently dropped
apple / swift (push) Successful in 1m40s
apple / screenshots (push) Has been cancelled
android / android (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
release / apple (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
apple / swift (push) Successful in 1m40s
apple / screenshots (push) Has been cancelled
android / android (push) Has been cancelled
arch / build-publish (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / web (push) Has been cancelled
ci / docs-site (push) Has been cancelled
ci / bench (push) Has been cancelled
deb / build-publish (push) Has been cancelled
decky / build-publish (push) Has been cancelled
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Has been cancelled
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Has been cancelled
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Has been cancelled
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Has been cancelled
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Has been cancelled
docker / deploy-docs (push) Has been cancelled
release / apple (push) Has been cancelled
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
Modifier keys arrive only as flagsChanged, and the direction was recovered by diffing the device-dependent L/R bits (NX_DEVICE*KEYMASK) alone. Those bits are undocumented and some keyboards omit them (only the class bit, e.g. NX_CONTROLMASK, is set), so the diff saw no transition and the key never reached the host — no Ctrl shortcuts. SDL/Moonlight key off the event's keyCode for exactly this reason; do the same: keyCode names the changed key, the class bit says up, the device bits (when present) pick the side, and a tracked-held-state flip covers keyboards without them. PUNKTFUNK_INPUT_DEBUG=1 now also logs every flagsChanged (keyCode + raw flags) so a field report is diagnosable from client logs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -98,5 +98,23 @@ extension InputCapture {
|
||||
m[0x47] = 0x90 // KP clear sits where NumLock is → VK_NUMLOCK. (KP equals 0x51 dropped.)
|
||||
return m
|
||||
}()
|
||||
|
||||
/// NSEvent.keyCode of each modifier key (kVK_Shift & co. — modifiers arrive only as
|
||||
/// flagsChanged) → its Windows VK plus the `NSEvent.modifierFlags` bits that describe
|
||||
/// it: `classMask` is the device-INDEPENDENT NX_*MASK for the modifier class,
|
||||
/// `deviceBit`/`siblingBit` the device-dependent bits (LOW 16 bits, NX_DEVICE*KEYMASK
|
||||
/// in IOLLEvent.h) for this key and its opposite-side twin. Consumed by
|
||||
/// `resolveModifier`, which explains why both kinds of bit are needed.
|
||||
static let modifierBits:
|
||||
[UInt16: (vk: UInt32, classMask: UInt, deviceBit: UInt, siblingBit: UInt)] = [
|
||||
56: (0xA0, 0x2_0000, 0x2, 0x4), // left shift → VK_LSHIFT
|
||||
60: (0xA1, 0x2_0000, 0x4, 0x2), // right shift → VK_RSHIFT
|
||||
59: (0xA2, 0x4_0000, 0x1, 0x2000), // left control → VK_LCONTROL
|
||||
62: (0xA3, 0x4_0000, 0x2000, 0x1), // right control → VK_RCONTROL
|
||||
58: (0xA4, 0x8_0000, 0x20, 0x40), // left option → VK_LMENU
|
||||
61: (0xA5, 0x8_0000, 0x40, 0x20), // right option → VK_RMENU
|
||||
55: (0x5B, 0x10_0000, 0x8, 0x10), // left command → VK_LWIN
|
||||
54: (0x5C, 0x10_0000, 0x10, 0x8), // right command → VK_RWIN
|
||||
]
|
||||
#endif
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user