Skip to content

Reduce typing lag by hiding invisible views from accessibility tree - #862

Merged
lawrencecchen merged 1 commit into
mainfrom
task-fix-accessibility-tree-typing-lag
Mar 4, 2026
Merged

lawrencecchen merged 1 commit into
mainfrom
task-fix-accessibility-tree-typing-lag

Conversation

@lawrencecchen

@lawrencecchen lawrencecchen commented Mar 4, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Profiling cmux NIGHTLY with sample shows the main thread spending ~24% of CPU time in AccessibilityViewGraph.needsUpdate during every SwiftUI layout pass. The accessibility subsystem walks the entire view tree, including invisible views (opacity-0, hit-testing disabled), blocking the run loop from dequeuing key events and causing typing lag.

  • Hide inactive workspaces from accessibility (ContentView.swift). All mounted workspaces sit in a ZStack; inactive ones are opacity-0 but still walked. Adding .accessibilityHidden(!isVisible) eliminates them from the walk.
  • Hide the tabs/notifications containers from accessibility when not selected.
  • Mark GhosttyTerminalView's HostContainerView as non-accessible. This empty NSView placeholder (portal pattern) has no content since the terminal surface lives in the AppKit layer above SwiftUI.

Note: NotificationsPage is effectively dead code for users (all notification paths go to the popover). Could be removed entirely in a follow-up.

Testing

  • Built successfully in Debug configuration.
  • Profile with sample <pid> 10 while typing to compare AccessibilityViewGraph.needsUpdate sample counts before/after.

Profiling data (before)

Main thread sample breakdown (10s capture, 5707 samples):

Samples % What
3576 63% NSHostingView.layout() → SwiftUI view graph render
1381 24% AccessibilityViewGraph.needsUpdate
1287 23% SwiftUI accessibility UpdateStack::update()
514 9% AccessibilityViewModifierAccessor

Summary by cubic

Hide invisible SwiftUI views from the accessibility tree to reduce layout overhead and improve typing responsiveness. This cuts time spent in AccessibilityViewGraph.needsUpdate during layout.

  • Performance
    • Add .accessibilityHidden(!isVisible) for inactive workspaces in ContentView.
    • Hide tabs and NotificationsPage from accessibility when not selected.
    • Mark GhosttyTerminalView’s HostContainerView as non-accessible (role .none, element false).

Written for commit 5742799. Summary will update on new commits.

Summary by CodeRabbit

  • Bug Fixes
    • Improved screen reader and accessibility tool behavior by preventing them from traversing inactive UI sections, including hidden workspaces, non-selected notifications, and terminal placeholders. Users relying on assistive technologies will now experience more streamlined navigation.

Profiling shows the main thread spends ~24% of time in
AccessibilityViewGraph.needsUpdate walking invisible SwiftUI views
during every layout pass, blocking key event dequeue.

- Add .accessibilityHidden on inactive workspaces in the ZStack
  (opacity-0 but still walked by the accessibility subsystem)
- Add .accessibilityHidden on NotificationsPage and the tabs
  container when their respective selection is not active
- Mark GhosttyTerminalView's HostContainerView (empty portal
  placeholder) as non-accessible since the terminal surface
  lives in the AppKit portal layer above SwiftUI
@vercel

vercel Bot commented Mar 4, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Mar 4, 2026 10:26am

@coderabbitai

coderabbitai Bot commented Mar 4, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0c16abe0-b55e-42be-b146-0a514c0b14ee

📥 Commits

Reviewing files that changed from the base of the PR and between f5de515 and 5742799.

📒 Files selected for processing (2)
  • Sources/ContentView.swift
  • Sources/GhosttyTerminalView.swift

📝 Walkthrough

Walkthrough

This pull request enhances accessibility by adding modifiers to hide non-visible or non-selected UI elements from assistive technologies. Additionally, a temporary container in the terminal view is marked to prevent accessibility traversal into placeholder elements.

Changes

Cohort / File(s) Summary
Accessibility Visibility Controls
Sources/ContentView.swift
Added accessibilityHidden() modifiers to workspaces, notifications, and tab views to hide UI elements from assistive technologies when they are not visually active or selected.
Terminal View Accessibility Guards
Sources/GhosttyTerminalView.swift
Set accessibility role to none and disabled accessibility element status on temporary container to prevent assistive technology traversal into placeholder content.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐰 Hop along, the path is clear,
Accessibility blooms far and near,
Hidden elements stay out of sight,
Assistive tech sees only what's right!
A rabbit's code, precise and bright. ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main objective of the PR: reducing typing lag by hiding invisible views from the accessibility tree through strategic use of accessibilityHidden() modifiers.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch task-fix-accessibility-tree-typing-lag

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

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

@greptile-apps

greptile-apps Bot commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR addresses typing lag caused by SwiftUI's accessibility subsystem walking the entire view tree during layout passes. The changes hide invisible views from the accessibility tree using .accessibilityHidden() modifiers, which should reduce CPU time spent in AccessibilityViewGraph.needsUpdate from ~24% to significantly less.

Key changes:

  • Inactive workspaces (opacity 0) are now hidden from accessibility tree
  • Tabs and notifications containers are hidden when not selected
  • HostContainerView placeholder is marked as non-accessible

The boolean logic correctly mirrors existing visibility patterns (opacity + hit testing), and follows the established pattern in the codebase of hiding invisible UI elements from accessibility. No actual accessibility functionality is affected since these views are already invisible to users.

Confidence Score: 5/5

  • This PR is safe to merge with no risk
  • The changes are minimal, logically correct, and follow existing patterns in the codebase. The accessibility modifiers only hide views that are already invisible, so there's no impact on actual accessibility functionality. The performance improvement is well-documented with profiling data.
  • No files require special attention

Important Files Changed

Filename Overview
Sources/ContentView.swift Added .accessibilityHidden() modifiers to workspace views, tabs, and notifications containers that are already invisible via opacity/selection state
Sources/GhosttyTerminalView.swift Marked HostContainerView as non-accessible since it's an empty placeholder for the AppKit portal pattern

Last reviewed commit: 5742799

@lawrencecchen
lawrencecchen merged commit 102931d into main Mar 4, 2026
13 checks passed
bn-l pushed a commit to bn-l/cmux that referenced this pull request Apr 3, 2026
…anaflow-ai#862)

Profiling shows the main thread spends ~24% of time in
AccessibilityViewGraph.needsUpdate walking invisible SwiftUI views
during every layout pass, blocking key event dequeue.

- Add .accessibilityHidden on inactive workspaces in the ZStack
  (opacity-0 but still walked by the accessibility subsystem)
- Add .accessibilityHidden on NotificationsPage and the tabs
  container when their respective selection is not active
- Mark GhosttyTerminalView's HostContainerView (empty portal
  placeholder) as non-accessible since the terminal surface
  lives in the AppKit portal layer above SwiftUI

This branch was successfully deployed

1 active deployment
Preview — 57427996 Deployed Mar 4, 2026 by vercel[bot]
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