Repository navigation
Steadier scrolling on ProMotion; let the reader scroll up during live text; 0.16.6 - #21
Merged
Merged
Conversation
…oming in The live window scrolled to its end on every new word, and the Q&A on every token of an answer, several times a second, so scrolling up was undone at once and the page looked like it could not be scrolled. Both now follow the end only while the reader is at it: scrolling up stops following, getting back to the end resumes it, and asking a question follows the answer. macOS 14 cannot read a scroll view's position, so it follows as before. The live window's sentences are Equatable on what they show, so a word added to the line still being spoken no longer redraws every sentence on screen. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UP49VoRGBw2wv1CEAroky7
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UP49VoRGBw2wv1CEAroky7
On macOS 27 a ProMotion panel does not settle on one refresh rate while a SwiftUI view scrolls: it flips between 120 Hz and 60 Hz, each frame stays on screen for an unpredictable time, and every page judders, plain text included (FB24091347, Developer Forums thread 840214). The only confirmed workaround is setting the whole display to 60 Hz. An app can say which rate it wants: a display link with a preferred frame-rate range is that request. One now runs from the first scroll event until shortly after the last, momentum included, asking for 120 Hz, and pauses when the page stops. `defaults write com.beluga.classnote scrollFrameRate -int 60` asks for a steady 60 Hz instead and `0` turns it off, from the next launch, so the two can be compared without a new build. Version 0.16.6 (build 24). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UP49VoRGBw2wv1CEAroky7
belugaming
pushed a commit
that referenced
this pull request
Oct 9, 2026
The branch still carried #21's commits, which main has as a squash; this keeps the branch's files exactly as they were. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UP49VoRGBw2wv1CEAroky7
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.
Every scrolling page judders on a macOS 27 MacBook Pro (M5 Max), including the plain-text live translation window. Two changes address this.
Ask for a steady refresh rate while scrolling
On macOS 27, a ProMotion panel does not settle on one refresh rate while a SwiftUI view scrolls. It flips between 120 Hz and 60 Hz, so each frame stays on screen for an unpredictable time. Apple has the report (FB24091347, Developer Forums thread 840214) and has not shipped a fix. The only confirmed workaround is setting the whole display to 60 Hz, which is a system setting and not something to ask of users.
An app's way to say which rate it wants is a display link with a preferred frame-rate range.
ScrollFrameRate(inApp/ScrollFrameRate.swift) runs one from the first scroll event until 0.4 s after the last, momentum included. It asks for 120 Hz (range 80–120, preferred 120), and the link pauses when the page stops, so an idle window costs nothing.defaults write com.beluga.classnote scrollFrameRate -int 60asks for a steady 60 Hz instead, and0turns the request off. Either takes effect from the next launch, so the options can be compared on the affected Mac without a new build.Not yet verified on the affected hardware. CI builds and tests on macos-15 without a ProMotion panel. Whether macOS 27 honours the request for scrolling has to be checked on the M5 Max.
Let the reader scroll up while text is still coming in
The live window scrolled to its end on every new word, and Ask AI did the same on every token of an answer. That happened several times a second, so scrolling up was undone at once.
Both views now follow the end only while the reader is at it:
This uses
onScrollGeometryChange, which needs macOS 15; on macOS 14 the views follow as before.The live window's sentences are now
Equatableon what they show, so a word added to the draft line no longer redraws every sentence on screen.Tests
BottomFollowTests: when following stops and resumes, including new text arriving under a reader who has not moved.ScrollFrameRateTests: the range asked for at each setting. A display link raises an exception on a malformed range, so every setting is checked for that.Version 0.16.6 (build 24).
🤖 Generated with Claude Code
https://claude.ai/code/session_01UP49VoRGBw2wv1CEAroky7
Generated by Claude Code