Zwei Anzeigen für einen Handgriff sind eine zu viel
Apples eigene Einblendung lässt sich aushängen, ohne Root und ohne SIP anzufassen: `com.apple.OSDUIHelper` liegt in der GUI-Domäne des angemeldeten Benutzers, nicht im System. `launchctl bootout` dort hinein genügt. Standardmäßig aus, denn es verschwindet **jede** Einblendung — auch Helligkeit und Feststelltaste, und für die Feststelltaste hat Onyx keinen Ersatz. Beim Beenden wird wieder eingehängt: eine Einstellung darf nicht überleben, was sie eingestellt hat. Dazu zwei Fehler im Anlernen behoben. Der Posenname stand als roher Schlüssel da — die Zeichenketten liegen im Bündel von `FaceProvider`, gesucht wurden sie im Hauptbündel. Und „Gesicht vergleichen" blieb nach dem Anlernen grau, weil `isEnrolled` bei jedem Aufruf den Schlüsselbund las: richtig, aber für SwiftUI unsichtbar, weil es nichts gab, woran eine Ansicht die Änderung hätte bemerken können. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
fd29df51cf
commit
a3399d3a96
@@ -24,6 +24,7 @@ final class AppModel {
|
||||
var onNotchStyleChanged: ((NotchStyle) -> Void)?
|
||||
var onNotchWidthsChanged: (([CGDirectDisplayID: CGFloat]) -> Void)?
|
||||
var onFaceUnlockChanged: ((Bool) -> Void)?
|
||||
var onSuppressOSDChanged: ((Bool) -> Void)?
|
||||
|
||||
var layout: [WidgetPlacement] {
|
||||
didSet {
|
||||
@@ -64,6 +65,19 @@ final class AppModel {
|
||||
onNotchWidthsChanged?(notchWidths)
|
||||
}
|
||||
|
||||
/// Ob Apples eigene Einblendung unterdrückt wird.
|
||||
///
|
||||
/// Standardmäßig aus: es verschwindet **jede** Einblendung, auch die für
|
||||
/// Helligkeit und Feststelltaste. Das ist eine Entscheidung, die man
|
||||
/// treffen soll, nicht eine, die man vorfindet.
|
||||
var suppressSystemOSD: Bool {
|
||||
didSet {
|
||||
guard suppressSystemOSD != oldValue else { return }
|
||||
defaults.set(suppressSystemOSD, forKey: Keys.suppressSystemOSD)
|
||||
onSuppressOSDChanged?(suppressSystemOSD)
|
||||
}
|
||||
}
|
||||
|
||||
/// Ob Onyx einen eigenen Sperrbildschirm anbietet.
|
||||
var lockScreenEnabled: Bool {
|
||||
didSet {
|
||||
@@ -186,6 +200,7 @@ final class AppModel {
|
||||
static let showsIdleIsland = "onyx.showsIdleIsland"
|
||||
static let notchStyle = "onyx.notchStyle"
|
||||
static let notchWidths = "onyx.notchWidths"
|
||||
static let suppressSystemOSD = "onyx.suppressSystemOSD"
|
||||
static let lockScreenEnabled = "onyx.lock.enabled"
|
||||
static let faceUnlockEnabled = "onyx.lock.face"
|
||||
static let bandLeading = "onyx.band.leading"
|
||||
@@ -208,6 +223,8 @@ final class AppModel {
|
||||
self.showsIdleIsland = defaults.object(forKey: Keys.showsIdleIsland) as? Bool ?? true
|
||||
self.notchStyle = defaults.string(forKey: Keys.notchStyle)
|
||||
.flatMap(NotchStyle.init(rawValue:)) ?? .automatic
|
||||
self.suppressSystemOSD = defaults.object(forKey: Keys.suppressSystemOSD) as? Bool ?? false
|
||||
|
||||
// Beides standardmäßig **aus**: ein Sperrbildschirm, den man nicht
|
||||
// bestellt hat, ist ein Schreck, und ein Gesichtsvergleich ohne
|
||||
// angelerntes Gesicht kann ohnehin nichts.
|
||||
|
||||
@@ -3685,6 +3685,38 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings.osd.suppress": {
|
||||
"localizations": {
|
||||
"de": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Apples Einblendung unterdrücken"
|
||||
}
|
||||
},
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Suppress Apple's own overlay"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings.osd.suppress.hint": {
|
||||
"localizations": {
|
||||
"de": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Sonst zeigt der Mac bei jedem Lautstärkeschritt zwei Anzeigen. Betrifft alle Einblendungen — auch Helligkeit und Feststelltaste. Beim Beenden von Onyx wird sie wieder eingeschaltet."
|
||||
}
|
||||
},
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Otherwise the Mac shows two indicators for every volume step. Affects every overlay — brightness and caps lock too. It is restored when Onyx quits."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"settings.permissions.calendar": {
|
||||
"extractionState": "stale",
|
||||
"localizations": {
|
||||
|
||||
@@ -55,6 +55,7 @@ struct LockSettingsView: View {
|
||||
Button(String(localized: "lock.face.forget"), role: .destructive) {
|
||||
enrollment.reset()
|
||||
model.faceUnlockEnabled = false
|
||||
controller.refreshEnrollment()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +72,12 @@ struct LockSettingsView: View {
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $isEnrolling) {
|
||||
EnrollmentSheet(enrollment: enrollment) { isEnrolling = false }
|
||||
EnrollmentSheet(enrollment: enrollment) {
|
||||
isEnrolling = false
|
||||
// Sonst bliebe „Gesicht vergleichen" grau, obwohl gerade eines
|
||||
// angelernt wurde.
|
||||
controller.refreshEnrollment()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +115,7 @@ private struct EnrollmentSheet: View {
|
||||
.clipShape(RoundedRectangle(cornerRadius: Onyx.Radius.card,
|
||||
style: .continuous))
|
||||
|
||||
Text(enrollment.pose.localizedName, bundle: .main)
|
||||
Text(enrollment.pose.localizedName)
|
||||
.font(Onyx.Font.headline)
|
||||
|
||||
Text(enrollment.seesFace ? "lock.enroll.ready" : "lock.enroll.noFace")
|
||||
|
||||
@@ -189,6 +189,11 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
}
|
||||
// Ohne diese Zeile wäre der Schalter in den Einstellungen eine
|
||||
// Behauptung: gespeichert, aber ohne Wirkung.
|
||||
if model.suppressSystemOSD { SystemOSD.suppress() }
|
||||
model.onSuppressOSDChanged = { suppress in
|
||||
suppress ? SystemOSD.suppress() : SystemOSD.restore()
|
||||
}
|
||||
|
||||
lockController.usesFaceUnlock = model.faceUnlockEnabled
|
||||
model.onFaceUnlockChanged = { [weak self] uses in
|
||||
self?.lockController.usesFaceUnlock = uses
|
||||
@@ -309,6 +314,11 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ notification: Notification) {
|
||||
// Apples Einblendung wieder einhängen. Ohne das säße jemand bis zum
|
||||
// nächsten Abmelden ganz ohne Rückmeldung da — auch bei der Helligkeit,
|
||||
// mit der Onyx nichts zu tun hat — und wüsste nicht, warum. Eine
|
||||
// Einstellung darf nicht überleben, was sie eingestellt hat.
|
||||
if model?.suppressSystemOSD == true { SystemOSD.restore() }
|
||||
coordinator?.stop()
|
||||
menuBar?.stop()
|
||||
// Der Herzschlag endet damit. Der Helfer stellt die Lüfter binnen fünf
|
||||
@@ -650,6 +660,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
|
||||
}
|
||||
|
||||
@objc private func quit() { NSApp.terminate(nil) }
|
||||
|
||||
}
|
||||
|
||||
/// Der Inhalt des Panels. Liest `model.layout` und zeichnet sich damit neu,
|
||||
|
||||
@@ -183,6 +183,11 @@ private struct NotchSettings: View {
|
||||
.frame(width: 200)
|
||||
}
|
||||
|
||||
OnyxFormRow(String(localized: "settings.osd.suppress"),
|
||||
hint: String(localized: "settings.osd.suppress.hint")) {
|
||||
Toggle("", isOn: $model.suppressSystemOSD).labelsHidden()
|
||||
}
|
||||
|
||||
OnyxFormRow(String(localized: "settings.notch.style"),
|
||||
hint: String(localized: "settings.notch.style.hint")) {
|
||||
Picker("", selection: $model.notchStyle) {
|
||||
|
||||
Reference in New Issue
Block a user