Skip to content

add a global multipane zoom preference - #52

Merged
h3nock merged 9 commits into
mainfrom
feature/settings-organization
Aug 7, 2026
Merged

add a global multipane zoom preference#52
h3nock merged 9 commits into
mainfrom
feature/settings-organization

Conversation

@h3nock

@h3nock h3nock commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Context

#49 changed multipane windows from automatic tmux zoom to displaying the complete tmux layout by default. Zoom remained available from Panes, but it had to be enabled separately for every window and session.

That works well when the complete layout is useful, especially on larger screens, but makes dense desktop layouts difficult to use from an iPhone.

Closes #51.

What changed

Adds a persisted Zoom multipane windows setting under Windows & Panes.

  • Enabled by default on iPhone.
  • Disabled by default on iPad, preserving the complete-layout experience.
  • Applies to existing multipane windows and windows that become multipane later.
  • Changing the global setting replaces temporary per-window choices.
  • Zoom can still be overridden per window from Panes for the current app session.
  • Returning to a single pane clears that temporary choice. If the window becomes multipane again, the global setting applies.
  • Remux continues to make a best-effort cleanup attempt for zooms it created when the app session ends normally.
  • Selecting a pane from the Panes sheet now dismisses the sheet.

This gives iPhone users the previous zoomed experience without removing the complete-layout behavior introduced in #49.

Settings behavior

The preference is persisted app-wide. Existing settings without this value adopt the device default:

  • iPhone: Zoom ON
  • iPad: Zoom OFF

Validation

Validated with focused tests, the iOS simulator, and a physical iPhone:

  • Device defaults, settings migration, and persistence.
  • Enabling and disabling the setting with existing multipane windows.
  • Applying the setting when a single-pane window becomes multipane.
  • Returning to one pane and splitting again.
  • Per-window overrides followed by a global-setting change.
  • Split Right and Split Down with Zoom enabled and disabled.
  • Switching between windows without losing temporary choices.
  • Avoiding redundant zoom commands for windows already in the requested state.
  • Normal cleanup of Remux-created zooms.
  • Pane selection dismissing the Panes sheet.

Summary by CodeRabbit

  • New Features
    • Added a “Zoom multipane windows” terminal preference.
    • Multipane zoom is enabled by default on iPhone and disabled on other devices, with saved preferences preserved.
    • Newly created splits can automatically use the configured zoom behavior.
  • Improvements
    • Improved pane and window zoom handling during navigation, splitting, and session changes.
    • Selecting a tmux pane now dismisses the selection sheet and restores keyboard focus.
    • Existing settings are migrated safely when the new preference is introduced.
  • Bug Fixes
    • Improved reliability when panes or windows change during zoom operations.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 6, 2026

Copy link
Copy Markdown

Deploying remux with  Cloudflare Pages  Cloudflare Pages

Latest commit: cd8a1de
Status: ✅  Deploy successful!
Preview URL: https://b0d4b674.remux-agx.pages.dev
Branch Preview URL: https://feature-settings-organizatio.remux-agx.pages.dev

View logs

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a7535378-96b1-4ac9-b157-7b4d14de7200

📥 Commits

Reviewing files that changed from the base of the PR and between 1f3aa33 and cd8a1de.

📒 Files selected for processing (3)
  • RemuxApp/Sources/App/RemuxAppDependencies.swift
  • RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift
  • RemuxAppTests/TmuxSessionControllerClientSizeTests.swift
🚧 Files skipped from review as they are similar to previous changes (3)
  • RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift
  • RemuxApp/Sources/App/RemuxAppDependencies.swift
  • RemuxAppTests/TmuxSessionControllerClientSizeTests.swift

📝 Walkthrough

Walkthrough

The change adds a persisted multipane zoom preference with device-specific defaults, exposes it in terminal settings, and propagates it to tmux sessions. It also replaces pane-refresh workflows with deferred, callback-based tmux mutations and adds coverage for migration, topology, ownership, lifecycle, and UI behavior.

Changes

Multipane zoom preference and tmux control

Layer / File(s) Summary
Settings contract, persistence, and UI
RemuxApp/Sources/Domain/TerminalSettings.swift, RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift, RemuxApp/Sources/App/RemuxAppDependencies.swift, RemuxApp/Sources/App/RootView.swift, RemuxAppTests/TerminalSettings*, RemuxAppUITests/RemuxAppUITests.swift
TerminalSettings stores and decodes the multipane zoom preference. Repositories apply device-specific defaults. The settings UI edits the value through a binding.
Multipane zoom policy and adapter ownership
RemuxApp/Sources/Tmux/TmuxTerminalScreenAdapter.swift, RemuxApp/Sources/Tmux/TmuxScreenModel.swift, RemuxAppTests/TmuxTerminalScreenAdapterTests.swift
The adapter resolves per-window zoom defaults, tracks pending ownership, preserves pane-specific state, and applies preference changes to eligible topologies.
Deferred tmux mutations and lifecycle cleanup
RemuxApp/Sources/Tmux/TmuxSessionController.swift, RemuxApp/Sources/Tmux/TmuxTerminalSession.swift, RemuxApp/Sources/Ghostty/GhosttySurfaceScreen.swift, RemuxAppTests/TmuxSessionControllerClientSizeTests.swift
The controller uses grouped commands, topology barriers, success callbacks, and deferred zoom intents. Pane-refresh callbacks and phase-change handling are removed.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SettingsView
  participant TmuxScreenModel
  participant TmuxTerminalScreenAdapter
  participant TmuxSessionController
  participant TmuxTerminalSession
  SettingsView->>TmuxScreenModel: update zoomMultipaneWindowsByDefault
  TmuxScreenModel->>TmuxTerminalScreenAdapter: apply preference
  TmuxTerminalScreenAdapter->>TmuxSessionController: submit deferred window zoom
  TmuxSessionController->>TmuxTerminalSession: send grouped tmux mutation
  TmuxTerminalSession-->>TmuxSessionController: report command completion
  TmuxSessionController-->>TmuxTerminalScreenAdapter: report successful submission
Loading

Possibly related PRs

  • h3nock/remux#49: Introduced the multipane rendering and zoom architecture modified by this change.
  • h3nock/remux#27: Overlaps with pane selection, zoom handling, and lifecycle changes.
  • h3nock/remux#9: Shares the terminal settings propagation and non-appearance settings behavior.
🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: adding a global multipane zoom preference.
Linked Issues check ✅ Passed The changes implement the global optional multipane layout preference requested in issue #51, including persistence and device-specific defaults.
Out of Scope Changes check ✅ Passed The changes support the preference, pane lifecycle behavior, cleanup, sheet dismissal, and related validation described in the objectives.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/settings-organization

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.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Aug 6, 2026

Copy link
Copy Markdown

Deploying getremux with  Cloudflare Pages  Cloudflare Pages

Latest commit: cd8a1de
Status: ✅  Deploy successful!
Preview URL: https://0a0f208a.getremux.pages.dev
Branch Preview URL: https://feature-settings-organizatio.getremux.pages.dev

View logs

@h3nock
h3nock marked this pull request as ready for review August 7, 2026 13:36

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5d24e0e5da

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +40 to +42
resolvedWindowIDs.insert(window.id)
if window.zoomed != isEnabled {
targets.append(window.id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reconcile preference changes with in-flight zoom commands

When the preference is toggled again before a previously submitted zoom command produces a topology update, this records the window as resolved from stale topology. For example, turning the setting on queues a zoom, then turning it off while the window still appears unzoomed records it as resolved and queues no inverse; when the first command later succeeds, subsequent topology updates skip the window and it remains zoomed despite the saved setting being off. Track in-flight desired states or reevaluate resolved windows after command settlement.

Useful? React with 👍 / 👎.

Comment on lines +982 to +985
onZoomSubmitted: { [weak self] windowID in
DispatchQueue.main.async {
self?.pendingZoomOwnershipWindowIDs.insert(windowID)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Record zoom ownership before asynchronous submission

If the user zooms a pane and immediately disconnects the session, ownership is not recorded until this main-queue block runs. prepareForSessionShutdown() can therefore inspect empty ownership sets and skip cleanup while the controller's already-enqueued zoom command still executes before shutdown, leaving Remux's zoom active on the server. Record pending ownership synchronously before returning from the UI action, and remove it if admission fails.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai 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.

Actionable comments posted: 2

🧹 Nitpick comments (4)
RemuxAppTests/TmuxSessionControllerClientSizeTests.swift (2)

1121-1128: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Drop the unused paneID parameter.

assertCommandWrite ignores paneID. Every call site still passes a value, and a wrong value now has no effect on the assertion. Remove the parameter, or use it to assert the command targets that pane.

♻️ Proposed refactor
     private func assertCommandWrite(
         _ writes: [String],
         command: String,
-        paneID _: TmuxPaneID,
         file: StaticString = `#filePath`,
         line: UInt = `#line`
     ) {
         XCTAssertEqual(writes, [command + "\n"], file: file, line: line)
     }

Update each call site to drop the paneID: argument.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@RemuxAppTests/TmuxSessionControllerClientSizeTests.swift` around lines 1121 -
1128, Remove the unused paneID parameter from assertCommandWrite and update
every call site to omit the paneID: argument, leaving the existing write
assertion unchanged.

436-446: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove or rename the duplicated shutdown-unzoom test.

testShutdownUnzoomSendsOnlyTheTmuxMutation uses the same fixture, the same call, and the same assertion as testExplicitUnzoomTogglesAnAuthoritativelyZoomedWindow at lines 420-434. It never shuts the controller down, so the name does not describe what it verifies. Either delete it, or make it exercise the real shutdown cleanup path through requestSetWindowsZoomed before shutdown().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@RemuxAppTests/TmuxSessionControllerClientSizeTests.swift` around lines 436 -
446, Remove the duplicate test testShutdownUnzoomSendsOnlyTheTmuxMutation, or
rename and revise it to cover the actual shutdown cleanup path by invoking
requestSetWindowsZoomed before shutdown(). Preserve
testExplicitUnzoomTogglesAnAuthoritativelyZoomedWindow for the direct unzoom
mutation assertion.
RemuxAppTests/TmuxTerminalScreenAdapterTests.swift (1)

139-163: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a case with more than two panes.

The fixture is used only with paneCount 1 and 2. TmuxMultipaneZoomDefaultPolicy.windowIDsNeedingChange breaks the pane loop at 2, so its paneCount == 2 guard means "two or more panes". No test proves that a three-pane window is still treated as multipane. A future reader could read == 2 as an exact count and change it without failing a test.

💚 Proposed additional test
func testMultipaneZoomDefaultTargetsAWindowWithMoreThanTwoPanes() {
    var policy = TmuxMultipaneZoomDefaultPolicy(isEnabled: true)

    XCTAssertEqual(
        policy.windowIDsNeedingChange(in: topology(zoomed: false, paneCount: 3)),
        [1]
    )
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@RemuxAppTests/TmuxTerminalScreenAdapterTests.swift` around lines 139 - 163,
Add a test alongside the existing TmuxMultipaneZoomDefaultPolicy tests that uses
topology(zoomed: false, paneCount: 3) with the policy enabled and asserts
windowIDsNeedingChange returns [1], confirming windows with more than two panes
are treated as multipane.
RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift (1)

16-20: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicated TerminalSettings default literals in RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift and RemuxApp/Sources/App/RemuxAppDependencies.swift. Both sites hand-write the full field list of TerminalSettings to express "the canonical default, with zoomMultipaneWindowsByDefault overridden". A new field or a changed default value in TerminalSettings will not reach either literal.

  • RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift#L16-L20: build defaultSettings from TerminalSettings.default and assign zoomMultipaneWindowsByDefault on the copy.
  • RemuxApp/Sources/App/RemuxAppDependencies.swift#L333-L339: build the UI-testing settings from TerminalSettings.default and assign zoomMultipaneWindowsByDefault = deviceDefaultZoomMultipaneWindows on the copy.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift` around lines
16 - 20, Replace the hand-written TerminalSettings initializer in
RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift#L16-L20 with a
copy of TerminalSettings.default, then override zoomMultipaneWindowsByDefault
with defaultZoomMultipaneWindows. Apply the same change in
RemuxApp/Sources/App/RemuxAppDependencies.swift#L333-L339, overriding the copied
default with deviceDefaultZoomMultipaneWindows.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@RemuxApp/Sources/Tmux/TmuxSessionController.swift`:
- Around line 856-869: Update the shutdown flow involving
prepareForSessionShutdown(), submitWindowZoom(), and shutdown() so deferred zoom
intents created during session shutdown are preserved and processed rather than
discarded when shutdown clears deferredWindowZoomIntent. Use a shutdown-safe
queue or drain the deferred intent before clearing shutdown state, ensuring the
cleanup requestSetWindowsZoomed(zoomed: false) is ultimately submitted for
Remux-owned windows.

In `@RemuxApp/Sources/Tmux/TmuxTerminalScreenAdapter.swift`:
- Around line 172-173: Update the `.zoomPane` failure handling around
requestSetWindowsZoomed so it removes only the failed window’s pending ownership
ID instead of clearing pendingZoomOwnershipWindowIDs globally. Preserve pending
IDs for successful grouped commands until topology confirms the window changed
or disappeared, allowing them to enter ownedZoomWindowIDs and be cleaned up on
shutdown.

---

Nitpick comments:
In `@RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift`:
- Around line 16-20: Replace the hand-written TerminalSettings initializer in
RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift#L16-L20 with a
copy of TerminalSettings.default, then override zoomMultipaneWindowsByDefault
with defaultZoomMultipaneWindows. Apply the same change in
RemuxApp/Sources/App/RemuxAppDependencies.swift#L333-L339, overriding the copied
default with deviceDefaultZoomMultipaneWindows.

In `@RemuxAppTests/TmuxSessionControllerClientSizeTests.swift`:
- Around line 1121-1128: Remove the unused paneID parameter from
assertCommandWrite and update every call site to omit the paneID: argument,
leaving the existing write assertion unchanged.
- Around line 436-446: Remove the duplicate test
testShutdownUnzoomSendsOnlyTheTmuxMutation, or rename and revise it to cover the
actual shutdown cleanup path by invoking requestSetWindowsZoomed before
shutdown(). Preserve testExplicitUnzoomTogglesAnAuthoritativelyZoomedWindow for
the direct unzoom mutation assertion.

In `@RemuxAppTests/TmuxTerminalScreenAdapterTests.swift`:
- Around line 139-163: Add a test alongside the existing
TmuxMultipaneZoomDefaultPolicy tests that uses topology(zoomed: false,
paneCount: 3) with the policy enabled and asserts windowIDsNeedingChange returns
[1], confirming windows with more than two panes are treated as multipane.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fa0511db-4047-4561-80b7-3e955d40c7b3

📥 Commits

Reviewing files that changed from the base of the PR and between 5b05e6f and 5d24e0e.

📒 Files selected for processing (15)
  • RemuxApp/Sources/App/RemuxAppDependencies.swift
  • RemuxApp/Sources/App/RootView.swift
  • RemuxApp/Sources/Domain/TerminalSettings.swift
  • RemuxApp/Sources/Ghostty/GhosttySurfaceScreen.swift
  • RemuxApp/Sources/Persistence/TerminalSettingsRepository.swift
  • RemuxApp/Sources/Tmux/TmuxScreenModel.swift
  • RemuxApp/Sources/Tmux/TmuxSessionController.swift
  • RemuxApp/Sources/Tmux/TmuxTerminalScreenAdapter.swift
  • RemuxApp/Sources/Tmux/TmuxTerminalSession.swift
  • RemuxAppTests/RemuxRootModelTests.swift
  • RemuxAppTests/TerminalSettingsRepositoryTests.swift
  • RemuxAppTests/TerminalSettingsTests.swift
  • RemuxAppTests/TmuxSessionControllerClientSizeTests.swift
  • RemuxAppTests/TmuxTerminalScreenAdapterTests.swift
  • RemuxAppUITests/RemuxAppUITests.swift
💤 Files with no reviewable changes (1)
  • RemuxApp/Sources/Tmux/TmuxTerminalSession.swift

Comment on lines +856 to +869
private func submitWindowZoom(_ intent: WindowZoomIntent) {
preconditionOnWriterQueue()
guard !awaitingTopologyMutationSettlement else {
deferredWindowZoomIntent = intent
return
}
deferredWindowZoomIntent = nil
enqueueWindowsZoom(
intent.windowIDs,
desired: intent.desired,
onZoomSubmitted: intent.onZoomSubmitted,
drainOutbound: true
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Trace the shutdown-time zoom cleanup ordering.
set -euo pipefail

# Find where prepareForSessionShutdown is invoked relative to controller shutdown.
rg -n -C 12 'prepareForSessionShutdown' --glob '*.swift'

# Inspect the session/model shutdown paths that drive the controller.
rg -n -C 10 'controller\.shutdown|func shutdown' RemuxApp/Sources/Tmux --glob '*.swift'

Repository: h3nock/remux

Length of output: 150


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Tracked Swift files containing relevant identifiers:\n'
git ls-files '*.swift' | xargs rg -n 'prepareForSessionShutdown|func shutdown|deferredWindowZoomIntent|awaitingTopologyMutationSettlement|requestSetWindowsZoomed|enqueueWindowsZoom|submitWindowZoom' || true

printf '\nRelevant Tmux directory files:\n'
git ls-files 'RemuxApp/Sources/Tmux/*.swift' || true

Repository: h3nock/remux

Length of output: 5279


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'TmuxScreenModel shutdown path:\n'
sed -n '300,345p' RemuxApp/Sources/Tmux/TmuxScreenModel.swift

printf '\nTmuxTerminalScreenAdapter prepare request:\n'
sed -n '980,1030p' RemuxApp/Sources/Tmux/TmuxTerminalScreenAdapter.swift

printf '\nTmuxSessionController zoom/deferred areas:\n'
sed -n '800,895p' RemuxApp/Sources/Tmux/TmuxSessionController.swift
sed -n '950,995p' RemuxApp/Sources/Tmux/TmuxSessionController.swift
sed -n '1014,1030p' RemuxApp/Sources/Tmux/TmuxSessionController.swift
sed -n '1125,1135p' RemuxApp/Sources/Tmux/TmuxSessionController.swift
sed -n '1350,1370p' RemuxApp/Sources/Tmux/TmuxSessionController.swift

printf '\nTmuxSessionController shutdown:\n'
sed -n '320,380p' RemuxApp/Sources/Tmux/TmuxSessionController.swift

printf '\nTmuxTerminalSession shutdown definitions:\n'
sed -n '120,155p' RemuxApp/Sources/Tmux/TmuxTerminalSession.swift

Repository: h3nock/remux

Length of output: 14933


Propagate deferred zoom cleanup through session shutdown.

TmuxScreenModel.stop() calls prepareForSessionShutdown() before session.shutdown(), so a cleanup requestSetWindowsZoomed(zoomed: false) can enter submitWindowZoom while awaitingTopologyMutationSettlement is true. submitWindowZoom then replaces deferredWindowZoomIntent, and shutdown() clears it. Move deferred zoom intents into a shutdown-safe queue or admit them from the deferred store before clearing shutdown state so zoomed Remux-owned windows are not left zoomed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@RemuxApp/Sources/Tmux/TmuxSessionController.swift` around lines 856 - 869,
Update the shutdown flow involving prepareForSessionShutdown(),
submitWindowZoom(), and shutdown() so deferred zoom intents created during
session shutdown are preserved and processed rather than discarded when shutdown
clears deferredWindowZoomIntent. Use a shutdown-safe queue or drain the deferred
intent before clearing shutdown state, ensuring the cleanup
requestSetWindowsZoomed(zoomed: false) is ultimately submitted for Remux-owned
windows.

Comment on lines +172 to 173
self?.pendingZoomOwnershipWindowIDs.removeAll()
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Keep ownership tracking for successful grouped zoom commands.

Line 172 clears every pending window when one .zoomPane command fails. requestSetWindowsZoomed submits one command per target window. A successful command can complete before its topology update. If a later command in that group fails, the successful window cannot enter ownedZoomWindowIDs when topology arrives. Session shutdown can then leave a Remux-created zoom on the server.

Track completion and failure per window, or retain each pending ID until topology confirms that window changed or disappeared.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@RemuxApp/Sources/Tmux/TmuxTerminalScreenAdapter.swift` around lines 172 -
173, Update the `.zoomPane` failure handling around requestSetWindowsZoomed so
it removes only the failed window’s pending ownership ID instead of clearing
pendingZoomOwnershipWindowIDs globally. Preserve pending IDs for successful
grouped commands until topology confirms the window changed or disappeared,
allowing them to enter ownedZoomWindowIDs and be cleaned up on shutdown.

@h3nock
h3nock merged commit e7c312e into main Aug 7, 2026
6 checks passed
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.

Make display full layout optional

1 participant