Skip to content

Canvas: keep agent panes from moving the viewport; honor Reduce Motion - #14939

Merged
teamleaderleo merged 7 commits into
mainfrom
canvas-motion-respects-user
Sep 27, 2026
Merged

teamleaderleo merged 7 commits into
mainfrom
canvas-motion-respects-user

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 27, 2026 •

Copy link
Copy Markdown
Collaborator

In canvas mode, a pane an agent or the CLI creates no longer scrolls the canvas away from what you're watching. It moves the viewport only if it also took focus (for example an explicit --focus), and then it jumps there without animation. Socket canvas verbs (set-frame, reveal, align, overview, zoom, join, break, new-pane) still do what they're asked, just without animation. Canvas pans, pane-frame animations and the overview toggle from your own gestures now respect Reduce Motion, which before only discrete zoom did.

How:

  • CanvasRootView.sync used to animate a reveal of the last pane added through descriptor sync, whoever created it. Panes the user creates on the canvas go through openNewCanvasPane, which inserts them into the model before sync, so anything sync adds came from somewhere else. Sync now reveals an added pane only when it is the focused panel, unanimated.
  • CanvasActionExecutor.perform takes animated (default true for keyboard, palette and menu). CanvasViewportControlling gains animated variants of toggleOverview, zoom(by:) and resetZoom, with protocol defaults so existing spies compile unchanged. TerminalController+ControlCanvasContext passes animated: false everywhere, and openNewCanvasPane takes animated so canvas.new-pane reveals without animation while shortcuts keep the pan.
  • setClipOrigin, modelDidChangeExternally, the overview toggle and discrete zoom go through shouldAnimate(_:), which checks the same accessibilityDisplayShouldReduceMotion gate zoom used. The gate is renamed shouldReduceMotion since it now covers all canvas motion.

Tests: new CanvasViewportMotionTests in CmuxCanvasUI. On the first commit (a39c583, tests only, run against main's code) focusedAddedPaneIsRevealedWithoutAnimation and reduceMotionRevealsPaneImmediately fail, since the reveal was still animating. The overview and unanimated zoom tests came with the follow-up fix in 4366dd1 and have no failing-first run. On 4366dd1 swift test --package-path Packages/macOS/CmuxCanvasUI --filter "CanvasViewportMotionTests|CanvasViewportZoomTests|CanvasPaneBodyFocusTests" runs 26 tests and all pass. An onMotionAnimationStarted hook lets tests check that no animation starts; windowless test views don't run animations, so the viewport position alone can't show that. The app-side changes (socket verbs, executor) passed swiftc -parse only, and CI compiles them. No tagged app build or dogfood yet.

🤖 Generated with Claude Code

teamleaderleo and others added 2 commits September 27, 2026 05:28
A pane that syncs in already focused should be revealed immediately, and
Reduce Motion should make revealPane move the viewport without animation.
Both fail on main: the reveal runs as a 0.28 s animation either way.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pane that arrives through descriptor sync (an agent, the CLI or the
socket created it) now moves the viewport only when it also took focus,
and without animation. Before, the newest added pane always panned the
canvas away over 0.28 s. Socket canvas verbs (set-frame, reveal, join,
break, new-pane) apply their result without animation.

Canvas pans and external pane-frame animations now check Reduce Motion
the same way discrete zoom does. The gate is renamed shouldReduceMotion
since it covers all canvas motion, and onMotionAnimationStarted lets
tests see when an animation actually starts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 3 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 2ff11361-094e-40cd-ad7d-26c8f08458dd

📥 Commits

Reviewing files that changed from the base of the PR and between cfdde0b and a539ea1.

📒 Files selected for processing (9)
  • CHANGELOG.md
  • Packages/macOS/CmuxCanvasUI/Sources/CmuxCanvasUI/CanvasRootView+Viewport.swift
  • Packages/macOS/CmuxCanvasUI/Sources/CmuxCanvasUI/CanvasRootView.swift
  • Packages/macOS/CmuxCanvasUI/Sources/CmuxCanvasUI/CanvasViewportControlling.swift
  • Packages/macOS/CmuxCanvasUI/Tests/CmuxCanvasUITests/CanvasViewportMotionTests.swift
  • Packages/macOS/CmuxCanvasUI/Tests/CmuxCanvasUITests/CanvasViewportZoomTests.swift
  • Sources/Canvas/CanvasAction.swift
  • Sources/Canvas/Workspace+CanvasLayout.swift
  • Sources/TerminalController+ControlCanvasContext.swift

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

teamleaderleo and others added 5 commits September 27, 2026 06:08
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The overview toggle ran two ungated 0.3 s animations, so Reduce Motion
did not cover it. It now goes through shouldAnimate like pans and pane
frames, and reports to onMotionAnimationStarted, as discrete zoom does.

CanvasActionExecutor.perform takes animated (default true for keyboard,
palette and menu). The viewport protocol gains animated variants of
toggleOverview, zoom and resetZoom, with defaults for spies. Socket
align, overview and zoom pass animated: false, which makes the file's
"Socket verbs never animate" comment true.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…otion-respects-user

# Conflicts:
#	CHANGELOG.md
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo merged commit 9943115 into main Sep 27, 2026
77 checks passed
@teamleaderleo
teamleaderleo deleted the canvas-motion-respects-user branch September 27, 2026 11:02
@github-actions

Copy link
Copy Markdown
Contributor

Merge receipt for a539ea1abd: every check was green at merge (28 verified; 21 skipped by policy). Full suite runs on main after merge.

rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 27, 2026
5090403 UI test frames: sample XCTest screen recordings; SIGKILL stuck prompts (manaflow-ai#14956)
9943115 Canvas: keep agent panes from moving the viewport; honor Reduce Motion (manaflow-ai#14939)
f873b5a Fix duplicate-instance handler terminating unrelated helpers (manaflow-ai#13845)
0c151d1 Open Settings panes at their natural top (manaflow-ai#14950)
cfdde0b cmux-tui: inject Claude hooks through a PATH shim, including under sr (manaflow-ai#14908)
320a966 ci: correct the producer rpath length in the relocation docstring (manaflow-ai#14947)
8f79066 Hover never outshouts selection; focus, badge, and feed pill edges (manaflow-ai#14941)
5617ac3 cmux-tui: publish the agent's session id on the agents roster (manaflow-ai#14904)
533a5b9 fix: stop WindowAccessor storing a deallocating window (manaflow-ai#14946)
9546e06 reloadp.sh: exclude only this build's own bundle from the stable check (manaflow-ai#14889)
e27f361 docs: say full-ci runs only selected cmuxUITests targets (manaflow-ai#14945)
28d1eaf ci: point restored products at their own package frameworks (manaflow-ai#14930)
75caaa5 Land hot-path sidebar, feed, palette and notification state changes in the next frame (manaflow-ai#14927)
6b58884 docs: tighten CLAUDE.md and CONTRIBUTING.md; move procedures to skills (manaflow-ai#14920)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant