fix: handle rapid Caps gestures

This commit is contained in:
casona 2026-10-25 20:10:09 +03:00
parent 3a620f89dc
commit 65d0954bbd
2 changed files with 25 additions and 6 deletions

View file

@ -267,15 +267,22 @@ final class MacOSInputController {
let flags = event.flags let flags = event.flags
let newAlphaShiftDown = flags.contains(.maskAlphaShift) let newAlphaShiftDown = flags.contains(.maskAlphaShift)
let newOptionDown = flags.contains(.maskAlternate) let newOptionDown = flags.contains(.maskAlternate)
let isCapsEvent = event.getIntegerValueField(.keyboardEventKeycode)
== Int64(Self.capsLockKeyCode)
if isPaused { if isPaused {
alphaShiftDown = newAlphaShiftDown if isCapsEvent {
alphaShiftDown = newAlphaShiftDown
}
optionDown = newOptionDown optionDown = newOptionDown
return Unmanaged.passUnretained(event) return Unmanaged.passUnretained(event)
} }
let capsDown = newAlphaShiftDown && !alphaShiftDown // Alpha-shift is also used by other keyboard events. Use the physical
let capsUp = !newAlphaShiftDown && alphaShiftDown // 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 optionPressed = newOptionDown && !optionDown
let optionReleased = !newOptionDown && optionDown let optionReleased = !newOptionDown && optionDown
@ -303,7 +310,9 @@ final class MacOSInputController {
action = combine(action, gestureMachine.handle(.optionUp)) action = combine(action, gestureMachine.handle(.optionUp))
} }
alphaShiftDown = newAlphaShiftDown if isCapsEvent {
alphaShiftDown = newAlphaShiftDown
}
optionDown = newOptionDown optionDown = newOptionDown
apply(action) apply(action)
@ -319,8 +328,16 @@ final class MacOSInputController {
case .none: case .none:
break break
case .switchToNextInputSource: case .switchToNextInputSource:
if inputSources.selectNextInputSource() { // TISSelectInputSource can synchronously trigger more keyboard
onStateChanged?() // 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: case .toggleCapsLock:
postSyntheticCapsLock() postSyntheticCapsLock()

View file

@ -55,6 +55,8 @@ tasks:
- test -f Sources/CapswitchApp/MacOSInputController.swift - test -f Sources/CapswitchApp/MacOSInputController.swift
- grep -q "LSUIElement" Resources/Info.plist - grep -q "LSUIElement" Resources/Info.plist
- grep -q ".flagsChanged" Sources/CapswitchApp/MacOSInputController.swift - 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.tapCreate" Sources/CapswitchApp/MacOSInputController.swift
- grep -q "CGEvent.tapEnable" Sources/CapswitchApp/MacOSInputController.swift - grep -q "CGEvent.tapEnable" Sources/CapswitchApp/MacOSInputController.swift
- test "$(grep -c "CGEventTapCreate" Sources/CapswitchApp/MacOSInputController.swift || true)" -eq 0 - test "$(grep -c "CGEventTapCreate" Sources/CapswitchApp/MacOSInputController.swift || true)" -eq 0