Skip to content

Fix #5917: restore OSC 11 pane-local backgrounds - #5997

Merged
austinywang merged 4 commits into
mainfrom
issue-5917-osc11-per-pane-background
Jun 13, 2026
Merged

austinywang merged 4 commits into
mainfrom
issue-5917-osc11-per-pane-background

Conversation

@austinywang

@austinywang austinywang commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

Closes #5917

Summary

  • Keep pane-local OSC 11 background overrides on the terminal surface fill path while preserving the shared window root backdrop for panes that do not set OSC 11.
  • Stop replacing the active window root snapshot with the focused pane's OSC 11 color; the shared root now remains the workspace/default terminal background.
  • Add a red/green regression for the shared-root snapshot so CI proves an OSC 11 surface override cannot tint the shared window root.

Regression provenance

Testing

  • Not run locally per task instruction.
  • git diff --check
  • CI will validate the failing-test-first stack: commit 1 adds the red regression, commit 2 fixes it.

Manual dogfood after CI green

Run only after explicit launch approval:
CMUX_SKIP_ZIG_BUILD=1 ./scripts/reload.sh --tag issue-5917-osc11-per-pane-background --launch
Then in a plain shell pane run printf '\e]11;#E6BE78\a'; the receiving pane should turn #E6BE78 while neighboring panes keep the shared/default backdrop.


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Restores per-pane OSC 11 backgrounds without tinting the shared window root. The workspace/default background stays on the root; OSC 11 colors only affect the target pane.

  • Bug Fixes
    • Keep OSC 11 overrides local to the pane; stop replacing the window root backdrop with the focused pane color.
    • Replace replacingTerminalBackgroundColor(...) with windowRootBackdropResolution(surfaceBackgroundColor:) that preserves the root snapshot; use compositedTerminalBackgroundColor when applying the plan.
    • Move the regression to Swift Testing and assert the shared root stays default while the pane uses the OSC 11 color.
    • Remove stale background color helper to avoid conflicting opacity logic.

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

Review in cubic

Summary by CodeRabbit

  • Bug Fixes

    • Improved window backdrop resolution when pane-local background color overrides are applied, ensuring correct behavior with shared window-root backdrops while respecting local surface overrides.
  • Tests

    • Added test coverage for pane background override scenarios.

@vercel

vercel Bot commented Jun 12, 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 Jun 12, 2026 10:02pm
cmux-staging Building Building Preview, Comment Jun 12, 2026 10:02pm

@coderabbitai

coderabbitai Bot commented Jun 12, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Refactored backdrop resolution to prevent OSC 11 pane-local surface colors from replacing the shared window backdrop. Introduced WindowAppearanceSnapshot.windowRootBackdropResolution(surfaceBackgroundColor:) to leave the snapshot unchanged while extracting source and override metadata. Updated view integration and debug logging, with new test coverage validating the pane-local behavior.

Changes

Pane-Local OSC 11 Backdrop Handling

Layer / File(s) Summary
Snapshot backdrop method and view integration
Sources/Windowing/WindowBackdropController.swift, Sources/GhosttyTerminalView.swift
WindowAppearanceSnapshot.windowRootBackdropResolution(surfaceBackgroundColor:) returns the snapshot unchanged with source and overrideHex metadata derived from the optional surface color, documenting that OSC 11 is pane-local. GhosttyNSView.applyWindowBackgroundIfActive() calls this method, uses windowRoot.snapshot.compositedTerminalBackgroundColor for the window background color, and logs via the new windowRoot.source and windowRoot.overrideHex fields instead of computing hasOverride flags.
Test validation and project configuration
cmuxTests/WindowAppearanceSnapshotPaneBackgroundTests.swift, cmux.xcodeproj/project.pbxproj
New test file verifies that a pane-local OSC surface color override (#E6BE78) produces the expected host-layer fill without replacing the shared window root backdrop colors, and correctly propagates the override hex through the window-root resolution while preserving the terminal background hex. Project configuration adds the test file to the cmuxTests target and build phase.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • manaflow-ai/cmux#3886: Original per-pane OSC 11 background preservation implementation with similar applyWindowBackgroundIfActive() refactoring and replacingTerminalBackgroundColor(_:) removal.
  • manaflow-ai/cmux#5106: Revert that removed per-pane background support; this PR restores the functionality with an updated snapshot resolution approach.
  • manaflow-ai/cmux#5509: Related OSC 11 plumbing changes affecting how WindowAppearanceSnapshot resolves and propagates window-root and surface backdrop colors.

Poem

🐰 A snapshot keeps its colors bright and true,
When panes paint locally in every hue,
No more replacing what the backdrop knew—
Per-pane, per-grace, the workspace shines right through!


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Logging ❌ Error GhosttyTerminalView.swift uses GhosttyApp.shared.logBackground(), which writes diagnostic logs to a file (backgroundLogURL) and the window-background debug message was materially changed to include... Remove/avoid ad hoc file-based diagnostics (logBackground writing to /tmp). Route logging through allowed Logger/debug-only (#if DEBUG) paths, or keep any changed diagnostics behind compile-time debug guards.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (19 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the primary change: restoring OSC 11 pane-local backgrounds, which directly addresses the issue #5917 being fixed.
Linked Issues check ✅ Passed The PR meets the primary coding objectives from #5917: restores per-pane OSC 11 isolation using windowRootBackdropResolution() [#5917], adds regression tests [#5917], and preserves shared root backdrop while allowing pane-local overrides [#5917]. The implementation uses compositedTerminalBackgroundColor instead of replacingTerminalBackgroundColor() to prevent root tinting.
Out of Scope Changes check ✅ Passed All changes align with the linked issue #5917 objectives: WindowBackdropController refactoring enables pane-local OSC 11, the test validates no shared-root tinting occurs, and logging adjustments support the new resolution flow. No unrelated changes detected.
Cmux Swift Actor Isolation ✅ Passed Reviewed added windowRootBackdropResolution(...) and updated applyWindowBackgroundIfActive; both are synchronous value computations with no new @MainActor/service/Sendable or background UI-store ac...
Cmux Swift Blocking Runtime ✅ Passed PR diff hunks scanned for swift-blocking-runtime primitives (Task.sleep, DispatchSemaphore waits, main sync, NSLock, sleeps/timers) show no matches in changed production Swift files.
Cmux Expensive Synchronous Load ✅ Passed PR #5997 diffs only adjust OSC 11/window-backdrop snapshot logic (GhosttyTerminalView.swift, WindowBackdropController.swift) and add tests; no RestorableAgentSessionIndex.load/sysctl or SharedLiveA...
Cmux Cache Substitution Correctness ✅ Passed PR change preserves root backdrop by building a fresh windowRoot snapshot from currentFromUserDefaults and deriving override/source from the live surfaceBackgroundColor; no cached/stale substitutio...
Cmux No Hacky Sleeps ✅ Passed PR #5997 changes only Swift files + project.pbxproj; web diff shows no TS/JS/shell/build script changes and no 'sleep/timeout/setTimeout' tokens in the diff.
Cmux Algorithmic Complexity ✅ Passed PR changes only constant-time snapshot/color wiring and debug logging; removed/added helpers return snapshots directly with no loops, scans, sorts, or per-record rescans.
Cmux Swift Concurrency ✅ Passed Swift changes are synchronous window-backdrop snapshot computations/logging; no new DispatchQueue/Combine/completion-handler/Task patterns in updated blocks (checked applyWindowBackgroundIfActive +...
Cmux Swift @Concurrent ✅ Passed PR diff contains no @concurrent, nonisolated async, or await keywords in changed Swift hunks, so no swift-concurrent-annotation rule violations detected.
Cmux Swift File And Package Boundaries ✅ Passed PR 5997 only makes small diffs: GhosttyTerminalView +3/−17 lines, WindowBackdropController +3/−17, and adds 23 test lines; no new oversized prod Swift files or boundary/mixed-responsibility violati...
Cmux User-Facing Error Privacy ✅ Passed PR only updates backdrop snapshot logic, debug background logging, project wiring, and adds a unit test—no user-facing errors/alerts/command output/API error bodies/recovery copy added or changed.
Cmux Full Internationalization ✅ Passed Checked PR’s changed Swift backdrop code: updates OSC 11 resolution + debug logging only; no user-facing Swift strings, .strings/Info.plist, or web/i18n message/catalog entries added or modified.
Cmux Swiftui State Layout ✅ Passed Modified GhosttyTerminalView.applyWindowBackgroundIfActive + WindowBackdropController helpers only backdrop computation/logging; no new SwiftUI state layout hazards (ObservableObject/@Published/Geo...
Cmux Architecture Rethink ✅ Passed PR updates backdrop snapshot resolution + logging and adds a unit test; the changed logic is synchronous/pure with no added sleeps, polling, locks, observers, or duplicate wiring.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PR #5997 only updates backdrop color snapshot logic (Sources/GhosttyTerminalView.swift, Sources/Windowing/WindowBackdropController.swift) and adds a snapshot unit test; no NSWindow/NSPanel/NSWindow...
Cmux Source Artifacts ✅ Passed PR changes only Swift source files, a unit test file, and the Xcode project file; no generated logs/temp/DerivedData/artifact directories are added, per rules.
Description check ✅ Passed The PR description comprehensively covers the summary, testing approach, manual verification instructions, and includes all major checklist items.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-5917-osc11-per-pane-background

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 and usage tips.

@greptile-apps

greptile-apps Bot commented Jun 12, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes issue #5917 by ensuring that OSC 11 pane-local background overrides are applied only to the surface fill layer, not to the shared window root backdrop. The root snapshot loaded from UserDefaults is now always preserved as the workspace/default background.

  • Replaces replacingTerminalBackgroundColor(_:) with windowRootBackdropResolution(surfaceBackgroundColor:), which always returns self (the unmodified workspace snapshot) plus logging metadata, making it structurally impossible for an OSC 11 color to tint the shared window root.
  • Removes the now-dead effectiveBackgroundColor() helper that was computing the pane-local composite color for the window backdrop; the log signature correctly uses snapshot.compositedTerminalBackgroundColor (workspace default) for the window path and surfaces the OSC 11 hex only through overrideHex metadata.
  • Adds a Swift Testing regression that asserts the fill plan routes the override to surfaceHostLayer while the shared root snapshot's terminalBackgroundColor and windowGlassSettings.terminalGlassTintColor remain the workspace default.

Confidence Score: 5/5

Safe to merge — the change is tightly scoped to the backdrop resolution path, the invariant is enforced structurally, and the deleted helper has no remaining callers.

The fix correctly isolates OSC 11 to the pane surface fill layer by making windowRootBackdropResolution always return the unmodified workspace snapshot. The removed effectiveBackgroundColor helper had no other callers. The new regression test exercises the exact bug scenario end-to-end. No production logic is left in a fragile or ambiguous state.

No files require special attention.

Important Files Changed

Filename Overview
Sources/GhosttyTerminalView.swift Removes effectiveBackgroundColor() (now dead), replaces replacingTerminalBackgroundColor with windowRootBackdropResolution, and updates the log signature to use the shared-root color; no remaining callers for the deleted helper
Sources/Windowing/WindowBackdropController.swift Replaces replacingTerminalBackgroundColor (which mutated the snapshot with the pane's OSC 11 color) with windowRootBackdropResolution (which always returns self, plus logging metadata); correctly enforces the invariant that OSC 11 never touches the shared window root
cmuxTests/WindowAppearanceSnapshotPaneBackgroundTests.swift New Swift Testing regression verifying that an OSC 11 surface override routes to the surfaceHostLayer fill plan while windowRootBackdropResolution preserves the workspace default color on the shared root snapshot
cmux.xcodeproj/project.pbxproj Adds the new test file to the Xcode project; UUIDs follow the project's existing sequential pattern

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[applyWindowBackgroundIfActive] --> B[applySurfaceBackground]
    B --> C{Has OSC 11 override?}
    C -- yes --> D[TerminalSurfaceBackgroundFillPlan\nowner: surfaceHostLayer\ncolor: OSC 11 color]
    C -- no --> E[TerminalSurfaceBackgroundFillPlan\nowner: default\ncolor: workspace default]
    A --> F[windowRootBackdropResolution\nsurfaceBackgroundColor: backgroundColor]
    F --> G[Always returns self\nunchanged workspace snapshot]
    G --> H[windowRoot.snapshot.backdropPlan]
    H --> I[WindowBackdropController.apply\nShared window root = workspace default]
    D -.-> J[Pane surface layer only]
    I --> K[Window backdrop layer\nalways workspace/default color]
Loading

Reviews (3): Last reviewed commit: "fix: remove stale background color helpe..." | Re-trigger Greptile

Comment on lines 130 to 133
func windowRootBackdropSnapshot(surfaceBackgroundColor _: NSColor?) -> Self {
// OSC 11 is pane-local state; the shared root remains the workspace backdrop.
self
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Parameter accepted but permanently ignored

surfaceBackgroundColor is labelled _: because the implementation unconditionally returns self. While the comment explains the invariant, calling code still constructs the optional NSColor and passes it, and any future reader must understand why a parameter exists solely to be discarded. If the method will never use the surface color, consider removing the parameter entirely and updating the call site to snapshot (no method call needed) — that would make the invariant "OSC 11 never touches the shared root" impossible to violate by passing a different value.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed by replacing the ignored-parameter helper with windowRootBackdropResolution(...), which preserves the shared root snapshot while deriving source/override log metadata from the pane color.

— Claude Code

@austinywang
austinywang merged commit 01d0ea9 into main Jun 13, 2026
20 checks passed
hhsw2015 pushed a commit to hhsw2015/cmux that referenced this pull request Jun 14, 2026
PRs included:
- AppDelegate decomposition: CmuxSession session-snapshot repository (manaflow-ai#6030)
- Fix Cmd+T cwd after session restore (manaflow-ai#6055)
- Speed up iOS terminal scroll rendering (manaflow-ai#6035)
- Preserve Pi sessions across workspace restore (manaflow-ai#5607)
- Scope Biome checks to maintained JS sources (manaflow-ai#6008)
- Fix manaflow-ai#5917: restore OSC 11 pane-local backgrounds (manaflow-ai#5997)
- Expose stable window title templates (manaflow-ai#6059)
- Honor macos-option-as-alt left/right
- Fix macOS 27 SF Symbol rasterization crash (manaflow-ai#5999)
- CmuxRemote* family: extract Workspace remote/cloud-VM connectivity
- Fix iOS workspace swipe-delete confirmation crash (manaflow-ai#6051)
- TabManager decomposition Wave 3+4 sub-models
- Sidebar row cleanups: branchless frame anchor
- CmuxIPCService: extract AppDelegate multi-window CLI routing
- CmuxSidebarGit: extract TabManager git-metadata + PR-polling subsystem
- CmuxTerminalCore: extract terminal core leaf

Fork-side adjustments:
- ghostty submodule: cherry-pick mouse-modifier-state fix onto our renderer-realized branch
- Workspace.swift: take theirs (upstream extracted ~7700 lines into CmuxCore.Remote/CmuxRemoteSession packages); restore fork's renameTopLevelLayoutTabContaining/closeTopLevelLayoutTabContaining + surfaceTmuxClientTTYNames + WorkspaceLayoutTab integration
- TabManager.swift: take theirs; re-add static allocatePortOrdinal()
- BrowserPanelView, RenderableSystemSymbol: keep fork's cmuxSymbolPixelSize extension on top of upstream's cmuxSymbolRasterSize
- Add CmuxWorkspaces / CMUXSessionDaemon / CmuxCommandPalette imports to TerminalController, Workspace, SessionPersistence
- Sources/Workspace+P43Stubs.swift: thin shims for SplitEqualizer, WorkspaceRemoteSessionController.PortScanKickReason, WorkspaceGroupNewWorkspacePlacementSettings (legacy types fork TC still calls; replace with package APIs in P44+)
- Sources/GhosttySurfaceSizeDeferralReason.swift: restore fork-only enum (deleted by upstream)
- Sources/StableLayout/SessionBlueprintExportAction.swift: parked debug action (depends on legacy SessionPersistenceStore, gone)
- Sources/GhosttyTerminalView.swift: stub ghostty_surface_select_cursor_line_compat (needs zig 0.15.2 xcframework rebuild)
- pbxproj: keep-both, drop stale ProcessPipeReader/SplitEqualizer/Panels/BrowserProxyEndpoint refs, fix SurfaceHibernationPolicy UUID collision
- Drop fork's WorkspaceRemoteConfiguration.swift + WorkspaceRemoteSSHBatchCommandBuilder.swift (extracted to CmuxCore package)
@austinywang austinywang mentioned this pull request Jun 15, 2026

This branch was successfully deployed

1 active deployment
Preview – cmux — a122f8b9 Deployed Jun 12, 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.

OSC 11 per-pane terminal background coloring regression (reverted in #5106)

1 participant