From c17ca676bdf31540be3cc6ef50ea65a74194d286 Mon Sep 17 00:00:00 2001 From: waydabber <37590873+waydabber@users.noreply.github.com> Date: Sat, 14 Aug 2021 15:33:28 +0200 Subject: [PATCH] Tweaks here and there, fixing bugs. --- MonitorControl/AppDelegate.swift | 42 ++++++------------- .../Extensions/NSNotification+Extension.swift | 3 -- MonitorControl/Info.plist | 2 +- MonitorControl/Manager/DisplayManager.swift | 12 +++--- MonitorControl/Model/Display.swift | 40 +++++++++++------- MonitorControl/Model/ExternalDisplay.swift | 4 +- MonitorControl/Support/Utils.swift | 2 +- .../MainPrefsViewController.swift | 13 ++---- MonitorControlHelper/Info.plist | 2 +- 9 files changed, 53 insertions(+), 67 deletions(-) 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