MonitorControl/MonitorControl/Support/DisplayManager.swift
2025-11-16 10:59:58 +01:00

560 lines
24 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright © MonitorControl. @JoniVR, @theOneyouseek, @waydabber and others
import Cocoa
import CoreGraphics
import os.log
class DisplayManager {
public static let shared = DisplayManager()
var displays: [Display] = []
var audioControlTargetDisplays: [OtherDisplay] = []
let globalDDCQueue = DispatchQueue(label: "Global DDC queue")
let gammaActivityEnforcer = NSWindow(contentRect: .init(origin: NSPoint(x: 0, y: 0), size: .init(width: DEBUG_GAMMA_ENFORCER ? 15 : 1, height: DEBUG_GAMMA_ENFORCER ? 15 : 1)), styleMask: [], backing: .buffered, defer: false)
var gammaInterferenceCounter = 0
var gammaInterferenceWarningShown = false
func createGammaActivityEnforcer() {
self.gammaActivityEnforcer.title = "Monitor Control Gamma Activity Enforcer"
self.gammaActivityEnforcer.isMovableByWindowBackground = false
self.gammaActivityEnforcer.backgroundColor = DEBUG_GAMMA_ENFORCER ? .red : .black
self.gammaActivityEnforcer.alphaValue = 1 * (DEBUG_GAMMA_ENFORCER ? 0.5 : 0.01)
self.gammaActivityEnforcer.ignoresMouseEvents = true
self.gammaActivityEnforcer.level = .screenSaver
self.gammaActivityEnforcer.orderFrontRegardless()
self.gammaActivityEnforcer.collectionBehavior = [.stationary, .canJoinAllSpaces]
os_log("Gamma activity enforcer created.", type: .info)
}
func enforceGammaActivity() {
if self.gammaActivityEnforcer.alphaValue == 1 * (DEBUG_GAMMA_ENFORCER ? 0.5 : 0.01) {
self.gammaActivityEnforcer.alphaValue = 2 * (DEBUG_GAMMA_ENFORCER ? 0.5 : 0.01)
} else {
self.gammaActivityEnforcer.alphaValue = 1 * (DEBUG_GAMMA_ENFORCER ? 0.5 : 0.01)
}
}
func moveGammaActivityEnforcer(displayID: CGDirectDisplayID) {
if let screen = DisplayManager.getByDisplayID(displayID: DisplayManager.resolveEffectiveDisplayID(displayID)) {
self.gammaActivityEnforcer.setFrameOrigin(screen.frame.origin)
}
self.gammaActivityEnforcer.orderFrontRegardless()
}
var shades: [CGDirectDisplayID: NSWindow] = [:]
var shadeGrave: [NSWindow] = []
func isDisqualifiedFromShade(_ displayID: CGDirectDisplayID) -> Bool {
if CGDisplayIsInHWMirrorSet(displayID) != 0 || CGDisplayIsInMirrorSet(displayID) != 0 {
if displayID == DisplayManager.resolveEffectiveDisplayID(displayID), DisplayManager.isVirtual(displayID: displayID) || DisplayManager.isDummy(displayID: displayID) {
var displayIDs = [CGDirectDisplayID](repeating: 0, count: 16)
var displayCount: UInt32 = 0
guard CGGetOnlineDisplayList(16, &displayIDs, &displayCount) == .success else {
return true
}
for displayId in displayIDs where CGDisplayMirrorsDisplay(displayId) == displayID && !DisplayManager.isVirtual(displayID: displayID) {
return true
}
return false
}
return true
}
return false
}
func createShadeOnDisplay(displayID: CGDirectDisplayID) -> NSWindow? {
if let screen = DisplayManager.getByDisplayID(displayID: displayID) {
let shade = NSWindow(contentRect: .init(origin: NSPoint(x: 0, y: 0), size: .init(width: 10, height: 1)), styleMask: [], backing: .buffered, defer: false)
shade.title = "Monitor Control Window Shade for Display " + String(displayID)
shade.isMovableByWindowBackground = false
shade.backgroundColor = .clear
shade.ignoresMouseEvents = true
shade.level = NSWindow.Level(rawValue: Int(CGShieldingWindowLevel()))
shade.orderFrontRegardless()
shade.collectionBehavior = [.stationary, .canJoinAllSpaces, .ignoresCycle]
shade.setFrame(screen.frame, display: true)
shade.contentView?.wantsLayer = true
shade.contentView?.alphaValue = 0.0
shade.contentView?.layer?.backgroundColor = .black
shade.contentView?.setNeedsDisplay(shade.frame)
os_log("Window shade created for display %{public}@", type: .info, String(displayID))
return shade
}
return nil
}
func getShade(displayID: CGDirectDisplayID) -> NSWindow? {
guard !self.isDisqualifiedFromShade(displayID) else {
return nil
}
if let shade = shades[displayID] {
return shade
} else {
if let shade = self.createShadeOnDisplay(displayID: displayID) {
self.shades[displayID] = shade
return shade
}
}
return nil
}
func destroyAllShades() -> Bool {
var ret = false
for displayID in self.shades.keys {
os_log("Attempting to destory shade for display %{public}@", type: .info, String(displayID))
if self.destroyShade(displayID: displayID) {
ret = true
}
}
if ret {
os_log("Destroyed all shades.", type: .info)
} else {
os_log("No shades were found to be destroyed.", type: .info)
}
return ret
}
func destroyShade(displayID: CGDirectDisplayID) -> Bool {
if let shade = shades[displayID] {
os_log("Destroying shade for display %{public}@", type: .info, String(displayID))
self.shadeGrave.append(shade)
self.shades.removeValue(forKey: displayID)
shade.close()
return true
}
return false
}
func updateShade(displayID: CGDirectDisplayID) -> Bool {
guard !self.isDisqualifiedFromShade(displayID) else {
return false
}
if let screen = DisplayManager.getByDisplayID(displayID: displayID) {
if let shade = getShade(displayID: displayID) {
shade.setFrame(screen.frame, display: true)
return true
}
}
return false
}
func getShadeAlpha(displayID: CGDirectDisplayID) -> Float? {
guard !self.isDisqualifiedFromShade(displayID) else {
return 1
}
if let shade = getShade(displayID: displayID) {
return Float(shade.contentView?.alphaValue ?? 1)
} else {
return 1
}
}
func setShadeAlpha(value: Float, displayID: CGDirectDisplayID) -> Bool {
guard !self.isDisqualifiedFromShade(displayID) else {
return false
}
if let shade = getShade(displayID: displayID) {
shade.contentView?.alphaValue = CGFloat(value)
return true
}
return false
}
func configureDisplays() {
self.clearDisplays()
var onlineDisplayIDs = [CGDirectDisplayID](repeating: 0, count: 16)
var displayCount: UInt32 = 0
guard CGGetOnlineDisplayList(16, &onlineDisplayIDs, &displayCount) == .success else {
os_log("Unable to get display list.", type: .info)
return
}
for onlineDisplayID in onlineDisplayIDs where onlineDisplayID != 0 {
let name = DisplayManager.getDisplayNameByID(displayID: onlineDisplayID)
let id = onlineDisplayID
let vendorNumber = CGDisplayVendorNumber(onlineDisplayID)
let modelNumber = CGDisplayModelNumber(onlineDisplayID)
let serialNumber = CGDisplaySerialNumber(onlineDisplayID)
let isDummy: Bool = DisplayManager.isDummy(displayID: onlineDisplayID)
let isVirtual: Bool = DisplayManager.isVirtual(displayID: onlineDisplayID)
if !DEBUG_SW, DisplayManager.isAppleDisplay(displayID: onlineDisplayID) { // MARK: (point of interest for testing)
let appleDisplay = AppleDisplay(id, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, serialNumber: serialNumber, isVirtual: isVirtual, isDummy: isDummy)
os_log("Apple display found - %{public}@", type: .info, "ID: \(appleDisplay.identifier), Name: \(appleDisplay.name) (Vendor: \(appleDisplay.vendorNumber ?? 0), Model: \(appleDisplay.modelNumber ?? 0))")
self.addDisplay(display: appleDisplay)
} else {
let otherDisplay = OtherDisplay(id, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, serialNumber: serialNumber, isVirtual: isVirtual, isDummy: isDummy)
os_log("Other display found - %{public}@", type: .info, "ID: \(otherDisplay.identifier), Name: \(otherDisplay.name) (Vendor: \(otherDisplay.vendorNumber ?? 0), Model: \(otherDisplay.modelNumber ?? 0))")
self.addDisplay(display: otherDisplay)
}
}
}
func setupOtherDisplays(firstrun: Bool = false) {
for otherDisplay in self.getOtherDisplays() {
for command in [Command.audioSpeakerVolume, Command.contrast] where !otherDisplay.readPrefAsBool(key: .unavailableDDC, for: command) && !otherDisplay.isSw() {
otherDisplay.setupCurrentAndMaxValues(command: command, firstrun: firstrun)
}
if (!otherDisplay.isSw() && !otherDisplay.readPrefAsBool(key: .unavailableDDC, for: .brightness)) || otherDisplay.isSw() {
otherDisplay.setupCurrentAndMaxValues(command: .brightness, firstrun: firstrun)
otherDisplay.brightnessSyncSourceValue = otherDisplay.readPrefAsFloat(for: .brightness)
}
}
}
func restoreOtherDisplays() {
for otherDisplay in self.getDdcCapableDisplays() {
for command in [Command.contrast, Command.brightness] where !otherDisplay.readPrefAsBool(key: .unavailableDDC, for: command) {
otherDisplay.restoreDDCSettingsToDisplay(command: command)
}
}
}
func normalizedName(_ name: String) -> String {
var normalizedName = name.replacingOccurrences(of: "(", with: "")
normalizedName = normalizedName.replacingOccurrences(of: ")", with: "")
normalizedName = normalizedName.replacingOccurrences(of: " ", with: "")
for i in 0 ... 9 {
normalizedName = normalizedName.replacingOccurrences(of: String(i), with: "")
}
return normalizedName
}
func updateAudioControlTargetDisplays(deviceName: String) -> Int {
self.audioControlTargetDisplays.removeAll()
os_log("Detecting displays for audio control via audio device name matching...", type: .info)
var numOfAddedDisplays = 0
for ddcCapableDisplay in self.getDdcCapableDisplays() {
var displayAudioDeviceName = ddcCapableDisplay.readPrefAsString(key: .audioDeviceNameOverride)
if displayAudioDeviceName == "" {
displayAudioDeviceName = DisplayManager.getDisplayRawNameByID(displayID: ddcCapableDisplay.identifier)
}
if self.normalizedName(displayAudioDeviceName) == self.normalizedName(deviceName) {
self.audioControlTargetDisplays.append(ddcCapableDisplay)
numOfAddedDisplays += 1
os_log("Added display for audio control - %{public}@", type: .info, ddcCapableDisplay.name)
}
}
return numOfAddedDisplays
}
func getOtherDisplays() -> [OtherDisplay] {
self.displays.compactMap { $0 as? OtherDisplay }
}
func sortDisplays() {
// Opsiyonel: sıralamadan önce log al
let before = displays.map { $0.name }
os_log("Displays before sorting: %{public}@", before)
// Inplace sıralama
displays.sort { lhs, rhs in
lhs.name.localizedStandardCompare(rhs.name) == .orderedAscending
}
// Opsiyonel: sıralamadan sonra log al
let after = displays.map { $0.name }
os_log("Displays after sorting: %{public}@", after)
}
func sortDisplaysByFriendlyName() -> [Display] {
return displays.sorted { lhs, rhs in
let lhsTitle = lhs.readPrefAsString(key: .friendlyName).isEmpty
? lhs.name
: lhs.readPrefAsString(key: .friendlyName)
let rhsTitle = rhs.readPrefAsString(key: .friendlyName).isEmpty
? rhs.name
: rhs.readPrefAsString(key: .friendlyName)
return lhsTitle.localizedStandardCompare(rhsTitle) == .orderedDescending
}
}
/// displays dizisini sıralar ve döner
func getAllDisplays() -> [Display] {
return displays
}
func getDdcCapableDisplays() -> [OtherDisplay] {
self.displays.compactMap { display -> OtherDisplay? in
if let otherDisplay = display as? OtherDisplay, !otherDisplay.isSw() {
return otherDisplay
} else { return nil }
}
}
func getAppleDisplays() -> [AppleDisplay] {
self.displays.compactMap { $0 as? AppleDisplay }
}
func getBuiltInDisplay() -> Display? {
self.displays.first { CGDisplayIsBuiltin($0.identifier) != 0 }
}
func getCurrentDisplay(byFocus: Bool = false) -> Display? {
if byFocus {
guard let mainDisplayID = NSScreen.main?.displayID else {
return nil
}
return self.displays.first { $0.identifier == mainDisplayID }
} else {
let mouseLocation = NSEvent.mouseLocation
let screens = NSScreen.screens
if let screenWithMouse = (screens.first { NSMouseInRect(mouseLocation, $0.frame, false) }) {
return self.displays.first { $0.identifier == screenWithMouse.displayID }
}
return nil
}
}
func addDisplay(display: Display) {
self.displays.append(display)
}
func clearDisplays() {
self.displays = []
}
func addDisplayCounterSuffixes() {
var nameDisplays: [String: [Display]] = [:]
for display in self.displays {
if nameDisplays[display.name] != nil {
nameDisplays[display.name]?.append(display)
} else {
nameDisplays[display.name] = [display]
}
}
for nameDisplayKey in nameDisplays.keys where nameDisplays[nameDisplayKey]?.count ?? 0 > 1 {
for i in 0 ... (nameDisplays[nameDisplayKey]?.count ?? 1) - 1 {
if let display = nameDisplays[nameDisplayKey]?[i] {
display.name = "" + display.name + " (" + String(i + 1) + ")"
}
}
}
}
func updateArm64AVServices() {
if Arm64DDC.isArm64 {
os_log("arm64 AVService update requested", type: .info)
var displayIDs: [CGDirectDisplayID] = []
for otherDisplay in self.getOtherDisplays() {
displayIDs.append(otherDisplay.identifier)
}
for serviceMatch in Arm64DDC.getServiceMatches(displayIDs: displayIDs) {
for otherDisplay in self.getOtherDisplays() where otherDisplay.identifier == serviceMatch.displayID && serviceMatch.service != nil {
otherDisplay.arm64avService = serviceMatch.service
os_log("Display service match successful for display %{public}@", type: .info, String(serviceMatch.displayID))
if serviceMatch.discouraged {
os_log("Display %{public}@ is flagged as discouraged by Arm64DDC.", type: .info, String(serviceMatch.displayID))
otherDisplay.isDiscouraged = true
} else if serviceMatch.dummy {
os_log("Display %{public}@ is flagged as dummy by Arm64DDC.", type: .info, String(serviceMatch.displayID))
otherDisplay.isDiscouraged = true
otherDisplay.isDummy = true
} else {
otherDisplay.arm64ddc = DEBUG_SW ? false : true // MARK: (point of interest when testing)
}
}
}
os_log("AVService update done", type: .info)
}
}
func resetSwBrightnessForAllDisplays(prefsOnly: Bool = false, noPrefSave: Bool = false, async: Bool = false) {
for otherDisplay in self.getOtherDisplays() {
if !prefsOnly {
_ = otherDisplay.setSwBrightness(1, smooth: async, noPrefSave: noPrefSave)
if !noPrefSave {
otherDisplay.smoothBrightnessTransient = 1
}
} else if !noPrefSave {
otherDisplay.savePref(1, key: .SwBrightness)
otherDisplay.smoothBrightnessTransient = 1
}
if otherDisplay.isSw(), !noPrefSave {
otherDisplay.savePref(1, for: .brightness)
}
}
}
func restoreSwBrightnessForAllDisplays(async: Bool = false) {
for otherDisplay in self.getOtherDisplays() {
if (otherDisplay.readPrefAsFloat(for: .brightness) == 0 && !prefs.bool(forKey: PrefKey.disableCombinedBrightness.rawValue)) || (otherDisplay.readPrefAsFloat(for: .brightness) < otherDisplay.combinedBrightnessSwitchingValue() && !prefs.bool(forKey: PrefKey.separateCombinedScale.rawValue) && !prefs.bool(forKey: PrefKey.disableCombinedBrightness.rawValue)) || otherDisplay.isSw() {
let savedPrefValue = otherDisplay.readPrefAsFloat(key: .SwBrightness)
if otherDisplay.getSwBrightness() != savedPrefValue {
OSDUtils.popEmptyOsd(displayID: otherDisplay.identifier, command: Command.brightness) // This will give the user a hint why is the brightness suddenly changes.
}
otherDisplay.savePref(otherDisplay.getSwBrightness(), key: .SwBrightness)
os_log("Restoring sw brightness to %{public}@ on other display %{public}@", type: .info, String(savedPrefValue), String(otherDisplay.identifier))
_ = otherDisplay.setSwBrightness(savedPrefValue, smooth: async)
if otherDisplay.isSw(), let slider = otherDisplay.sliderHandler[.brightness] {
os_log("Restoring sw slider to %{public}@ for other display %{public}@", type: .info, String(savedPrefValue), String(otherDisplay.identifier))
slider.setValue(savedPrefValue, displayID: otherDisplay.identifier)
}
} else {
_ = otherDisplay.setSwBrightness(1)
}
}
}
func getAffectedDisplays(isBrightness: Bool = false, isVolume: Bool = false) -> [Display]? {
var affectedDisplays: [Display]
let allDisplays = self.getAllDisplays()
var currentDisplay: Display?
if isBrightness {
if prefs.integer(forKey: PrefKey.multiKeyboardBrightness.rawValue) == MultiKeyboardBrightness.allScreens.rawValue {
affectedDisplays = allDisplays
return affectedDisplays
}
currentDisplay = self.getCurrentDisplay(byFocus: prefs.integer(forKey: PrefKey.multiKeyboardBrightness.rawValue) == MultiKeyboardBrightness.focusInsteadOfMouse.rawValue)
}
if isVolume {
if prefs.integer(forKey: PrefKey.multiKeyboardVolume.rawValue) == MultiKeyboardVolume.allScreens.rawValue {
affectedDisplays = allDisplays
return affectedDisplays
} else if prefs.integer(forKey: PrefKey.multiKeyboardVolume.rawValue) == MultiKeyboardVolume.audioDeviceNameMatching.rawValue {
return self.audioControlTargetDisplays
}
currentDisplay = self.getCurrentDisplay(byFocus: false)
}
if let currentDisplay = currentDisplay {
affectedDisplays = [currentDisplay]
if CGDisplayIsInHWMirrorSet(currentDisplay.identifier) != 0 || CGDisplayIsInMirrorSet(currentDisplay.identifier) != 0, CGDisplayMirrorsDisplay(currentDisplay.identifier) == 0 {
for display in allDisplays where CGDisplayMirrorsDisplay(display.identifier) == currentDisplay.identifier {
affectedDisplays.append(display)
}
}
} else {
affectedDisplays = []
}
return affectedDisplays
}
static func isDummy(displayID: CGDirectDisplayID) -> Bool {
let vendorNumber = CGDisplayVendorNumber(displayID)
let rawName = DisplayManager.getDisplayRawNameByID(displayID: displayID)
if rawName.lowercased().contains("dummy") || (self.isVirtual(displayID: displayID) && vendorNumber == UInt32(0xF0F0)) {
os_log("NOTE: Display is a dummy!", type: .info)
return true
}
return false
}
static func isVirtual(displayID: CGDirectDisplayID) -> Bool {
var isVirtual = false
if !DEBUG_MACOS10, #available(macOS 11.0, *) {
if let dictionary = (CoreDisplay_DisplayCreateInfoDictionary(displayID)?.takeRetainedValue() as NSDictionary?) {
let isVirtualDevice = dictionary["kCGDisplayIsVirtualDevice"] as? Bool
let displayIsAirplay = dictionary["kCGDisplayIsAirPlay"] as? Bool
if isVirtualDevice ?? displayIsAirplay ?? false {
isVirtual = true
}
}
}
return isVirtual
}
static func engageMirror() -> Bool {
var onlineDisplayIDs = [CGDirectDisplayID](repeating: 0, count: 16)
var displayCount: UInt32 = 0
guard CGGetOnlineDisplayList(16, &onlineDisplayIDs, &displayCount) == .success, displayCount > 1 else {
return false
}
// Break display mirror if there is any
var mirrorBreak = false
var displayConfigRef: CGDisplayConfigRef?
for onlineDisplayID in onlineDisplayIDs where onlineDisplayID != 0 {
if CGDisplayIsInHWMirrorSet(onlineDisplayID) != 0 || CGDisplayIsInMirrorSet(onlineDisplayID) != 0 {
if mirrorBreak == false {
CGBeginDisplayConfiguration(&displayConfigRef)
}
CGConfigureDisplayMirrorOfDisplay(displayConfigRef, onlineDisplayID, kCGNullDirectDisplay)
mirrorBreak = true
}
}
if mirrorBreak {
CGCompleteDisplayConfiguration(displayConfigRef, CGConfigureOption.permanently)
return true
}
// Build display mirror
var mainDisplayId = kCGNullDirectDisplay
for onlineDisplayID in onlineDisplayIDs where onlineDisplayID != 0 {
if CGDisplayIsBuiltin(onlineDisplayID) == 0, mainDisplayId == kCGNullDirectDisplay {
mainDisplayId = onlineDisplayID
}
}
guard mainDisplayId != kCGNullDirectDisplay else {
return false
}
CGBeginDisplayConfiguration(&displayConfigRef)
for onlineDisplayID in onlineDisplayIDs where onlineDisplayID != 0 && onlineDisplayID != mainDisplayId {
CGConfigureDisplayMirrorOfDisplay(displayConfigRef, onlineDisplayID, mainDisplayId)
}
CGCompleteDisplayConfiguration(displayConfigRef, CGConfigureOption.permanently)
return true
}
static func resolveEffectiveDisplayID(_ displayID: CGDirectDisplayID) -> CGDirectDisplayID {
var realDisplayID = displayID
if CGDisplayIsInHWMirrorSet(displayID) != 0 || CGDisplayIsInMirrorSet(displayID) != 0 {
let mirroredDisplayID = CGDisplayMirrorsDisplay(displayID)
if mirroredDisplayID != 0 {
realDisplayID = mirroredDisplayID
}
}
return realDisplayID
}
static func isAppleDisplay(displayID: CGDirectDisplayID) -> Bool {
if #available(macOS 15.0, *) {
if CGDisplayVendorNumber(displayID) != 1552, CGSIsHDRSupported(displayID), CGSIsHDREnabled(displayID) {
return CGDisplayIsBuiltin(displayID) != 0
}
}
var brightness: Float = -1
let ret = DisplayServicesGetBrightness(displayID, &brightness)
if ret == 0, brightness >= 0 { // If brightness read appears to be successful using DisplayServices then it should be an Apple display
return true
}
return CGDisplayIsBuiltin(displayID) != 0 // If built-in display, it should be Apple
}
static func getByDisplayID(displayID: CGDirectDisplayID) -> NSScreen? {
NSScreen.screens.first { $0.displayID == displayID }
}
static func getDisplayRawNameByID(displayID: CGDirectDisplayID) -> String {
let defaultName = ""
if !DEBUG_MACOS10, #available(macOS 11.0, *) {
if let dictionary = (CoreDisplay_DisplayCreateInfoDictionary(displayID)?.takeRetainedValue() as NSDictionary?), let nameList = dictionary["DisplayProductName"] as? [String: String], let name = nameList["en_US"] ?? nameList.first?.value {
return name
}
}
if let screen = getByDisplayID(displayID: displayID) {
return screen.displayName ?? defaultName
}
return defaultName
}
static func getDisplayNameByID(displayID: CGDirectDisplayID) -> String {
let defaultName: String = NSLocalizedString("Unknown", comment: "Unknown display name")
if !DEBUG_MACOS10, #available(macOS 11.0, *) {
if let dictionary = (CoreDisplay_DisplayCreateInfoDictionary(displayID)?.takeRetainedValue() as NSDictionary?), let nameList = dictionary["DisplayProductName"] as? [String: String], var name = nameList[Locale.current.identifier] ?? nameList["en_US"] ?? nameList.first?.value {
if CGDisplayIsInHWMirrorSet(displayID) != 0 || CGDisplayIsInMirrorSet(displayID) != 0 {
let mirroredDisplayID = CGDisplayMirrorsDisplay(displayID)
if mirroredDisplayID != 0, let dictionary = (CoreDisplay_DisplayCreateInfoDictionary(mirroredDisplayID)?.takeRetainedValue() as NSDictionary?), let nameList = dictionary["DisplayProductName"] as? [String: String], let mirroredName = nameList[Locale.current.identifier] ?? nameList["en_US"] ?? nameList.first?.value {
name.append(" | " + mirroredName)
}
}
return name
}
}
if let screen = getByDisplayID(displayID: displayID) { // MARK: This, and NSScreen+Extension.swift will not be needed when we drop MacOS 10 support.
if #available(macOS 10.15, *) {
return screen.localizedName
} else {
return screen.displayName ?? defaultName
}
}
return defaultName
}
}