Rewrite IFViewAnimator using CoreAnimation (fixes #46)#51
Open
angstsmurf wants to merge 1 commit into
Open
Conversation
The view-switching animation (source <-> Contents, and next/previous section) was driven by a 100Hz NSTimer that called -setNeedsDisplay: every tick, with -drawRect: manually compositing two cached bitmaps on the CPU. Not vsync-synced and easily starved on the main thread, which made the transition choppy. Replace the timer/drawRect machinery with CoreAnimation: snapshot the 'from' and 'to' views into two CALayers and slide (or cross-fade) them with CABasicAnimation, GPU-composited and display-link synced. Layer contentsScale is set to the window backing scale so snapshots stay crisp on Retina. The public API is unchanged, so callers in IFSourcePage.m need no changes. The old mid-animation 'recache' hack is replaced by forcing layout/display before snapshotting. The unused Left/Right/Up/Down slide directions are preserved exactly; the unused CrossFade/FloatIn/FloatOut styles fall back to a cross-fade. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
angstsmurf
marked this pull request as ready for review
July 11, 2026 22:55
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.
Summary
Fixes #46 — the source ⇄ Contents and next/previous-section transitions in the Source pane were choppy.
IFViewAnimatordrove its transition from a 100 HzNSTimerthat called-setNeedsDisplay:on every tick, with-drawRect:manually compositing two cached bitmaps on the CPU each frame. Because the timer runs on the main thread and isn't vsync-synced, it is easily starved and the animation stutters.This rewrites the animator to use CoreAnimation: the "from" and "to" views are snapshotted into two
CALayers and slid (or cross-faded) withCABasicAnimation, which is GPU-composited and display-link synced.Details
IFSourcePage.mneed no changes.IFAnimateLeft/Right/Up/Down) are preserved exactly — I traced each one's geometry from the old-drawRect:so the direction of motion matches the previous behaviour.IFAnimateCrossFade,IFFloatIn, andIFFloatOutstyles fall back to a simple cross-fade so the API keeps working.contentsScaleis set to the window's backing scale factor, so snapshots stay crisp on Retina displays (the old CPU path did not account for this).-drawRect:(re-snapshotting the target if it still wanted display in the first 25%) is replaced by forcinglayoutSubtreeIfNeeded+displayIfNeededbefore taking the snapshot.finishAnimationtears down the layers and is guarded by the existingoriginalView != nilcheck, so theCATransactioncompletion block is a safe no-op if the animation was abandoned early or the animator was deallocated.Net change is a single file, +145 / −265 lines.
Testing
Built and run in the Xcode IDE. Verified visually:
Base branch is
extensionssince that is where current development seems to live.🤖 Generated with Claude Code