Skip to content

Commit 6248d58

Browse files
authored
Some additional fixes (MonitorControl#738)
- Fix naming of wakeNotification() - Fix for failing to update Advanced Settings checkbox on Preferences Reset. - Better handling of known dummy displays.
1 parent 5d3d08d commit 6248d58

File tree

10 files changed

+70
-26
lines changed

10 files changed

+70
-26
lines changed

MonitorControl/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundleShortVersionString</key>
2020
<string>$(MARKETING_VERSION)</string>
2121
<key>CFBundleVersion</key>
22-
<string>6828</string>
22+
<string>6850</string>
2323
<key>LSApplicationCategoryType</key>
2424
<string>public.app-category.utilities</string>
2525
<key>LSMinimumSystemVersion</key>

MonitorControl/Model/AppleDisplay.swift

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,34 @@ import os.log
66
class AppleDisplay: Display {
77
private var displayQueue: DispatchQueue
88

9-
override init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false) {
9+
override init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false, isDummy: Bool = false) {
1010
self.displayQueue = DispatchQueue(label: String("displayQueue-\(identifier)"))
11-
super.init(identifier, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual)
11+
super.init(identifier, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual, isDummy: isDummy)
1212
}
1313

1414
public func getAppleBrightness() -> Float {
15+
guard !self.isDummy else {
16+
return 1
17+
}
1518
var brightness: Float = 0
1619
DisplayServicesGetBrightness(self.identifier, &brightness)
1720
return brightness
1821
}
1922

2023
public func setAppleBrightness(value: Float) {
24+
guard !self.isDummy else {
25+
return
26+
}
2127
self.displayQueue.sync {
2228
DisplayServicesSetBrightness(self.identifier, value)
2329
DisplayServicesBrightnessChanged(self.identifier, Double(value))
2430
}
2531
}
2632

2733
override func setDirectBrightness(_ to: Float, transient: Bool = false) -> Bool {
34+
guard !self.isDummy else {
35+
return false
36+
}
2837
let value = max(min(to, 1), 0)
2938
self.setAppleBrightness(value: value)
3039
if !transient {
@@ -36,6 +45,9 @@ class AppleDisplay: Display {
3645
}
3746

3847
override func getBrightness() -> Float {
48+
guard !self.isDummy else {
49+
return 1
50+
}
3951
if self.prefExists(for: .brightness) {
4052
return self.readPrefAsFloat(for: .brightness)
4153
} else {

MonitorControl/Model/Display.swift

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class Display: Equatable {
2222
var sliderHandler: [Command: SliderHandler] = [:]
2323
var brightnessSyncSourceValue: Float = 1
2424
var isVirtual: Bool = false
25+
var isDummy: Bool = false
2526

2627
var defaultGammaTableRed = [CGGammaValue](repeating: 0, count: 256)
2728
var defaultGammaTableGreen = [CGGammaValue](repeating: 0, count: 256)
@@ -61,21 +62,22 @@ class Display: Equatable {
6162
return (key ?? PrefKey.value).rawValue + (command != nil ? String((command ?? Command.none).rawValue) : "") + self.prefsId
6263
}
6364

64-
internal init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false) {
65+
internal init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false, isDummy: Bool = false) {
6566
self.identifier = identifier
6667
self.name = name
6768
self.vendorNumber = vendorNumber
6869
self.modelNumber = modelNumber
6970
self.prefsId = "(" + String(name.filter { !$0.isWhitespace }) + String(vendorNumber ?? 0) + String(modelNumber ?? 0) + "@" + String(identifier) + ")"
7071
os_log("Display init with prefsIdentifier %{public}@", type: .info, self.prefsId)
7172
self.isVirtual = DEBUG_VIRTUAL ? true : isVirtual
73+
self.isDummy = isDummy
7274
self.swUpdateDefaultGammaTable()
7375
self.smoothBrightnessTransient = self.getBrightness()
74-
if self.isVirtual {
75-
os_log("Creating or updating shade for virtual display %{public}@", type: .info, String(self.identifier))
76+
if self.isVirtual || self.readPrefAsBool(key: PrefKey.avoidGamma), !self.isDummy {
77+
os_log("Creating or updating shade for display %{public}@", type: .info, String(self.identifier))
7678
_ = DisplayManager.shared.updateShade(displayID: self.identifier)
7779
} else {
78-
os_log("Destroying shade (if exists) for real display %{public}@", type: .info, String(self.identifier))
80+
os_log("Destroying shade (if exists) for display %{public}@", type: .info, String(self.identifier))
7981
_ = DisplayManager.shared.destroyShade(displayID: self.identifier)
8082
}
8183
self.brightnessSyncSourceValue = self.getBrightness()
@@ -187,6 +189,9 @@ class Display: Equatable {
187189
}
188190

189191
func swUpdateDefaultGammaTable() {
192+
guard !self.isDummy else {
193+
return
194+
}
190195
CGGetDisplayTransferByTable(self.identifier, 256, &self.defaultGammaTableRed, &self.defaultGammaTableGreen, &self.defaultGammaTableBlue, &self.defaultGammaTableSampleCount)
191196
let redPeak = self.defaultGammaTableRed.max() ?? 0
192197
let greenPeak = self.defaultGammaTableGreen.max() ?? 0
@@ -210,6 +215,10 @@ class Display: Equatable {
210215
if !noPrefSave {
211216
self.savePref(brightnessValue, key: .SwBrightness)
212217
}
218+
guard !self.isDummy else {
219+
self.swBrightnessSemaphore.signal()
220+
return true
221+
}
213222
var newValue = brightnessValue
214223
currentValue = self.swBrightnessTransform(value: currentValue)
215224
newValue = self.swBrightnessTransform(value: newValue)
@@ -249,6 +258,13 @@ class Display: Equatable {
249258
}
250259

251260
func getSwBrightness() -> Float {
261+
guard !self.isDummy else {
262+
if self.prefExists(key: .SwBrightness) {
263+
return self.readPrefAsFloat(key: .SwBrightness)
264+
} else {
265+
return 1
266+
}
267+
}
252268
self.swBrightnessSemaphore.wait()
253269
if self.isVirtual || self.readPrefAsBool(key: .avoidGamma) {
254270
let rawBrightnessValue = 1 - (DisplayManager.shared.getShadeAlpha(displayID: self.identifier) ?? 1)
@@ -274,7 +290,7 @@ class Display: Equatable {
274290

275291
func checkGammaInterference() {
276292
let currentSwBrightness = self.getSwBrightness()
277-
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 {
293+
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 {
278294
return
279295
}
280296
DisplayManager.shared.gammaInterferenceCounter += 1
@@ -309,7 +325,7 @@ class Display: Equatable {
309325
}
310326

311327
func isSwBrightnessNotDefault() -> Bool {
312-
guard !self.isVirtual else {
328+
guard !self.isVirtual, !self.isDummy else {
313329
return false
314330
}
315331
if self.getSwBrightness() < 1 {

MonitorControl/Model/OtherDisplay.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ class OtherDisplay: Display {
2323
set { prefs.set(newValue, forKey: PrefKey.pollingCount.rawValue + self.prefsId) }
2424
}
2525

26-
override init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false) {
27-
super.init(identifier, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual)
26+
override init(_ identifier: CGDirectDisplayID, name: String, vendorNumber: UInt32?, modelNumber: UInt32?, isVirtual: Bool = false, isDummy: Bool = false) {
27+
super.init(identifier, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual, isDummy: isDummy)
2828
if !isVirtual, !Arm64DDC.isArm64 {
2929
self.ddc = IntelDDC(for: identifier)
3030
}
@@ -256,7 +256,7 @@ class OtherDisplay: Display {
256256
}
257257

258258
func isSwOnly() -> Bool {
259-
return (!self.arm64ddc && self.ddc == nil) || self.isVirtual
259+
return (!self.arm64ddc && self.ddc == nil) || self.isVirtual || self.isDummy
260260
}
261261

262262
func isSw() -> Bool {

MonitorControl/Support/AppDelegate.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ class AppDelegate: NSObject, NSApplicationDelegate {
168168
NotificationCenter.default.addObserver(self, selector: #selector(self.audioDeviceChanged), name: Notification.Name.defaultOutputDeviceChanged, object: nil) // subscribe Audio output detector (SimplyCoreAudio)
169169
DistributedNotificationCenter.default.addObserver(self, selector: #selector(self.displayReconfigured), name: NSNotification.Name(rawValue: kColorSyncDisplayDeviceProfilesNotification.takeRetainedValue() as String), object: nil) // ColorSync change
170170
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.sleepNotification), name: NSWorkspace.screensDidSleepNotification, object: nil) // sleep and wake listeners
171-
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.wakeNotofication), name: NSWorkspace.screensDidWakeNotification, object: nil)
171+
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.wakeNotification), name: NSWorkspace.screensDidWakeNotification, object: nil)
172172
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.sleepNotification), name: NSWorkspace.willSleepNotification, object: nil)
173-
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.wakeNotofication), name: NSWorkspace.didWakeNotification, object: nil)
173+
NSWorkspace.shared.notificationCenter.addObserver(self, selector: #selector(self.wakeNotification), name: NSWorkspace.didWakeNotification, object: nil)
174174
_ = 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
175175
}
176176

@@ -179,7 +179,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
179179
os_log("Sleeping with sleep %{public}@", type: .info, String(self.sleepID))
180180
}
181181

182-
@objc private func wakeNotofication() {
182+
@objc private func wakeNotification() {
183183
if self.sleepID != 0 {
184184
os_log("Waking up from sleep %{public}@", type: .info, String(self.sleepID))
185185
let dispatchedSleepID = self.sleepID

MonitorControl/Support/Arm64DDC.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,10 @@ class Arm64DDC: NSObject {
271271
if ioregService.manufacturerID == "AOC", ioregService.productName == "28E850" {
272272
return true
273273
}
274+
// If the display contains the string "Dummy", then it is highly suspicious
275+
if ioregService.productName.contains("Dummy") || ioregService.productName.contains("dummy") {
276+
return true
277+
}
274278
// First service location of Mac Mini HDMI is broken for DDC communication
275279
if ioregService.transportDownstream == "HDMI", ioregService.serviceLocation == 1, modelIdentifier == "Macmini9,1" {
276280
return true

MonitorControl/Support/DisplayManager.swift

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,27 +151,34 @@ class DisplayManager {
151151
return
152152
}
153153
for onlineDisplayID in onlineDisplayIDs where onlineDisplayID != 0 {
154+
let rawName = DisplayManager.getDisplayRawNameByID(displayID: onlineDisplayID)
154155
let name = DisplayManager.getDisplayNameByID(displayID: onlineDisplayID)
155156
let id = onlineDisplayID
156157
let vendorNumber = CGDisplayVendorNumber(onlineDisplayID)
157158
let modelNumber = CGDisplayModelNumber(onlineDisplayID)
159+
var isDummy: Bool = false
158160
var isVirtual: Bool = false
161+
if rawName == "28E850" || rawName.lowercased().contains("dummy") {
162+
os_log("NOTE: Display is a dummy!", type: .info)
163+
isDummy = true
164+
}
159165
if !DEBUG_MACOS10, #available(macOS 11.0, *) {
160166
if let dictionary = ((CoreDisplay_DisplayCreateInfoDictionary(onlineDisplayID))?.takeRetainedValue() as NSDictionary?) {
161167
let isVirtualDevice = dictionary["kCGDisplayIsVirtualDevice"] as? Bool
162168
let displayIsAirplay = dictionary["kCGDisplayIsAirPlay"] as? Bool
163169
if isVirtualDevice ?? displayIsAirplay ?? false {
170+
os_log("NOTE: Display is virtual!", type: .info)
164171
isVirtual = true
165172
}
166173
}
167174
}
168175
if !DEBUG_SW, DisplayManager.isAppleDisplay(displayID: onlineDisplayID) { // MARK: (point of interest for testing)
169-
let appleDisplay = AppleDisplay(id, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual)
170-
os_log("Apple display found - %{public}@", type: .info, "ID: \(appleDisplay.identifier) Name: \(appleDisplay.name) (Vendor: \(appleDisplay.vendorNumber ?? 0), Model: \(appleDisplay.modelNumber ?? 0))")
176+
let appleDisplay = AppleDisplay(id, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual, isDummy: isDummy)
177+
os_log("Apple display found - %{public}@", type: .info, "ID: \(appleDisplay.identifier), Name: \(appleDisplay.name) (Vendor: \(appleDisplay.vendorNumber ?? 0), Model: \(appleDisplay.modelNumber ?? 0))")
171178
self.addDisplay(display: appleDisplay)
172179
} else {
173-
let otherDisplay = OtherDisplay(id, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual)
174-
os_log("Other display found - %{public}@", type: .info, "ID: \(otherDisplay.identifier) Name: \(otherDisplay.name) (Vendor: \(otherDisplay.vendorNumber ?? 0), Model: \(otherDisplay.modelNumber ?? 0))")
180+
let otherDisplay = OtherDisplay(id, name: name, vendorNumber: vendorNumber, modelNumber: modelNumber, isVirtual: isVirtual, isDummy: isDummy)
181+
os_log("Other display found - %{public}@", type: .info, "ID: \(otherDisplay.identifier), Name: \(otherDisplay.name) (Vendor: \(otherDisplay.vendorNumber ?? 0), Model: \(otherDisplay.modelNumber ?? 0))")
175182
self.addDisplay(display: otherDisplay)
176183
}
177184
}
@@ -351,7 +358,7 @@ class DisplayManager {
351358
}
352359
}
353360

354-
func getAffectedDisplays(isBrightness: Bool = false, isVolume: Bool = false, isContrast _: Bool = false) -> [Display]? {
361+
func getAffectedDisplays(isBrightness: Bool = false, isVolume: Bool = false) -> [Display]? {
355362
var affectedDisplays: [Display]
356363
let allDisplays = self.getAllDisplays()
357364
var currentDisplay: Display?

MonitorControl/View Controllers/DisplaysPrefsViewController.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,13 @@ class DisplaysPrefsViewController: NSViewController, PreferencePane, NSTableView
2525

2626
override func viewDidLoad() {
2727
super.viewDidLoad()
28-
self.showAdvancedDisplays.state = prefs.bool(forKey: PrefKey.showAdvancedSettings.rawValue) ? .on : .off
29-
self.loadDisplayList()
3028
self.displayScrollView.scrollerStyle = .legacy
29+
self.populateSettings()
30+
self.loadDisplayList()
31+
}
32+
33+
func populateSettings() {
34+
self.showAdvancedDisplays.state = prefs.bool(forKey: PrefKey.showAdvancedSettings.rawValue) ? .on : .off
3135
}
3236

3337
override func viewWillAppear() {
@@ -88,12 +92,12 @@ class DisplaysPrefsViewController: NSViewController, PreferencePane, NSTableView
8892
var displayImage = "display.trianglebadge.exclamationmark"
8993
var controlMethod = NSLocalizedString("No Control", comment: "Shown in the Display Preferences") + " ⚠️"
9094
var controlStatus = NSLocalizedString("This display has an unspecified control status.", comment: "Shown in the Display Preferences")
91-
if display.isVirtual {
95+
if display.isVirtual, !display.isDummy {
9296
displayType = NSLocalizedString("Virtual Display", comment: "Shown in the Display Preferences")
9397
displayImage = "tv.and.mediabox"
9498
controlMethod = NSLocalizedString("Software (shade)", comment: "Shown in the Display Preferences") + " ⚠️"
9599
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")
96-
} else if display is OtherDisplay {
100+
} else if display is OtherDisplay, !display.isDummy {
97101
displayType = NSLocalizedString("External Display", comment: "Shown in the Display Preferences")
98102
displayImage = "display"
99103
if let otherDisplay: OtherDisplay = display as? OtherDisplay {
@@ -119,7 +123,7 @@ class DisplaysPrefsViewController: NSViewController, PreferencePane, NSTableView
119123
}
120124
}
121125
}
122-
} else if let appleDisplay: AppleDisplay = display as? AppleDisplay {
126+
} else if !display.isDummy, let appleDisplay: AppleDisplay = display as? AppleDisplay {
123127
if appleDisplay.isBuiltIn() {
124128
displayType = NSLocalizedString("Built-in Display", comment: "Shown in the Display Preferences")
125129
if self.isImac() {

MonitorControl/View Controllers/MainPrefsViewController.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ class MainPrefsViewController: NSViewController, PreferencePane {
152152
self.populateSettings()
153153
menuslidersPrefsVc?.populateSettings()
154154
keyboardPrefsVc?.populateSettings()
155+
displaysPrefsVc?.populateSettings()
155156
}
156157
}
157158

MonitorControlHelper/Info.plist

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<key>CFBundleShortVersionString</key>
2020
<string>$(MARKETING_VERSION)</string>
2121
<key>CFBundleVersion</key>
22-
<string>6828</string>
22+
<string>6850</string>
2323
<key>LSApplicationCategoryType</key>
2424
<string>public.app-category.utilities</string>
2525
<key>LSBackgroundOnly</key>

0 commit comments

Comments
 (0)