Quarter brightness steps with Option+Shift, and Swift 6 language mode - #172
Merged
Merged
Conversation
macOS moves the built-in a quarter of a stop while Option and Shift are held, and Crisp's keys moved a whole stop whatever was held. The same quarter step now reaches every display Crisp drives, and the built-in under the pointer still passes through to macOS, which does it itself. A bound shortcut keeps the whole stop, since it has no modifiers of its own to read. The pointer path steps through adjustDisplays like the other modes now, so the grid is picked in one place instead of two. Idea from #166.
The bezel fills in proportion to filled over total, not in whole chiclets, measured with a probe on 14.8.7 and 15.7.7. The fixed total of sixteen therefore kept three of every four quarter presses off the bar. Sixty-four units, four to a chiclet, put the fill edge where the press lands, and the bezel still draws its sixteen segments. Crisp's own banner on macOS 26 already fills continuously, so it needed nothing.
The dev loop, the Xcode build, the release script and CI all compiled with -swift-version 5 and minimal strict concurrency, so none of the concurrency rules this code is written against were actually enforced. Every build path now uses -swift-version 6 and the SWIFT_STRICT_CONCURRENCY overrides are gone. What that turned up, all of it real: - The retry and watchdog timers in BrightnessKeyService, and the repeat timer in HotkeyService, handed the timer itself to a main-actor block. It stays in the callback now, where the run loop put it. - CGHelpers guarded its resume flag with a lock over a captured var, which reads as a race whatever the lock does. The flag lives in a small class instead. - DDCService's async completions run on a per-display queue, so they are @sendable. - UpdateService is main-actor isolated, which is what Sparkle's standard user driver already asked of it, and the conformance says so. - DDCOperationQueuePool.Hold and CGDisplayMode now state what they are: immutable or lock-guarded state that more than one queue reads. - FrameSpring is main-actor, because a CADisplayLink made from a view ticks there. - The Accessibility prompt key is named outright. The Command Line Tools SDK exposes it as a global var, which Swift 6 reads as shared mutable state. docs/BUILDING.md carried the old flags too.
This is the tool that settled how the macOS 14 and 15 bezel draws a value that is not a whole chiclet. It asks OSDUIHelper for a given filled/total pair, which is how the proportional fill showed up, and that is why BrightnessHUDService passes 64 totals. Kept because the next question about that bezel would need it again.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
macOS moves the built-in a quarter of a stop while Option and Shift are held. Crisp now moves the displays it drives the same way, so an external gets the same 64 steps, and a built-in under the pointer still passes through to macOS. No new setting: the people who know the shortcut will use it, and the people who do not are unaffected.
The OSD bezel on macOS 14 and 15 fills in proportion to filled over total, not in whole chiclets. I measured that on 14.8.7 and 15.7.7, so the bezel now gets 64 units instead of 16. It still draws sixteen segments, and only the fill edge moves in quarters. macOS 26 draws Crisp's own capsule and needed no change.
Verified on the desk: a plain press moves a full stop, Option+Shift moves a quarter of one. An external sat at 100 and one fine press down took it to 98.4375, exactly a quarter of a 6.25 stop. The unit tests cover the arithmetic, including the rounded value an external reports back over DDC.
The last commit moves every build path to Swift 6 language mode. The dev loop, the Xcode build, the release script and CI all compiled with -swift-version 5 and minimal strict concurrency, so none of the concurrency rules this code is written against were enforced. Twelve files needed a fix, and every one is a real isolation crossing: three timers that handed the timer itself into a main-actor block, a resume flag guarded by a lock over a captured var, the DDC completions that cross onto a per-display queue, Sparkle's delegate conformance, and a display link that ticks on the main actor.
The probe I measured that with is in the last commit, in
scripts/next to the other hardware probes.The quarter-step idea came from #166.