import AppKit import CoreGraphics import Foundation import OSLog import MacToolsPluginKit @MainActor protocol DisplayResolutionControlling { func listConnectedDisplays() -> [DisplayInfo] func listAvailableResolutions(for displayID: CGDirectDisplayID) -> [DisplayResolutionInfo] func applyResolution( _ info: DisplayResolutionInfo, for displayID: CGDirectDisplayID ) -> Result } @MainActor final class DisplayResolutionController { private let displayProvider: DisplayProviding private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "cc.ggbond.mactools", category: "DisplayResolutionController") init(displayProvider: DisplayProviding = SystemDisplayService()) { self.displayProvider = displayProvider } func listConnectedDisplays() -> [DisplayInfo] { displayProvider.listConnectedDisplays() } func listAvailableResolutions(for displayID: CGDirectDisplayID) -> [DisplayResolutionInfo] { let options = [kCGDisplayShowDuplicateLowResolutionModes: kCFBooleanTrue] as CFDictionary guard let rawModes = CGDisplayCopyAllDisplayModes(displayID, options) as? [CGDisplayMode] else { logger.error("CGDisplayCopyAllDisplayModes returned nil for displayID \(displayID)") return [] } let currentID = CGDisplayCopyDisplayMode(displayID)?.ioDisplayModeID ?? 0 let candidates = rawModes.filter { mode in let flags = mode.ioFlags return mode.isUsableForDesktopGUI() && flags & DisplayModeFlags.safe != 0 && flags & DisplayModeFlags.notPreset == 0 } let infos = candidates.map { mode in let flags = mode.ioFlags return DisplayResolutionInfo( modeId: mode.ioDisplayModeID, width: mode.width, height: mode.height, pixelWidth: mode.pixelWidth, pixelHeight: mode.pixelHeight, refreshRate: mode.refreshRate, isHiDPI: mode.pixelWidth > mode.width, isNative: flags & DisplayModeFlags.native != 0, isDefault: flags & DisplayModeFlags.default != 0, isCurrent: mode.ioDisplayModeID == currentID ) } return Self.sortModes(Self.deduplicateModes(infos)) } nonisolated static func deduplicateModes(_ modes: [DisplayResolutionInfo]) -> [DisplayResolutionInfo] { var bestByKey: [String: DisplayResolutionInfo] = [:] for mode in modes { let key = deduplicationKey(for: mode) if let existing = bestByKey[key] { bestByKey[key] = preferredMode(existing: existing, candidate: mode) } else { bestByKey[key] = mode } } return Array(bestByKey.values) } nonisolated static func sortModes(_ modes: [DisplayResolutionInfo]) -> [DisplayResolutionInfo] { modes.sorted { if $0.width != $1.width { return $0.width > $1.width } if $0.height != $1.height { return $0.height > $1.height } if $0.isCurrent != $1.isCurrent { return $0.isCurrent } if $0.isHiDPI != $1.isHiDPI { return $0.isHiDPI } return $0.refreshRate > $1.refreshRate } } @discardableResult func applyResolution( _ info: DisplayResolutionInfo, for displayID: CGDirectDisplayID ) -> Result { guard let target = fetchCGDisplayMode(modeId: info.modeId, displayID: displayID) else { return .failure(.modeNotFound(modeId: info.modeId)) } var config: CGDisplayConfigRef? let beginError = CGBeginDisplayConfiguration(&config) guard beginError == .success, let config else { return .failure(.beginConfigFailed(beginError)) } let configureError = CGConfigureDisplayWithDisplayMode(config, displayID, target, nil) guard configureError == .success else { CGCancelDisplayConfiguration(config) return .failure(.configureFailed(configureError)) } let completeError = CGCompleteDisplayConfiguration(config, .permanently) guard completeError == .success else { return .failure(.completeFailed(completeError)) } return .success(()) } private func fetchCGDisplayMode(modeId: Int32, displayID: CGDirectDisplayID) -> CGDisplayMode? { let options = [kCGDisplayShowDuplicateLowResolutionModes: kCFBooleanTrue] as CFDictionary guard let modes = CGDisplayCopyAllDisplayModes(displayID, options) as? [CGDisplayMode] else { return nil } return modes.first(where: { $0.ioDisplayModeID == modeId }) } nonisolated private static func deduplicationKey(for mode: DisplayResolutionInfo) -> String { "\(mode.width)x\(mode.height)" } nonisolated private static func preferredMode( existing: DisplayResolutionInfo, candidate: DisplayResolutionInfo ) -> DisplayResolutionInfo { if existing.isCurrent != candidate.isCurrent { return existing.isCurrent ? existing : candidate } if existing.isHiDPI != candidate.isHiDPI { return existing.isHiDPI ? existing : candidate } return existing.refreshRate >= candidate.refreshRate ? existing : candidate } } extension DisplayResolutionController: DisplayResolutionControlling {}