You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
43 lines
1.8 KiB
43 lines
1.8 KiB
/// Finds the connected screen a `ScreenRef` means.
|
|
public enum ScreenMatching {
|
|
/// - Parameter names: names of the connected screens in system order.
|
|
/// - Returns: index into `names`, or nil if the screen is not connected.
|
|
public static func index(of ref: ScreenRef, in names: [String]) -> Int? {
|
|
let sameName = names.indices.filter { names[$0] == ref.name }
|
|
switch sameName.count {
|
|
case 1:
|
|
return sameName[0]
|
|
case 0:
|
|
// Renamed or different monitor model: only trust the position if the count still fits.
|
|
return nil
|
|
default:
|
|
// Identical monitors: prefer the remembered position, else the first free match.
|
|
return sameName.contains(ref.index) ? ref.index : sameName.first
|
|
}
|
|
}
|
|
|
|
/// Resolves all assignments; screens claimed twice keep the first assignment.
|
|
public static func resolve(_ assignments: [VideoAssignment], in names: [String]) -> [Int: Source] {
|
|
var result: [Int: Source] = [:]
|
|
for assignment in assignments {
|
|
guard let index = index(of: assignment.screen, in: names), result[index] == nil else { continue }
|
|
result[index] = assignment.source
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
|
|
/// What to stop and start to get from the current state to the desired one.
|
|
public enum Reconcile {
|
|
public struct Plan<Key: Hashable, Value: Equatable> {
|
|
public var stop: [Key]
|
|
public var start: [Key: Value]
|
|
}
|
|
|
|
public static func plan<Key: Hashable, Value: Equatable>(current: [Key: Value], desired: [Key: Value]) -> Plan<Key, Value> {
|
|
let stop = current.keys.filter { desired[$0] == nil }
|
|
let start = desired.filter { current[$0.key] != $0.value }
|
|
return Plan(stop: stop, start: start)
|
|
}
|
|
}
|