fix: handle rapid Caps gestures

This commit is contained in:
root 2026-10-25 20:10:09 +03:00
parent 1059a8c79d
commit 240bd4fcf6
2 changed files with 25 additions and 6 deletions

View file

@ -267,15 +267,22 @@ final class MacOSInputController {
let flags = event.flags
let newAlphaShiftDown = flags.contains(.maskAlphaShift)
let newOptionDown = flags.contains(.maskAlternate)
let isCapsEvent = event.getIntegerValueField(.keyboardEventKeycode)
== Int64(Self.capsLockKeyCode)
if isPaused {
alphaShiftDown = newAlphaShiftDown
if isCapsEvent {
alphaShiftDown = newAlphaShiftDown
}
optionDown = newOptionDown
return Unmanaged.passUnretained(event)
}
let capsDown = newAlphaShiftDown && !alphaShiftDown
let capsUp = !newAlphaShiftDown && alphaShiftDown
// Alpha-shift is also used by other keyboard events. Use the physical
// key code so a fast sequence of unrelated flagsChanged events cannot
// be mistaken for a Caps Lock edge.
let capsDown = isCapsEvent && newAlphaShiftDown && !alphaShiftDown
let capsUp = isCapsEvent && !newAlphaShiftDown && alphaShiftDown
let optionPressed = newOptionDown && !optionDown
let optionReleased = !newOptionDown && optionDown
@ -303,7 +310,9 @@ final class MacOSInputController {
action = combine(action, gestureMachine.handle(.optionUp))
}
alphaShiftDown = newAlphaShiftDown
if isCapsEvent {
alphaShiftDown = newAlphaShiftDown
}
optionDown = newOptionDown
apply(action)
@ -319,8 +328,16 @@ final class MacOSInputController {
case .none:
break
case .switchToNextInputSource:
if inputSources.selectNextInputSource() {
onStateChanged?()
// TISSelectInputSource can synchronously trigger more keyboard
// notifications. Let the event tap return first so a rapid key +
// Caps sequence sees the new source before the next key is typed.
DispatchQueue.main.async { [weak self] in
guard let self, self.isRunning, !self.isPaused else {
return
}
if self.inputSources.selectNextInputSource() {
self.onStateChanged?()
}
}
case .toggleCapsLock:
postSyntheticCapsLock()

View file

@ -55,6 +55,8 @@ tasks:
- test -f Sources/CapswitchApp/MacOSInputController.swift
- grep -q "LSUIElement" Resources/Info.plist
- grep -q ".flagsChanged" Sources/CapswitchApp/MacOSInputController.swift
- grep -q "keyboardEventKeycode" Sources/CapswitchApp/MacOSInputController.swift
- grep -q "DispatchQueue.main.async" Sources/CapswitchApp/MacOSInputController.swift
- grep -q "CGEvent.tapCreate" Sources/CapswitchApp/MacOSInputController.swift
- grep -q "CGEvent.tapEnable" Sources/CapswitchApp/MacOSInputController.swift
- test "$(grep -c "CGEventTapCreate" Sources/CapswitchApp/MacOSInputController.swift || true)" -eq 0