32 lines
1.3 KiB
Swift
32 lines
1.3 KiB
Swift
import AppKit
|
|
|
|
/// Which screens to keep, remove, or add when reconciling live bars against the
|
|
/// current `NSScreen.screens`.
|
|
///
|
|
/// Pure and identity-based (it never reads `NSScreen` properties), so it can be
|
|
/// unit-tested with any `[NSScreen]` without driving real window lifecycle.
|
|
enum PHScreenSync {
|
|
struct Diff: Equatable {
|
|
/// Screens that already have a bar and are still attached. Their window
|
|
/// frame is recomputed since geometry may have changed.
|
|
let kept: [NSScreen]
|
|
/// Screens whose bar must be torn down (monitor disconnected).
|
|
let removed: [NSScreen]
|
|
/// Screens with no bar yet that need one (monitor connected).
|
|
let added: [NSScreen]
|
|
}
|
|
|
|
/// Compare the screens now attached (`current`) against the screens currently
|
|
/// occupied by bars (`occupied`). A disconnected monitor reappears as a new
|
|
/// `NSScreen` instance, so it is reported as remove + add, never a keep.
|
|
static func diff(current: [NSScreen], occupied: [NSScreen]) -> Diff {
|
|
let currentIDs = Set(current.map(ObjectIdentifier.init))
|
|
let occupiedIDs = Set(occupied.map(ObjectIdentifier.init))
|
|
return Diff(
|
|
kept: occupied.filter { currentIDs.contains(ObjectIdentifier($0)) },
|
|
removed: occupied.filter { !currentIDs.contains(ObjectIdentifier($0)) },
|
|
added: current.filter { !occupiedIDs.contains(ObjectIdentifier($0)) }
|
|
)
|
|
}
|
|
}
|