Files
onyx/Packages/OnyxKit/Sources/OnyxNotch/NotchBand.swift
T
ScarriffleandClaude Opus 5 c05ccb8ae1 Die Notch wird zur Insel, wo es keine Hardware gibt
Die Silhouette bestand aus zwei überlappenden Teilpfaden. Gefüllt stimmte die
Vereinigung, aber die Kontur zeichnete jeden Teilpfad vollständig nach — auch
dort, wo er innen lag. Dazu kippte die Form ab einer Breite in einen anderen
Zweig, und die beiden Zweige waren nicht dieselbe Geometrie. Zusammen war das
das Flackern an den Rundungen. Jetzt ein durchgehender Umriss, dessen Zweige
ineinander übergehen statt zu springen.

Neu ist die Wahl zwischen verschmolzen und schwebend. Eine echte Notch **muss**
an der Kante kleben und oben eckig sein, sonst klafft ein Spalt zum Gehäuse;
eine Insel **muss** Abstand halten und rundum gerundet sein, sonst sieht sie aus
wie ein abgeschnittenes Rechteck. Beides zu mischen geht nicht, deshalb eine
Wahl und keine zwei Schalter.

Ihre Höhe rät Onyx nicht mehr, sondern misst die Menüleiste: 24 Punkte minus
Luft oben und unten. Vorher hing ein festes Maß unten heraus.

Dazu „nur der Hauptbildschirm" als dritte Anzeigewahl — gemeint ist der mit der
Menüleiste, nicht `NSScreen.main`, das mit dem aktiven Fenster mitwandert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-05 21:05:13 +02:00

60 lines
2.3 KiB
Swift

import CoreGraphics
/// Wie viel Platz links und rechts der Notch bleibt — auf Menüleistenhöhe.
///
/// Der oberste Streifen des Panels ist so hoch wie die Notch und so breit wie
/// das Panel. In der Mitte sitzt die Hardware; links und rechts davon lag
/// bisher durchsichtiges, ungenutztes Fenster. Bei fünf Kacheln sind das je
/// 376 Punkte.
public struct NotchBand: Equatable, Sendable {
/// Breite links der Notch.
public let leading: CGFloat
/// Breite rechts der Notch.
public let trailing: CGFloat
public init(leading: CGFloat, trailing: CGFloat) {
self.leading = leading
self.trailing = trailing
}
public static let none = NotchBand(leading: 0, trailing: 0)
public var isEmpty: Bool { leading <= 0 && trailing <= 0 }
/// Die Gesamtbreite des gezeichneten Streifens, Notch eingeschlossen.
public func totalWidth(notchWidth: CGFloat) -> CGFloat {
leading + notchWidth + trailing
}
}
/// Rechnet aus, wie breit die Arme neben der Notch sein dürfen.
///
/// Reine Rechnung ohne AppKit, damit sie ohne Bildschirm prüfbar ist — wie
/// `NotchGeometry` und `TriggerArea`.
public enum NotchBandLayout {
/// Ab wann ein Arm überhaupt etwas tragen kann.
///
/// Ein Symbol, ein zweistelliger Wert und Luft an beiden Seiten. Schmaler
/// wird der Arm zu einem Streifen, in dem nichts steht — und ein leerer
/// Streifen neben der Notch sieht nicht nach Zurückhaltung aus, sondern
/// nach einem Zeichenfehler.
public static let minimumUsableWidth: CGFloat = 56
/// - Parameters:
/// - panelWidth: Die Breite des ausgefahrenen Panels.
/// - notchWidth: Die Breite der Notch bzw. ihres virtuellen Ersatzes.
///
/// **Symmetrisch oder gar nicht.** Reicht es nur auf einer Seite, bleiben
/// beide leer: ein Arm links ohne Gegenstück rechts liest sich als
/// verrutschtes Panel, nicht als Absicht.
public static func resolve(panelWidth: CGFloat,
notchWidth: CGFloat,
minimumUsableWidth: CGFloat = minimumUsableWidth) -> NotchBand {
let side = (panelWidth - notchWidth) / 2
guard side >= minimumUsableWidth else { return .none }
return NotchBand(leading: side, trailing: side)
}
}