From b3ad9c49d6606c3851a2217b2f523172ccdc0b87 Mon Sep 17 00:00:00 2001 From: Scarriffle Date: Sun, 6 Sep 2026 21:05:25 +0200 Subject: [PATCH] =?UTF-8?q?Den=20Tastenabgriff=20n=C3=A4her=20an=20die=20H?= =?UTF-8?q?ardware=20setzen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An der Sitzung angesetzt fing er synthetische Ereignisse zuverlässig ab — die echten Lautstärketasten aber nicht: nachgemessen läuft der Abgriff, und ein selbst erzeugter Tastendruck wird erkannt und verbraucht, während der Druck auf die Taste weiterhin Apples Einblendung auslöste. Auf neueren macOS-Fassungen werden die Tasten offenbar weiter vorn behandelt, bevor die Sitzung sie sieht. `cghidEventTap` sitzt davor. Ob das reicht, zeigt erst die echte Taste — synthetisch ist beides nicht zu unterscheiden. Die Protokollzeilen bleiben vorerst drin: ohne sie ist „es geht immer noch nicht" nicht von „der Abgriff läuft gar nicht" zu trennen. Co-Authored-By: Claude Opus 5 --- Onyx/OnyxApp.swift | 9 ++++++++- Packages/OnyxKit/Sources/OnyxCore/MediaKeyTap.swift | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Onyx/OnyxApp.swift b/Onyx/OnyxApp.swift index cc4c384..36c9d50 100644 --- a/Onyx/OnyxApp.swift +++ b/Onyx/OnyxApp.swift @@ -448,10 +448,15 @@ final class AppDelegate: NSObject, NSApplicationDelegate { /// `docs/spikes/J-osd.md`. Was geht, ist ihr zuvorzukommen: das System /// blendet nichts ein, wenn der Tastendruck es nie erreicht. private func applyMediaKeys(_ on: Bool) { - guard on else { mediaKeys.stop(); return } + guard on else { + mediaKeys.stop() + log.notice("Tastenabgriff aus") + return + } guard MediaKeyTap.isTrusted else { // Ohne Bedienungshilfen tut der Abgriff nichts. Den Dialog anfragen // statt stumm zu scheitern. + log.notice("Tastenabgriff: Bedienungshilfen fehlen — Dialog angefragt") MediaKeyTap.requestTrust() return } @@ -459,12 +464,14 @@ final class AppDelegate: NSObject, NSApplicationDelegate { MainActor.assumeIsolated { self?.handleMediaKey(key) ?? false } } mediaKeys.start() + log.notice("Tastenabgriff \(self.mediaKeys.isRunning ? "läuft" : "NICHT gestartet", privacy: .public)") } /// Wie macOS selbst: ein Sechzehntel je Anschlag. private static let volumeStep = 1.0 / 16.0 private func handleMediaKey(_ key: MediaKeyTap.Key) -> Bool { + log.notice("Taste abgefangen: \(String(describing: key), privacy: .public)") let current = systemAudio.outputVolume switch key { case .volumeUp: diff --git a/Packages/OnyxKit/Sources/OnyxCore/MediaKeyTap.swift b/Packages/OnyxKit/Sources/OnyxCore/MediaKeyTap.swift index dcbce21..18230f5 100644 --- a/Packages/OnyxKit/Sources/OnyxCore/MediaKeyTap.swift +++ b/Packages/OnyxKit/Sources/OnyxCore/MediaKeyTap.swift @@ -69,7 +69,12 @@ public final class MediaKeyTap { // `NSSystemDefined` ist der Ereignistyp der Sondertasten. let mask = CGEventMask(1 << 14) - guard let tap = CGEvent.tapCreate(tap: .cgSessionEventTap, + // **`cghidEventTap` und nicht `cgSessionEventTap`.** An der Sitzung + // angesetzt fing der Abgriff zwar synthetische Ereignisse ab, die + // echten Tasten aber nicht: auf neueren macOS-Fassungen werden sie + // weiter vorn behandelt, bevor die Sitzung sie zu sehen bekommt. Der + // HID-Abgriff sitzt davor. + guard let tap = CGEvent.tapCreate(tap: .cghidEventTap, place: .headInsertEventTap, options: .defaultTap, eventsOfInterest: mask,