Some additional fixes (#738)

- Fix naming of wakeNotification()
- Fix for failing to update Advanced Settings checkbox on Preferences Reset.
- Better handling of known dummy displays.
This commit is contained in:
Istvan T 2021-10-25 19:40:52 +02:00 committed by GitHub
parent 5d3d08ddfc
commit 6248d582ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 70 additions and 26 deletions

View file

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>6828</string>
<string>6850</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>

View file

@ -6,18 +6,24 @@ import os.log
class AppleDisplay: Display {
private var displayQueue: DispatchQueue
override init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false) {
override init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false, isDummy: Bool = false) {
self.displayQueue = DispatchQueue(label: String("displayQueue-\(identifier)"))
super.init(identifier, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual)
super.init(identifier, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual, isDummy: isDummy)
}
public func getAppleBrightness() -> Float {
guard !self.isDummy else {
return 1
}
var brightness: Float = 0
DisplayServicesGetBrightness(self.identifier, &brightness)
return brightness
}
public func setAppleBrightness(value: Float) {
guard !self.isDummy else {
return
}
self.displayQueue.sync {
DisplayServicesSetBrightness(self.identifier, value)
DisplayServicesBrightnessChanged(self.identifier, Double(value))
@ -25,6 +31,9 @@ class AppleDisplay: Display {
}
override func setDirectBrightness(_ to: Float, transient: Bool = false) -> Bool {
guard !self.isDummy else {
return false
}
let value = max(min(to, 1), 0)
self.setAppleBrightness(value: value)
if !transient {
@ -36,6 +45,9 @@ class AppleDisplay: Display {
}
override func getBrightness() -> Float {
guard !self.isDummy else {
return 1
}
if self.prefExists(for: .brightness) {
return self.readPrefAsFloat(for: .brightness)
} else {

View file

@ -22,6 +22,7 @@ class Display: Equatable {
var sliderHandler: [Command: SliderHandler] = [:]
var brightnessSyncSourceValue: Float = 1
var isVirtual: Bool = false
var isDummy: Bool = false
var defaultGammaTableRed = [CGGammaValue](repeating: 0, count: 256)
var defaultGammaTableGreen = [CGGammaValue](repeating: 0, count: 256)
@ -61,7 +62,7 @@ class Display: Equatable {
return (key ?? PrefKey.value).rawValue + (command != nil ? String((command ?? Command.none).rawValue) : "") + self.prefsId
}
internal init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false) {
internal init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false, isDummy: Bool = false) {
self.identifier = identifier
self.name = name
self.vendorNumber = vendorNumber
@ -69,13 +70,14 @@ class Display: Equatable {
self.prefsId = "(" + String(name.filter { !$0.isWhitespace }) + String(vendorNumber ?? 0) + String(modelNumber ?? 0) + "@" + String(identifier) + ")"
os_log("Display init with prefsIdentifier %{public}@", type: .info, self.prefsId)
self.isVirtual = DEBUG_VIRTUAL ? true : isVirtual
self.isDummy = isDummy
self.swUpdateDefaultGammaTable()
self.smoothBrightnessTransient = self.getBrightness()
if self.isVirtual {
os_log("Creating or updating shade for virtual display %{public}@", type: .info, String(self.identifier))
if self.isVirtual || self.readPrefAsBool(key: PrefKey.avoidGamma), !self.isDummy {
os_log("Creating or updating shade for display %{public}@", type: .info, String(self.identifier))
_ = DisplayManager.shared.updateShade(displayID: self.identifier)
} else {
os_log("Destroying shade (if exists) for real display %{public}@", type: .info, String(self.identifier))
os_log("Destroying shade (if exists) for display %{public}@", type: .info, String(self.identifier))
_ = DisplayManager.shared.destroyShade(displayID: self.identifier)
}
self.brightnessSyncSourceValue = self.getBrightness()
@ -187,6 +189,9 @@ class Display: Equatable {
}
func swUpdateDefaultGammaTable() {
guard !self.isDummy else {
return
}
CGGetDisplayTransferByTable(self.identifier, 256, &self.defaultGammaTableRed, &self.defaultGammaTableGreen, &self.defaultGammaTableBlue, &self.defaultGammaTableSampleCount)
let redPeak = self.defaultGammaTableRed.max() ?? 0
let greenPeak = self.defaultGammaTableGreen.max() ?? 0
@ -210,6 +215,10 @@ class Display: Equatable {
if !noPrefSave {
self.savePref(brightnessValue, key: .SwBrightness)
}
guard !self.isDummy else {
self.swBrightnessSemaphore.signal()
return true
}
var newValue = brightnessValue
currentValue = self.swBrightnessTransform(value: currentValue)
newValue = self.swBrightnessTransform(value: newValue)
@ -249,6 +258,13 @@ class Display: Equatable {
}
func getSwBrightness() -> Float {
guard !self.isDummy else {
if self.prefExists(key: .SwBrightness) {
return self.readPrefAsFloat(key: .SwBrightness)
} else {
return 1
}
}
self.swBrightnessSemaphore.wait()
if self.isVirtual || self.readPrefAsBool(key: .avoidGamma) {
let rawBrightnessValue = 1 - (DisplayManager.shared.getShadeAlpha(displayID: self.identifier) ?? 1)
@ -274,7 +290,7 @@ class Display: Equatable {
func checkGammaInterference() {
let currentSwBrightness = self.getSwBrightness()
guard !DisplayManager.shared.gammaInterferenceWarningShown, !(prefs.bool(forKey: PrefKey.disableCombinedBrightness.rawValue)), !self.readPrefAsBool(key: .avoidGamma), !self.isVirtual, !self.smoothBrightnessRunning, self.prefExists(key: .SwBrightness), abs(currentSwBrightness - self.readPrefAsFloat(key: .SwBrightness)) > 0.02 else {
guard !self.isDummy, !DisplayManager.shared.gammaInterferenceWarningShown, !(prefs.bool(forKey: PrefKey.disableCombinedBrightness.rawValue)), !self.readPrefAsBool(key: .avoidGamma), !self.isVirtual, !self.smoothBrightnessRunning, self.prefExists(key: .SwBrightness), abs(currentSwBrightness - self.readPrefAsFloat(key: .SwBrightness)) > 0.02 else {
return
}
DisplayManager.shared.gammaInterferenceCounter += 1
@ -309,7 +325,7 @@ class Display: Equatable {
}
func isSwBrightnessNotDefault() -> Bool {
guard !self.isVirtual else {
guard !self.isVirtual, !self.isDummy else {
return false
}
if self.getSwBrightness() < 1 {

View file

@ -23,8 +23,8 @@ class OtherDisplay: Display {
set { prefs.set(newValue, forKey: PrefKey.pollingCount.rawValue + self.prefsId) }
}
override init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false) {
super.init(identifier, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual)
override init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false, isDummy: Bool = false) {
super.init(identifier, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual, isDummy: isDummy)
if !isVirtual, !Arm64DDC.isArm64 {
self.ddc = IntelDDC(for: identifier)
}
@ -256,7 +256,7 @@ class OtherDisplay: Display {
}
func isSwOnly() -> Bool {
return (!self.arm64ddc && self.ddc == nil) || self.isVirtual
return (!self.arm64ddc && self.ddc == nil) || self.isVirtual || self.isDummy
}
func isSw() -> Bool {

View file

@ -168,9 +168,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
NotificationCenter.default.addObserver(self, selector: #selector(self.audioDeviceChanged), name: Notification.Name.defaultOutputDeviceChanged, object: nil) // subscribe Audio output detector (SimplyCoreAudio)
DistributedNotificationCenter.default.addObserver(self, selector: #selector(self.displayReconfigured), name: NSNotification.Name(rawValue: kColorSyncDisplayDeviceProfilesNotification.takeRetainedValue() as String), object: nil) // ColorSync change
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.sleepNotification), name: NSWorkspace.screensDidSleepNotification, object: nil) // sleep and wake listeners
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.wakeNotofication), name: NSWorkspace.screensDidWakeNotification, object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.wakeNotification), name: NSWorkspace.screensDidWakeNotification, object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.sleepNotification), name: NSWorkspace.willSleepNotification, object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.wakeNotofication), name: NSWorkspace.didWakeNotification, object: nil)
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.wakeNotification), name: NSWorkspace.didWakeNotification, object: nil)
_ = DistributedNotificationCenter.default().addObserver(forName: NSNotification.Name(rawValue: NSNotification.Name.accessibilityApi.rawValue), object: nil, queue: nil) { _ in DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { self.updateMediaKeyTap() } } // listen for accessibility status changes
}
@ -179,7 +179,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
os_log("Sleeping with sleep %{public}@", type: .info, String(self.sleepID))
}
@objc private func wakeNotofication() {
@objc private func wakeNotification() {
if self.sleepID != 0 {
os_log("Waking up from sleep %{public}@", type: .info, String(self.sleepID))
let dispatchedSleepID = self.sleepID

View file

@ -271,6 +271,10 @@ class Arm64DDC: NSObject {
if ioregService.manufacturerID == "AOC", ioregService.productName == "28E850" {
return true
}
// If the display contains the string "Dummy", then it is highly suspicious
if ioregService.productName.contains("Dummy") || ioregService.productName.contains("dummy") {
return true
}
// First service location of Mac Mini HDMI is broken for DDC communication
if ioregService.transportDownstream == "HDMI", ioregService.serviceLocation == 1, modelIdentifier == "Macmini9,1" {
return true

View file

@ -151,27 +151,34 @@ class DisplayManager {
return
}
for onlineDisplayID in onlineDisplayIDs where onlineDisplayID != 0 {
let rawName = DisplayManager.getDisplayRawNameByID(displayID: onlineDisplayID)
let name = DisplayManager.getDisplayNameByID(displayID: onlineDisplayID)
let id = onlineDisplayID
let vendorNumber = CGDisplayVendorNumber(onlineDisplayID)
let modelNumber = CGDisplayModelNumber(onlineDisplayID)
var isDummy: Bool = false
var isVirtual: Bool = false
if rawName == "28E850" || rawName.lowercased().contains("dummy") {
os_log("NOTE: Display is a dummy!", type: .info)
isDummy = true
}
if !DEBUG_MACOS10, #available(macOS 11.0, *) {
if let dictionary = ((CoreDisplay_DisplayCreateInfoDictionary(onlineDisplayID))?.takeRetainedValue() as NSDictionary?) {
let isVirtualDevice = dictionary["kCGDisplayIsVirtualDevice"] as? Bool
let displayIsAirplay = dictionary["kCGDisplayIsAirPlay"] as? Bool
if isVirtualDevice ?? displayIsAirplay ?? false {
os_log("NOTE: Display is virtual!", type: .info)
isVirtual = true
}
}
}
if !DEBUG_SW, DisplayManager.isAppleDisplay(displayID: onlineDisplayID) { // MARK: (point of interest for testing)
let appleDisplay = AppleDisplay(id, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual)
os_log("Apple display found - %{public}@", type: .info, "ID: \(appleDisplay.identifier) Name: \(appleDisplay.name) (Vendor: \(appleDisplay.vendorNumber ?? 0), Model: \(appleDisplay.modelNumber ?? 0))")
let appleDisplay = AppleDisplay(id, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, 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, isVirtual: isVirtual)
os_log("Other display found - %{public}@", type: .info, "ID: \(otherDisplay.identifier) Name: \(otherDisplay.name) (Vendor: \(otherDisplay.vendorNumber ?? 0), Model: \(otherDisplay.modelNumber ?? 0))")
let otherDisplay = OtherDisplay(id, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, 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)
}
}
@ -351,7 +358,7 @@ class DisplayManager {
}
}
func getAffectedDisplays(isBrightness: Bool = false, isVolume: Bool = false, isContrast _: Bool = false) -> [Display]? {
func getAffectedDisplays(isBrightness: Bool = false, isVolume: Bool = false) -> [Display]? {
var affectedDisplays: [Display]
let allDisplays = self.getAllDisplays()
var currentDisplay: Display?

View file

@ -25,9 +25,13 @@ class DisplaysPrefsViewController: NSViewController, PreferencePane, NSTableView
override func viewDidLoad() {
super.viewDidLoad()
self.showAdvancedDisplays.state = prefs.bool(forKey: PrefKey.showAdvancedSettings.rawValue) ? .on : .off
self.loadDisplayList()
self.displayScrollView.scrollerStyle = .legacy
self.populateSettings()
self.loadDisplayList()
}
func populateSettings() {
self.showAdvancedDisplays.state = prefs.bool(forKey: PrefKey.showAdvancedSettings.rawValue) ? .on : .off
}
override func viewWillAppear() {
@ -88,12 +92,12 @@ class DisplaysPrefsViewController: NSViewController, PreferencePane, NSTableView
var displayImage = "display.trianglebadge.exclamationmark"
var controlMethod = NSLocalizedString("No Control", comment: "Shown in the Display Preferences") + " ⚠️"
var controlStatus = NSLocalizedString("This display has an unspecified control status.", comment: "Shown in the Display Preferences")
if display.isVirtual {
if display.isVirtual, !display.isDummy {
displayType = NSLocalizedString("Virtual Display", comment: "Shown in the Display Preferences")
displayImage = "tv.and.mediabox"
controlMethod = NSLocalizedString("Software (shade)", comment: "Shown in the Display Preferences") + " ⚠️"
controlStatus = NSLocalizedString("This is a virtual display (examples: AirPlay, Sidecar, display connected via a DisplayLink Dock or similar) which does not allow hardware or software gammatable control. Shading is used as a substitute but only in non-mirror scenarios. Mouse cursor will be unaffected and artifacts may appear when entering/leaving full screen mode.", comment: "Shown in the Display Preferences")
} else if display is OtherDisplay {
} else if display is OtherDisplay, !display.isDummy {
displayType = NSLocalizedString("External Display", comment: "Shown in the Display Preferences")
displayImage = "display"
if let otherDisplay: OtherDisplay = display as? OtherDisplay {
@ -119,7 +123,7 @@ class DisplaysPrefsViewController: NSViewController, PreferencePane, NSTableView
}
}
}
} else if let appleDisplay: AppleDisplay = display as? AppleDisplay {
} else if !display.isDummy, let appleDisplay: AppleDisplay = display as? AppleDisplay {
if appleDisplay.isBuiltIn() {
displayType = NSLocalizedString("Built-in Display", comment: "Shown in the Display Preferences")
if self.isImac() {

View file

@ -152,6 +152,7 @@ class MainPrefsViewController: NSViewController, PreferencePane {
self.populateSettings()
menuslidersPrefsVc?.populateSettings()
keyboardPrefsVc?.populateSettings()
displaysPrefsVc?.populateSettings()
}
}

View file

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>6828</string>
<string>6850</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSBackgroundOnly</key>