Initial FocusFixer implementation

Menu-bar utility that fixes cross-display keyboard focus loss: a
listen-only CGEvent tap locates the window under the cursor and
reasserts app activation + AX focus on it, with debounce, tap
auto-recovery, and an Accessibility permission gate.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
sttlab-tech
2026-08-10 12:02:29 +02:00
commit 561a547b70
18 changed files with 1411 additions and 0 deletions
+40
View File
@@ -0,0 +1,40 @@
import XCTest
@testable import FocusFixer
final class DebounceTests: XCTestCase {
func testFirstEventIsAlwaysProcessed() {
var clockValue: TimeInterval = 0
var debouncer = Debouncer(interval: 0.15, clock: { clockValue })
XCTAssertTrue(debouncer.shouldProcess())
}
func testEventWithinIntervalIsSuppressed() {
var clockValue: TimeInterval = 0
var debouncer = Debouncer(interval: 0.15, clock: { clockValue })
XCTAssertTrue(debouncer.shouldProcess())
clockValue += 0.05
XCTAssertFalse(debouncer.shouldProcess())
}
func testEventAfterIntervalIsProcessed() {
var clockValue: TimeInterval = 0
var debouncer = Debouncer(interval: 0.15, clock: { clockValue })
XCTAssertTrue(debouncer.shouldProcess())
clockValue += 0.2
XCTAssertTrue(debouncer.shouldProcess())
}
func testAcceptedEventResetsTheWindow() {
var clockValue: TimeInterval = 0
var debouncer = Debouncer(interval: 0.15, clock: { clockValue })
XCTAssertTrue(debouncer.shouldProcess())
clockValue += 0.2
XCTAssertTrue(debouncer.shouldProcess())
clockValue += 0.05
XCTAssertFalse(debouncer.shouldProcess())
}
}