Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Address review feedback on concurrency and DDC fixes
- Drop DispatchQueue.main.sync around CGSetDisplayTransferByTable in the
  smooth-brightness loop. CoreGraphics does not require the main thread
  here, and hopping per gamma step (~200 iterations) both stalled the
  animation and contended with main-thread UI work.
- Address the global preferences domain via UserDefaults.globalDomain
  instead of the literal ".GlobalPreferences", which is a filename and
  not a CFPreferences application ID. The old form returned nil, so the
  volume-changed beep silently never played.
- Restore the original DDC attempt count. The retry cap regressed the
  default from 5 attempts to 4 (and minimal polling from 2 to 1); it is
  now min(attempts + 1, 30), preserving prior behaviour under the cap.
- Migrate the login-item status read in MainPrefsViewController to
  SMAppService.loginItem(_:).status on macOS 13+. The writer had moved to
  SMAppService while the reader still used SMCopyAllJobDictionaries, so
  the Start at login checkbox showed stale state.
- Track DDC write success across every attempted control code rather than
  letting the last iteration win, so writeDDCLastSavedValue and isTouched
  are persisted only when all attempted writes actually succeeded.

kIOMainPortDefault is intentionally changed only in Arm64DDC, where it is
guarded by an availability check. The remaining call sites stay on
kIOMasterPortDefault because the project's deployment target predates
macOS 12.
  • Loading branch information
MyronKoch committed Sep 21, 2026
commit 5afd2153ca0ab1885dff2123dc674e29c94f720b
4 changes: 1 addition & 3 deletions MonitorControl/Model/Display.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,7 @@ class Display: Equatable {
let gammaTableRed = self.defaultGammaTableRed.map { $0 * transientValue }
let gammaTableGreen = self.defaultGammaTableGreen.map { $0 * transientValue }
let gammaTableBlue = self.defaultGammaTableBlue.map { $0 * transientValue }
DispatchQueue.main.sync {
CGSetDisplayTransferByTable(self.identifier, self.defaultGammaTableSampleCount, gammaTableRed, gammaTableGreen, gammaTableBlue)
}
CGSetDisplayTransferByTable(self.identifier, self.defaultGammaTableSampleCount, gammaTableRed, gammaTableGreen, gammaTableBlue)
}
Thread.sleep(forTimeInterval: 0.001) // Let's make things quick if not performed in the background
}
Expand Down
15 changes: 8 additions & 7 deletions MonitorControl/Model/OtherDisplay.swift
Original file line number Diff line number Diff line change
Expand Up @@ -401,24 +401,25 @@ class OtherDisplay: Display {
controlCodes.append(command.rawValue)
}
var writeAttempted = false
var writeSucceeded = true
var allSucceeded = true
for controlCode in controlCodes {
if Arm64DDC.isArm64 {
if self.arm64ddc {
writeAttempted = true
writeSucceeded = Arm64DDC.write(service: self.arm64avService, command: controlCode, value: value)
if !Arm64DDC.write(service: self.arm64avService, command: controlCode, value: value) {
allSucceeded = false
}
}
} else {
if self.ddc != nil {
writeAttempted = true
writeSucceeded = self.ddc?.write(command: controlCode, value: value, errorRecoveryWaitTime: 2000) ?? false
if !(self.ddc?.write(command: controlCode, value: value, errorRecoveryWaitTime: 2000) ?? false) {
allSucceeded = false
}
}
}
if writeAttempted, !writeSucceeded {
break
}
}
if writeAttempted, writeSucceeded {
if writeAttempted, allSucceeded {
self.writeDDCQueue.async(flags: .barrier) {
self.writeDDCLastSavedValue[command] = value
self.savePref(true, key: PrefKey.isTouched, for: command)
Expand Down
2 changes: 1 addition & 1 deletion MonitorControl/Support/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}

func getSystemSettings() -> [String: Any]? {
UserDefaults.standard.persistentDomain(forName: ".GlobalPreferences")
UserDefaults.standard.persistentDomain(forName: UserDefaults.globalDomain)
}
Comment on lines +362 to 364

func macOS10() -> Bool {
Expand Down
2 changes: 1 addition & 1 deletion MonitorControl/Support/Arm64DDC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class Arm64DDC: NSObject {
}
var packet: [UInt8] = [UInt8(0x80 | (send.count + 1)), UInt8(send.count)] + send + [0] // Note: the last byte is the place of the checksum, see next line!
packet[packet.count - 1] = self.checksum(chk: send.count == 1 ? ARM64_DDC_7BIT_ADDRESS << 1 : ARM64_DDC_7BIT_ADDRESS << 1 ^ dataAddress, data: &packet, start: 0, end: packet.count - 2)
let attempts = max(1, Int(min(numOfRetryAttemps ?? 4, UInt8(30))))
let attempts = min(Int(numOfRetryAttemps ?? 4) + 1, 30)
for _ in 0 ..< attempts {
for _ in 1 ... max((numOfWriteCycles ?? 2) + 0, 1) {
usleep(writeSleepTime ?? 10000)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,13 @@ class MainPrefsViewController: NSViewController, SettingsPane {

@available(macOS, deprecated: 10.10)
func populateSettings() {
// This is marked as deprectated but according to the function header it still does not have a replacement as of macOS 12 Monterey and is valid to use.
let startAtLogin = (SMCopyAllJobDictionaries(kSMDomainUserLaunchd).takeRetainedValue() as? [[String: AnyObject]])?.first { $0["Label"] as? String == "\(Bundle.main.bundleIdentifier!)Helper" }?["OnDemand"] as? Bool ?? false
let startAtLogin: Bool
let helperID = "\(Bundle.main.bundleIdentifier!)Helper"
if #available(macOS 13.0, *) {
startAtLogin = SMAppService.loginItem(identifier: helperID).status == .enabled
} else {
startAtLogin = (SMCopyAllJobDictionaries(kSMDomainUserLaunchd).takeRetainedValue() as? [[String: AnyObject]])?.first { $0["Label"] as? String == helperID }?["OnDemand"] as? Bool ?? false
}
self.startAtLogin.state = startAtLogin ? .on : .off
self.automaticUpdateCheck.state = prefs.bool(forKey: PrefKey.SUEnableAutomaticChecks.rawValue) ? .on : .off
self.combinedBrightness.state = prefs.bool(forKey: PrefKey.disableCombinedBrightness.rawValue) ? .off : .on
Expand Down