improve volume/mute handling and fix OSD/slider#1
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
| slider.integerValue = Int(currentValue) | ||
| slider.maxValue = Double(maxValue) | ||
| display.saveValue(Int(muteValues!.current), for: command) | ||
| display.saveMaxValue(Int(muteValues!.max), for: command) |
There was a problem hiding this comment.
Mute polling overwrites volume metadata
High Severity
When handling .audioSpeakerVolume, the mute polling result is saved using for: command instead of for: .audioMuteScreenBlank. This writes mute current/max into the volume keys, corrupting stored volume state and max range. Subsequent volume logic that reads getMaxValue(.audioSpeakerVolume) can behave incorrectly.
| if self.cmd == .audioSpeakerVolume, (self.display.isMuted() && value > 0) || (!self.display.isMuted() && value == 0) { | ||
| self.display.toggleMute(fromVolumeSlider: true) | ||
| } | ||
|
|
There was a problem hiding this comment.
Unmute slider can restore wrong volume
Medium Severity
When the volume slider moves from muted to a non-zero value, toggleMute(fromVolumeSlider: true) restores the previously saved volume asynchronously, then the slider writes the new value separately. These two writes can race, so the final monitor volume may end up at the old restored value instead of the selected slider value.


Note
Medium Risk
Changes core brightness/volume/mute control logic and DDC command sequencing, which may behave differently across monitor models and could regress OSD/slider synchronization.
Overview
Improves external display volume/mute handling by basing mute state on the DDC
audioMuteScreenBlankvalue (with detection for monitors that don’t support the mute command) and by synchronizing mute/volume updates between media keys, sliders, saved prefs, and the on-screen display.Refactors brightness/volume step calculations to better match macOS OSD “chiclet” behavior (including small-increment steps) and updates OSD rendering to use raw values/max values rather than derived step counts. DDC polling logic is centralized into
Display.readDDCValues, and volume slider initialization now also polls mute state to show0when muted.Written by Cursor Bugbot for commit 7a9264d. This will update automatically on new commits. Configure here.