diff --git a/MonitorControl/AppDelegate.swift b/MonitorControl/AppDelegate.swift
index e61ae91..88077a9 100644
--- a/MonitorControl/AppDelegate.swift
+++ b/MonitorControl/AppDelegate.swift
@@ -84,7 +84,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}
- func clearDisplays() {
+ func clearMenu() {
if self.statusMenu.items.count > 2 {
var items: [NSMenuItem] = []
for i in 0 ..< self.statusMenu.items.count - 2 {
@@ -95,9 +95,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
self.statusMenu.removeItem(item)
}
}
-
self.monitorItems = []
- DisplayManager.shared.clearDisplays()
}
func updateArm64AVServices() {
@@ -135,7 +133,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
}
- func updateMenus(controllableExternalDisplays: [ExternalDisplay]) {
+ func updateMenus() {
+ self.clearMenu()
+ var controllableExternalDisplays: [ExternalDisplay] = []
+ if prefs.bool(forKey: Utils.PrefKeys.fallbackSw.rawValue) {
+ controllableExternalDisplays = DisplayManager.shared.getNonVirtualExternalDisplays()
+ } else {
+ controllableExternalDisplays = DisplayManager.shared.getDdcCapableDisplays()
+ }
if controllableExternalDisplays.count == 0 {
let item = NSMenuItem()
item.title = NSLocalizedString("No supported display found", comment: "Shown in menu")
@@ -161,7 +166,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
os_log("Request for updateDisplay with reconfigreID %{public}@", type: .info, String(dispatchedReconfigureID))
self.reconfigureID = 0
- self.clearDisplays()
+ DisplayManager.shared.clearDisplays()
var onlineDisplayIDs = [CGDirectDisplayID](repeating: 0, count: 10)
var displayCount: UInt32 = 0
guard CGGetOnlineDisplayList(10, &onlineDisplayIDs, &displayCount) == .success else {
@@ -195,18 +200,12 @@ class AppDelegate: NSObject, NSApplicationDelegate {
DisplayManager.shared.resetSwBrightnessForAllDisplays(settingsOnly: true)
} else {
if prefs.bool(forKey: Utils.PrefKeys.fallbackSw.rawValue) || prefs.bool(forKey: Utils.PrefKeys.lowerSwAfterBrightness.rawValue) {
- DisplayManager.shared.restoreSwBrightnessForAllDisplays()
+ DisplayManager.shared.restoreSwBrightnessForAllDisplays(async: true)
}
}
self.updateArm64AVServices()
NotificationCenter.default.post(name: Notification.Name(Utils.PrefKeys.displayListUpdate.rawValue), object: nil)
- var controllableExternalDisplays: [ExternalDisplay] = []
- if prefs.bool(forKey: Utils.PrefKeys.fallbackSw.rawValue) {
- controllableExternalDisplays = DisplayManager.shared.getNonVirtualExternalDisplays()
- } else {
- controllableExternalDisplays = DisplayManager.shared.getDdcCapableDisplays()
- }
- self.updateMenus(controllableExternalDisplays: controllableExternalDisplays)
+ self.updateMenus()
}
private func addDisplayToMenu(display: ExternalDisplay, asSubMenu: Bool) {
@@ -250,9 +249,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
private func subscribeEventListeners() {
NotificationCenter.default.addObserver(self, selector: #selector(handleListenForChanged), name: .listenFor, object: nil) // subscribe KeyTap event listeners
- NotificationCenter.default.addObserver(self, selector: #selector(handleShowContrastChanged), name: .showContrast, object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(handleShowVolumeChanged), name: .showVolume, object: nil)
- NotificationCenter.default.addObserver(self, selector: #selector(handleFallbackSwChanged), name: .fallbackSw, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handleFriendlyNameChanged), name: .friendlyName, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(handlePreferenceReset), name: .preferenceReset, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(audioDeviceChanged), name: Notification.Name.defaultOutputDeviceChanged, object: nil) // subscribe Audio output detector (SimplyCoreAudio)
@@ -423,20 +419,8 @@ extension AppDelegate: MediaKeyTapDelegate {
self.updateMediaKeyTap()
}
- @objc func handleShowContrastChanged() {
- self.updateDisplays()
- }
-
- @objc func handleShowVolumeChanged() {
- self.updateDisplays()
- }
-
- @objc func handleFallbackSwChanged() {
- self.updateDisplays()
- }
-
@objc func handleFriendlyNameChanged() {
- self.updateDisplays()
+ self.updateMenus()
}
@objc func handlePreferenceReset() {
diff --git a/MonitorControl/Extensions/NSNotification+Extension.swift b/MonitorControl/Extensions/NSNotification+Extension.swift
index d90a09b..94353ef 100644
--- a/MonitorControl/Extensions/NSNotification+Extension.swift
+++ b/MonitorControl/Extensions/NSNotification+Extension.swift
@@ -3,9 +3,6 @@ import Cocoa
extension NSNotification.Name {
static let accessibilityApi = NSNotification.Name(rawValue: "com.apple.accessibility.api")
static let listenFor = NSNotification.Name(rawValue: Utils.PrefKeys.listenFor.rawValue)
- static let showContrast = NSNotification.Name(rawValue: Utils.PrefKeys.showContrast.rawValue)
- static let showVolume = NSNotification.Name(rawValue: Utils.PrefKeys.showVolume.rawValue)
- static let fallbackSw = NSNotification.Name(rawValue: Utils.PrefKeys.fallbackSw.rawValue)
static let friendlyName = NSNotification.Name(rawValue: Utils.PrefKeys.friendlyName.rawValue)
static let preferenceReset = NSNotification.Name(rawValue: Utils.PrefKeys.preferenceReset.rawValue)
static let displayListUpdate = NSNotification.Name(rawValue: Utils.PrefKeys.displayListUpdate.rawValue)
diff --git a/MonitorControl/Info.plist b/MonitorControl/Info.plist
index bed639f..6034beb 100644
--- a/MonitorControl/Info.plist
+++ b/MonitorControl/Info.plist
@@ -19,7 +19,7 @@
CFBundleShortVersionString
$(MARKETING_VERSION)
CFBundleVersion
- 2240
+ 2305
LSApplicationCategoryType
public.app-category.utilities
LSMinimumSystemVersion
diff --git a/MonitorControl/Manager/DisplayManager.swift b/MonitorControl/Manager/DisplayManager.swift
index f8c4f5b..34f16b2 100644
--- a/MonitorControl/Manager/DisplayManager.swift
+++ b/MonitorControl/Manager/DisplayManager.swift
@@ -71,10 +71,10 @@ class DisplayManager {
self.displays = []
}
- func resetSwBrightnessForAllDisplays(settingsOnly: Bool = false) {
+ func resetSwBrightnessForAllDisplays(settingsOnly: Bool = false, async: Bool = false) {
for externalDisplay in self.getNonVirtualExternalDisplays() {
if !settingsOnly {
- _ = externalDisplay.setSwBrightness(value: externalDisplay.getSwMaxBrightness())
+ _ = externalDisplay.setSwBrightness(value: externalDisplay.getSwMaxBrightness(), smooth: async)
} else {
externalDisplay.saveSwBirghtnessPrefValue(Int(externalDisplay.getSwMaxBrightness()))
}
@@ -84,12 +84,14 @@ class DisplayManager {
}
}
- func restoreSwBrightnessForAllDisplays() {
+ func restoreSwBrightnessForAllDisplays(async: Bool = false) {
for externalDisplay in self.getExternalDisplays() {
if externalDisplay.getValue(for: .brightness) == 0 || externalDisplay.isSw() {
- _ = externalDisplay.setSwBrightness(value: UInt8(externalDisplay.getSwBrightnessPrefValue()))
+ let savedPrefValue = externalDisplay.getSwBrightnessPrefValue()
+ externalDisplay.saveSwBirghtnessPrefValue(Int(externalDisplay.getSwBrightness()))
+ _ = externalDisplay.setSwBrightness(value: UInt8(savedPrefValue), smooth: async)
} else {
- _ = externalDisplay.setSwBrightness(value: externalDisplay.getSwMaxBrightness())
+ _ = externalDisplay.setSwBrightness(value: externalDisplay.getSwMaxBrightness(), smooth: async)
}
}
}
diff --git a/MonitorControl/Model/Display.swift b/MonitorControl/Model/Display.swift
index 7e0a4da..fcb160e 100644
--- a/MonitorControl/Model/Display.swift
+++ b/MonitorControl/Model/Display.swift
@@ -93,28 +93,36 @@ class Display {
}
}
- func setSwBrightness(value: UInt8, fast _: Bool = false) -> Bool {
+ let swBrightnessSemaphore = DispatchSemaphore(value: 1)
+ func setSwBrightness(value: UInt8, smooth: Bool = false) -> Bool {
let brightnessValue: UInt8 = min(getSwMaxBrightness(), value)
- var currentValue = Float(self.getSwBrightness()) / Float(self.getSwMaxBrightness())
-// var currentValue = Float(self.getSwBrightnessPrefValue()) / Float(self.getSwMaxBrightness()) // Better for async version but is not right after display reconfiguration
+ var currentValue = Float(self.getSwBrightnessPrefValue()) / Float(self.getSwMaxBrightness())
self.saveSwBirghtnessPrefValue(Int(brightnessValue))
var newValue = Float(Float(brightnessValue)) / Float(self.getSwMaxBrightness())
currentValue = self.swBrightnessTransform(value: currentValue)
newValue = self.swBrightnessTransform(value: newValue)
os_log("setting software brightness to: %{public}@", type: .debug, String(newValue))
- let gammaTableRed = self.defaultGammaTableRed.map { $0 * /* transientValue */ newValue }
- let gammaTableGreen = self.defaultGammaTableGreen.map { $0 * /* transientValue */ newValue }
- let gammaTableBlue = self.defaultGammaTableBlue.map { $0 * /* transientValue */ newValue }
- CGSetDisplayTransferByTable(self.identifier, self.defaultGammaTableSampleCount, gammaTableRed, gammaTableGreen, gammaTableBlue)
-// DispatchQueue.global(qos: .userInitiated).async {
-// for transientValue in stride(from: currentValue, to: newValue, by: 0.0025 * (currentValue > newValue ? -1 : 1)) {
-// let gammaTableRed = self.defaultGammaTableRed.map { $0 * transientValue }
-// let gammaTableGreen = self.defaultGammaTableGreen.map { $0 * transientValue }
-// let gammaTableBlue = self.defaultGammaTableBlue.map { $0 * transientValue }
-// CGSetDisplayTransferByTable(self.identifier, self.defaultGammaTableSampleCount, gammaTableRed, gammaTableGreen, gammaTableBlue)
-// Thread.sleep(forTimeInterval: 0.0005) // This will make things a bit nicer and mimic delay of DDC communication for consistency
-// }
-// }
+ if smooth {
+ DispatchQueue.global(qos: .userInteractive).async {
+ self.swBrightnessSemaphore.wait()
+ for transientValue in stride(from: currentValue, to: newValue, by: 0.0025 * (currentValue > newValue ? -1 : 1)) {
+ let gammaTableRed = self.defaultGammaTableRed.map { $0 * transientValue }
+ let gammaTableGreen = self.defaultGammaTableGreen.map { $0 * transientValue }
+ let gammaTableBlue = self.defaultGammaTableBlue.map { $0 * transientValue }
+ guard app.reconfigureID == 0 else {
+ return
+ }
+ CGSetDisplayTransferByTable(self.identifier, self.defaultGammaTableSampleCount, gammaTableRed, gammaTableGreen, gammaTableBlue)
+ Thread.sleep(forTimeInterval: 0.001) // Let's make things quick if not performed in the background
+ }
+ self.swBrightnessSemaphore.signal()
+ }
+ } else {
+ let gammaTableRed = self.defaultGammaTableRed.map { $0 * /* transientValue */ newValue }
+ let gammaTableGreen = self.defaultGammaTableGreen.map { $0 * /* transientValue */ newValue }
+ let gammaTableBlue = self.defaultGammaTableBlue.map { $0 * /* transientValue */ newValue }
+ CGSetDisplayTransferByTable(self.identifier, self.defaultGammaTableSampleCount, gammaTableRed, gammaTableGreen, gammaTableBlue)
+ }
return true
}
diff --git a/MonitorControl/Model/ExternalDisplay.swift b/MonitorControl/Model/ExternalDisplay.swift
index 6e78dc9..b4e57a4 100644
--- a/MonitorControl/Model/ExternalDisplay.swift
+++ b/MonitorControl/Model/ExternalDisplay.swift
@@ -168,7 +168,7 @@ class ExternalDisplay: Display {
let isAlreadySet = osdValue == self.getValue(for: .brightness)
if self.isSw(), self.prefs.bool(forKey: Utils.PrefKeys.fallbackSw.rawValue) {
- if self.setSwBrightness(value: UInt8(osdValue)) {
+ if self.setSwBrightness(value: UInt8(osdValue), smooth: true) {
self.showOsd(command: .brightness, value: osdValue, roundChiclet: !isSmallIncrement)
self.saveValue(osdValue, for: .brightness)
if let slider = brightnessSliderHandler?.slider {
@@ -192,7 +192,7 @@ class ExternalDisplay: Display {
swBirghtnessValue = Int(getSwMaxBrightness())
swAfterBirghtnessMode = false
}
- if self.setSwBrightness(value: UInt8(swBirghtnessValue), fast: true) {
+ if self.setSwBrightness(value: UInt8(swBirghtnessValue), smooth: true) {
self.showOsd(command: .brightness, value: self.getValue(for: .brightness), roundChiclet: !isSmallIncrement)
}
}
diff --git a/MonitorControl/Support/Utils.swift b/MonitorControl/Support/Utils.swift
index a89cb79..6c2e6f2 100644
--- a/MonitorControl/Support/Utils.swift
+++ b/MonitorControl/Support/Utils.swift
@@ -66,7 +66,7 @@ class Utils: NSObject {
var (currentValue, maxValue) = (UInt16(0), UInt16(0))
if display.isSw(), command == DDC.Command.brightness {
- (currentValue, maxValue) = (UInt16(display.getSwBrightness()), UInt16(display.getSwMaxBrightness()))
+ (currentValue, maxValue) = (UInt16(display.getSwBrightnessPrefValue()), UInt16(display.getSwMaxBrightness()))
} else {
if tries != 0 {
values = display.readDDCValues(for: command, tries: tries, minReplyDelay: delay)
diff --git a/MonitorControl/View Controllers/MainPrefsViewController.swift b/MonitorControl/View Controllers/MainPrefsViewController.swift
index fdd4bf6..20aecbf 100644
--- a/MonitorControl/View Controllers/MainPrefsViewController.swift
+++ b/MonitorControl/View Controllers/MainPrefsViewController.swift
@@ -89,12 +89,10 @@ class MainPrefsViewController: NSViewController, PreferencePane {
self.prefs.set(false, forKey: Utils.PrefKeys.showContrast.rawValue)
default: break
}
-
+ app.updateMenus()
#if DEBUG
os_log("Toggle show contrast slider state: %{public}@", type: .info, sender.state == .on ? "on" : "off")
#endif
-
- NotificationCenter.default.post(name: Notification.Name(Utils.PrefKeys.showContrast.rawValue), object: nil)
}
@IBAction func showVolumeSliderClicked(_ sender: NSButton) {
@@ -105,12 +103,10 @@ class MainPrefsViewController: NSViewController, PreferencePane {
self.prefs.set(false, forKey: Utils.PrefKeys.showVolume.rawValue)
default: break
}
-
+ app.updateMenus()
#if DEBUG
os_log("Toggle show volume slider state: %{public}@", type: .info, sender.state == .on ? "on" : "off")
#endif
-
- NotificationCenter.default.post(name: Notification.Name(Utils.PrefKeys.showVolume.rawValue), object: nil)
}
@IBAction func lowerSwAfterBrightnessClicked(_ sender: NSButton) {
@@ -133,14 +129,13 @@ class MainPrefsViewController: NSViewController, PreferencePane {
self.prefs.set(true, forKey: Utils.PrefKeys.fallbackSw.rawValue)
case .off:
self.prefs.set(false, forKey: Utils.PrefKeys.fallbackSw.rawValue)
- DisplayManager.shared.resetSwBrightnessForAllDisplays()
default: break
}
+ DisplayManager.shared.resetSwBrightnessForAllDisplays()
+ app.updateMenus()
#if DEBUG
os_log("Toggle fallback to software if no DDC: %{public}@", type: .info, sender.state == .on ? "on" : "off")
#endif
-
- NotificationCenter.default.post(name: Notification.Name(Utils.PrefKeys.fallbackSw.rawValue), object: nil)
}
@IBAction func listenForChanged(_ sender: NSPopUpButton) {
diff --git a/MonitorControlHelper/Info.plist b/MonitorControlHelper/Info.plist
index c659786..85a757f 100644
--- a/MonitorControlHelper/Info.plist
+++ b/MonitorControlHelper/Info.plist
@@ -19,7 +19,7 @@
CFBundleShortVersionString
$(MARKETING_VERSION)
CFBundleVersion
- 2240
+ 2305
LSApplicationCategoryType
public.app-category.utilities
LSBackgroundOnly