[GH-ISSUE #1911] Brightness sync never resumes after display/system sleep on Intel Macs (soberNow doesn't restart job) #1312

Open
opened 2026-10-02 22:07:24 -06:00 by gitea-mirror · 1 comment
Owner

Originally created by @LuisMa9L on GitHub (Sep 22, 2026).
Original GitHub issue: https://github.com/MonitorControl/MonitorControl/issues/1911

Before opening the issue, have you...?

  • Searched for existing issues
  • Looked through the wiki
  • Updated MonitorControl to the latest version (if applicable)

Describe the bug

On an Intel Mac, "Sync brightness changes from built-in display" works after launch, but stops for good after the first display sleep or system sleep. The app keeps running and keyboard brightness control still works, yet ambient light sensor changes are no longer synced to the external display until MonitorControl is relaunched. Same symptom as #922 and #1372 (both closed); still present in v4.4.0 and on main.

Cause (from reading the v4.4.0 source, AppDelegate.swift): sleepNotification() increments sleepID, so the next job() tick exits ("MonitorControl job died because of sleep or reconfiguration."). On wake, soberNow() only restarts the job in two cases:

if self.reconfigureID != 0 {
  self.configure(dispatchedReconfigureID: dispatchedReconfigureID) // ends with job(start: true)
} else if Arm64DDC.isArm64 {
  DisplayManager.shared.updateArm64AVServices()
  self.job(start: true)
}

On Intel, when no display reconfiguration happened during sleep, neither branch runs, so job() is never restarted.

Suggested fix: restart the job regardless of architecture. job(start:) already guards against a second loop via jobRunning.

} else {
  if Arm64DDC.isArm64 {
    os_log("Displays don't need reconfig after sober but might need AVServices update", type: .info)
    DisplayManager.shared.updateArm64AVServices()
  }
  self.job(start: true)
}

Workaround: relaunching MonitorControl a few seconds after NSWorkspace.screensDidWakeNotification / didWakeNotification (I use a small LaunchAgent) restores sync.

Side note, possibly a separate issue: with smooth brightness transitions enabled and combined hardware/software dimming, I got the "Is f.lux or similar running?" alert right after a relaunch. From the code, restoreSwBrightnessForAllDisplays(async: true) animates the gamma in the background while the first job() tick calls OtherDisplay.setBrightness() -> checkGammaInterference(), which can read the half-animated gamma table as interference (and resets software brightness to 1). With smooth transitions disabled it didn't happen again in my tests.

Steps to reproduce

  1. On an Intel Mac with a built-in display (ambient light sensor) and an external DDC display, enable "Sync brightness changes from built-in display" (combined dimming on, startup action "Apply last saved values").
  2. Launch MonitorControl and cover the ambient light sensor: the external display follows.
  3. Put the displays to sleep (pmset displaysleepnow), wait a few seconds, wake them.
  4. Cover the sensor again: the external display no longer follows.
  5. Relaunch MonitorControl: sync works again until the next sleep.

Log captured with /usr/bin/log stream --info --predicate 'process == "MonitorControl"' during step 3:

12:46:54  Sleeping with sleep 1
12:46:55  MonitorControl job died because of sleep or reconfiguration.
12:47:14  Waking up from sleep 1
12:47:17  Sober from sleep 1

No "MonitorControl job started." follows. In earlier runs, sync stayed dead for 20+ minutes until a manual relaunch.

Expected behavior

After waking, brightness sync resumes automatically, as the Apple Silicon branch of soberNow() already does, without relaunching the app.

Anything else?

No response

Environment Information (please complete the following information)

- macOS version: 13.7.8 Ventura
- Mac model: iMac (Retina 4K, 21.5-inch, 2017), Intel Core i5-7500
- MonitorControl version: v4.4.0
- Monitor(s): Gigabyte G27F 2 (via USB-C to HDMI adapter)
- Apple Silicon/M1 (yes or no): no
Originally created by @LuisMa9L on GitHub (Sep 22, 2026). Original GitHub issue: https://github.com/MonitorControl/MonitorControl/issues/1911 ### Before opening the issue, have you...? - [x] Searched for existing issues - [x] Looked through [the wiki](https://github.com/MonitorControl/MonitorControl/wiki) - [x] Updated MonitorControl to the latest version (if applicable) ### Describe the bug On an Intel Mac, "Sync brightness changes from built-in display" works after launch, but stops for good after the first display sleep or system sleep. The app keeps running and keyboard brightness control still works, yet ambient light sensor changes are no longer synced to the external display until MonitorControl is relaunched. Same symptom as #922 and #1372 (both closed); still present in v4.4.0 and on `main`. **Cause (from reading the v4.4.0 source, `AppDelegate.swift`):** `sleepNotification()` increments `sleepID`, so the next `job()` tick exits ("MonitorControl job died because of sleep or reconfiguration."). On wake, `soberNow()` only restarts the job in two cases: ```swift if self.reconfigureID != 0 { self.configure(dispatchedReconfigureID: dispatchedReconfigureID) // ends with job(start: true) } else if Arm64DDC.isArm64 { DisplayManager.shared.updateArm64AVServices() self.job(start: true) } ``` On Intel, when no display reconfiguration happened during sleep, neither branch runs, so `job()` is never restarted. **Suggested fix:** restart the job regardless of architecture. `job(start:)` already guards against a second loop via `jobRunning`. ```swift } else { if Arm64DDC.isArm64 { os_log("Displays don't need reconfig after sober but might need AVServices update", type: .info) DisplayManager.shared.updateArm64AVServices() } self.job(start: true) } ``` **Workaround:** relaunching MonitorControl a few seconds after `NSWorkspace.screensDidWakeNotification` / `didWakeNotification` (I use a small LaunchAgent) restores sync. **Side note, possibly a separate issue:** with smooth brightness transitions enabled and combined hardware/software dimming, I got the "Is f.lux or similar running?" alert right after a relaunch. From the code, `restoreSwBrightnessForAllDisplays(async: true)` animates the gamma in the background while the first `job()` tick calls `OtherDisplay.setBrightness()` -> `checkGammaInterference()`, which can read the half-animated gamma table as interference (and resets software brightness to 1). With smooth transitions disabled it didn't happen again in my tests. ### Steps to reproduce 1. On an Intel Mac with a built-in display (ambient light sensor) and an external DDC display, enable "Sync brightness changes from built-in display" (combined dimming on, startup action "Apply last saved values"). 2. Launch MonitorControl and cover the ambient light sensor: the external display follows. 3. Put the displays to sleep (`pmset displaysleepnow`), wait a few seconds, wake them. 4. Cover the sensor again: the external display no longer follows. 5. Relaunch MonitorControl: sync works again until the next sleep. Log captured with `/usr/bin/log stream --info --predicate 'process == "MonitorControl"'` during step 3: ``` 12:46:54 Sleeping with sleep 1 12:46:55 MonitorControl job died because of sleep or reconfiguration. 12:47:14 Waking up from sleep 1 12:47:17 Sober from sleep 1 ``` No "MonitorControl job started." follows. In earlier runs, sync stayed dead for 20+ minutes until a manual relaunch. ### Expected behavior After waking, brightness sync resumes automatically, as the Apple Silicon branch of `soberNow()` already does, without relaunching the app. ### Anything else? _No response_ ### Environment Information (please complete the following information) ```markdown - macOS version: 13.7.8 Ventura - Mac model: iMac (Retina 4K, 21.5-inch, 2017), Intel Core i5-7500 - MonitorControl version: v4.4.0 - Monitor(s): Gigabyte G27F 2 (via USB-C to HDMI adapter) - Apple Silicon/M1 (yes or no): no ```
Author
Owner

@Blizzeq commented on GitHub (Sep 24, 2026):

Thanks for tracing this. I opened #1915 with the fix you suggested.

<!-- gh-comment-id:5810466861 --> @Blizzeq commented on GitHub (Sep 24, 2026): Thanks for tracing this. I opened #1915 with the fix you suggested.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
github-starred/MonitorControl#1312
No description provided.