Add window.openAtFixedSize fixed-window-size config - #5466
austinywang wants to merge 8 commits into
Conversation
Introduce the pure window-open-size policy + frame-source precedence types in CmuxSettings, plus a unit test asserting that with the fixed-size option enabled a new window opens at the configured size instead of the persisted last-window geometry (and that disabling it keeps persisted geometry). The resolver intentionally omits the fixed-size branch in this commit so the precedence test goes red; the fix commit adds the branch and wires the feature end to end. Proves the test catches the behavior per the two-commit policy. Issue: #5461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Opt-in window.* config to open new main windows at a configured width × height (points) instead of restoring the last-used window size, mirroring Ghostty's fixed-size-on-launch behavior. Default off, so existing restore-last behavior is unchanged until enabled. Precedence (highest first): full session restore → fixed size → source-window match (Cmd-Shift-N) → persisted last-window geometry → built-in default. Fixed size overrides the source-window match and the persisted geometry for every freshly created window, but session-restored frames still win so a saved multi-window layout keeps each window's exact geometry. The size/precedence logic is a pure, value-typed resolver (WindowOpenSizeSettings + InitialWindowFrameSource) in CmuxSettings, unit-tested without launching the app; AppDelegate maps the decision to AppKit geometry via CmuxMainWindow.fixedSizeContentRect (clamped to the visible screen, no 1000×700 floor) and routes fixed/default windows through center + cascade. Wired end to end like markdown.* / browser.*: web schema + descriptions, CmuxSettings catalog, cmux.json parse + template + supported paths, Settings UI rows (App section) + search aliases, configuration docs, and en/ja Localizable strings. schemaDescriptions.window.* and exampleWindow* added across all 20 web message catalogs. Closes #5461 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Wondering what really moved? Review this PR in Change Stack to inspect semantic changes, definitions, and references. Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds an opt-in window sizing feature: new catalog keys and defaults, policy + precedence resolution, app delegate wiring and fixed-size content-rect helper, config parsing and template support, settings UI and localized strings, web schema/docs updates, and tests. ChangesFixed-size window opening configuration
Sequence Diagram(s)sequenceDiagram
participant AppSection
participant DefaultsStore
participant WindowOpenSizeSettings
participant AppDelegate
participant CmuxMainWindow
AppSection->>DefaultsStore: set catalog.window.openAtFixedSize / width / height
DefaultsStore->>WindowOpenSizeSettings: read(from: defaults)
AppDelegate->>WindowOpenSizeSettings: resolveInitialFrameSource(fixedContentSize:, restoredFrame:, sourceWindowFrame:, persistedGeometryFrame:)
WindowOpenSizeSettings-->>AppDelegate: InitialWindowFrameSource
AppDelegate->>CmuxMainWindow: fixedSizeContentRect(contentSize:, styleMask:) (when frameSource==fixedSize)
CmuxMainWindow-->>AppDelegate: content rect (clamped to display)
AppDelegate->>CmuxMainWindow: create & setFrame / positionNewMainWindow (apply resolved frame)
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
Caution Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional.
❌ Failed checks (1 error, 1 warning)
✅ Passed checks (17 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis PR adds an opt-in
Confidence Score: 5/5Safe to merge — the feature is default-off, session restore continues to win, and the precedence logic is covered by unit tests that run without launching the app. The resolver is a pure value-type function with no AppKit dependency, tested across all five precedence branches. The two AppKit integration points (fixedSizeContentRect and the startup geometry guard) follow the existing patterns for defaultContentRect and the session-restore gate. Managed UserDefaults written by parseWindowSection flow through UserDefaults.standard, which WindowOpenSizeSettings.read(from: .standard) correctly reads. i18n is complete across all 20 locales in both the app string catalog and the web messages directory. No files require special attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[createMainWindow called] --> B{restoredFrame from session?}
B -- Yes --> C[".restored(frame)"]
B -- No --> D{openAtFixedSize enabled?}
D -- Yes --> E[".fixedSize(configuredSize)"]
D -- No --> F{sourceWindow exists?}
F -- Yes --> G[".sourceWindow(frame)"]
F -- No --> H{persistedGeometry exists?}
H -- Yes --> I[".persistedGeometry(frame)"]
H -- No --> J[".fallbackDefault"]
C --> K["window.setFrame(restoredFrame)"]
E --> L["fixedSizeContentRect → center + cascade"]
G --> M["contentRect from sourceFrame → positionNewMainWindow"]
I --> N["window.setFrame(persistedFrame)"]
J --> O["defaultContentRect → center + cascade"]
P[App launch startup path] --> Q{full session restore?}
Q -- Yes --> R[restore session windows]
Q -- No --> S{shouldRestorePersistedStartupGeometry?}
S -- false: openAtFixedSize=on --> T[skip — window already at fixed size]
S -- true: openAtFixedSize=off --> U[apply persisted geometry to primary window]
Reviews (6): Last reviewed commit: "Capture startup-overwrite regression beh..." | Re-trigger Greptile |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 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 `@web/messages/de.json`:
- Around line 743-747: The German locale file web/messages/de.json contains
new/updated user-facing strings still in English (keys like
schemaDescriptions.window.openAtFixedSize, schemaDescriptions.window.width,
schemaDescriptions.window.height and related exampleWindow* and
exampleMarkdownMaxWidth entries); replace those English strings with proper
German translations matching the other locale catalogs so the de.json is fully
localized and consistent (update the values for schemaDescriptions.window.*,
exampleWindow*, exampleMarkdownMaxWidth to their German equivalents and verify
similar entries at lines referenced like 752-755 are also translated).
In `@web/messages/es.json`:
- Around line 744-746: The Spanish locale file still contains English text for
the docs.configuration keys; update the values for "openAtFixedSize", "width",
and "height" in web/messages/es.json to proper Spanish translations (and
likewise fix the other newly added docs.configuration entries referenced around
the same area, e.g., the keys noted near lines 752-755) so the Spanish docs
render fully localized; locate the keys "openAtFixedSize", "width", and "height"
in the JSON and replace the English strings with accurate Spanish equivalents.
In `@web/messages/fr.json`:
- Around line 743-756: Replace the English strings added under the French
localization with proper French translations: update
schemaDescriptions.window.openAtFixedSize, schemaDescriptions.window.width,
schemaDescriptions.window.height and the example keys
exampleWindowOpenAtFixedSize, exampleWindowWidth, exampleWindowHeight (and
ensure exampleMarkdownFontSize/FontFamily/FontSizeZoom remain correctly
localized if applicable) by providing native French text matching the rest of
fr.json style; locate those keys in the diff and replace the English sentences
with concise French equivalents preserving placeholders/units (e.g., "Ouvrir les
nouvelles fenêtres à la largeur et hauteur fixes ci‑dessous..." for
openAtFixedSize, "Largeur de fenêtre fixe, en points..." for width, etc.).
In `@web/messages/no.json`:
- Around line 743-746: Replace the English strings for the docs.configuration
"window" entries in the Norwegian locale with proper Norwegian translations:
update "window.openAtFixedSize" to a Norwegian sentence (e.g., "Åpne nye vinduer
med fast bredde og høyde som angitt nedenfor i stedet for å gjenopprette siste
brukte vindusstørrelse. Vinduer gjenopprettet fra en lagret økt bevarer sin egen
størrelse."), "window.width" to something like "Fast vindusbredde i punkter som
brukes når openAtFixedSize er aktivert.", and "window.height" to "Fast
vindushøyde i punkter som brukes når openAtFixedSize er aktivert."; also scan
the nearby entries referenced in the comment (the other strings around the same
block) and translate those (lines noted as 753–755) so the Norwegian locale
contains no remaining English fallbacks.
In `@web/messages/pt-BR.json`:
- Around line 743-746: The pt-BR locale is missing Portuguese text for the
window configuration entries; replace the English strings with native Portuguese
translations for the keys
configuration.schemaDescriptions.window.openAtFixedSize,
configuration.schemaDescriptions.window.width,
configuration.schemaDescriptions.window.height and the example keys
configuration.exampleWindowOpenAtFixedSize, configuration.exampleWindowWidth,
configuration.exampleWindowHeight (also update the same entries around lines
754-756) by providing the corresponding Portuguese copy for each string so all
user-facing messages in web/messages/pt-BR.json are translated.
In `@web/messages/ru.json`:
- Around line 743-746: The new Russian locale entries for docs.configuration are
still in English; update the Russian file entries for schemaDescriptions.window
keys ("openAtFixedSize", "width", "height") and the example keys referenced as
"exampleWindow*" and "exampleMarkdownMaxWidth" to proper Russian translations so
the ru.json no longer contains English fallback text; locate those keys in
web/messages/ru.json (the "window" block and the example* keys) and replace the
English strings with accurate Russian translations consistent with other locale
phrasing.
In `@web/messages/uk.json`:
- Around line 743-747: The Ukrainian locale file currently contains untranslated
English entries for the window schema keys—specifically the "window" object and
its properties "openAtFixedSize", "width", "height" (and the related
"exampleWindow*" entries)—which causes mixed-language UI text; update
web/messages/uk.json by translating those keys' values into Ukrainian
(preserving the JSON keys exactly: window.openAtFixedSize, window.width,
window.height and any exampleWindow* keys) so the Ukrainian catalog provides
full i18n coverage for these user-facing strings.
In `@web/messages/zh-CN.json`:
- Around line 743-746: The Simplified Chinese locale file left the new
window-related keys untranslated; update the zh-CN.json entries for the "window"
object—specifically "openAtFixedSize", "width", and "height"—to provide proper
Chinese translations matching the user-facing English text so the configuration
UI is fully localized (also apply the same fix for the other missing entries
referenced at lines 753–755).
In `@web/messages/zh-TW.json`:
- Around line 743-746: The new "window" localization block in
web/messages/zh-TW.json contains English values for the keys "openAtFixedSize",
"width", and "height"; translate those three strings into Traditional Chinese
and replace the English text for the corresponding keys (also update the
duplicate entries referenced around lines 753–755) so the zh-TW locale contains
fully localized copy for "window.openAtFixedSize", "window.width", and
"window.height".
🪄 Autofix (Beta)
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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 4e35906c-9aaa-4a6b-81a1-cf20a97fa6a0
📒 Files selected for processing (35)
Packages/CmuxSettings/Sources/CmuxSettings/Keys/SettingCatalog.swiftPackages/CmuxSettings/Sources/CmuxSettings/Keys/WindowCatalogSection.swiftPackages/CmuxSettings/Sources/CmuxSettings/Window/InitialWindowFrameSource.swiftPackages/CmuxSettings/Sources/CmuxSettings/Window/WindowOpenSizeSettings.swiftPackages/CmuxSettings/Tests/CmuxSettingsTests/WindowOpenSizeSettingsTests.swiftPackages/CmuxSettingsUI/Sources/CmuxSettingsUI/Navigation/CuratedSettingEntry+Default.swiftPackages/CmuxSettingsUI/Sources/CmuxSettingsUI/Sections/AppSection.swiftResources/Localizable.xcstringsSources/App/CmuxMainWindow.swiftSources/AppDelegate.swiftSources/CmuxSettingsJSONPathSupport.swiftSources/KeyboardShortcutSettingsFileStore+Template.swiftSources/KeyboardShortcutSettingsFileStore.swiftweb/app/[locale]/docs/configuration/page.tsxweb/data/cmux.schema.jsonweb/messages/ar.jsonweb/messages/bs.jsonweb/messages/da.jsonweb/messages/de.jsonweb/messages/en.jsonweb/messages/es.jsonweb/messages/fr.jsonweb/messages/it.jsonweb/messages/ja.jsonweb/messages/km.jsonweb/messages/ko.jsonweb/messages/no.jsonweb/messages/pl.jsonweb/messages/pt-BR.jsonweb/messages/ru.jsonweb/messages/th.jsonweb/messages/tr.jsonweb/messages/uk.jsonweb/messages/zh-CN.jsonweb/messages/zh-TW.json
The three new window.* Settings rows add curated search entries, which the everyCuratedSettingEntryIsReachable test requires to map to a scrollable row anchor. Add window.openAtFixedSize/width/height to rowConfigPaths so the search results resolve to their rows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 6a8d582. Configure here.
- Startup session restore reapplied the persisted last-window geometry onto the primary window even when window.openAtFixedSize was on, clobbering the fixed dimensions createMainWindow had just set. Gate the persisted-geometry reapply on the fixed-size option being off so a fixed-size launch keeps the configured size. (Cursor Bugbot, medium.) - Translate the new window.* schema descriptions and example strings from English placeholders into all 18 non-en/ja web message catalogs. (CodeRabbit.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add translations for the three new window.* Settings rows (titles + subtitles) to every app locale in Localizable.xcstrings, matching the full-locale-set entries rather than the en/ja-only stubs. (Greptile.) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@web/messages/th.json`:
- Line 753: The Thai translation for the key exampleWindowOpenAtFixedSize omits
the required “restored sessions keep their own window size” clause; update the
string for exampleWindowOpenAtFixedSize to include the equivalent Thai wording
for that rule so it matches the schemaDescriptions.window.* and other
exampleWindow* keys (i.e., append or integrate the phrase stating restored
sessions retain their own window size into the existing Thai sentence for
exampleWindowOpenAtFixedSize).
🪄 Autofix (Beta)
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: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 0256bec1-cf08-4156-93db-4610fb3919e7
📒 Files selected for processing (19)
Sources/AppDelegate.swiftweb/messages/ar.jsonweb/messages/bs.jsonweb/messages/da.jsonweb/messages/de.jsonweb/messages/es.jsonweb/messages/fr.jsonweb/messages/it.jsonweb/messages/km.jsonweb/messages/ko.jsonweb/messages/no.jsonweb/messages/pl.jsonweb/messages/pt-BR.jsonweb/messages/ru.jsonweb/messages/th.jsonweb/messages/tr.jsonweb/messages/uk.jsonweb/messages/zh-CN.jsonweb/messages/zh-TW.json
…-5461-fixed-window-size
Extract the startup persisted-geometry reapply decision into a pure, testable WindowOpenSizeSettings.shouldRestorePersistedStartupGeometry() and use it from AppDelegate, so both window-sizing entrypoints share one policy path. Add regression tests asserting that with the fixed-size option on, startup does NOT reapply persisted geometry (the bug Cursor caught), and that both entrypoints honor the fixed size over persisted geometry. Verified the tests go red when the gate is removed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Closes #5461
What
Adds an opt-in
window.*config so cmux can open new main windows at a configured fixed width × height (points) instead of restoring the last-used window size — the Ghostty-like "open at fixed dimensions on launch" the issue asks for. Default off, so existing restore-last behavior is unchanged until enabled.cmux deliberately does not read Ghostty's
window-width/window-height(those are terminal cells, which don't map to cmux's tabbed/sidebar app window). This is a dedicated cmux config in points.Precedence
Highest first:
window.openAtFixedSize) — overrides the source-window match and the persisted last-window geometry for every freshly created window.Design
The size + precedence logic is a pure, value-typed resolver in
CmuxSettings(WindowOpenSizeSettings+InitialWindowFrameSource) with no AppKit dependency, so it is unit-tested without launching the app.AppDelegatemaps the decision to AppKit geometry viaCmuxMainWindow.fixedSizeContentRect(clamped to the visible screen, honoring sizes below the 1000×700 default), and routes fixed/default windows through center + cascade.Wired end to end (mirrors
markdown.*/browser.*)web/data/cmux.schema.json+schemaDescriptions.window.*andexampleWindow*across all 20web/messages/*.jsoncatalogsCmuxSettingscatalog (WindowCatalogSection)cmux.jsonparse (parseWindowSection), template, and supported JSON pathsResources/Localizable.xcstrings(en + ja) for the new Settings stringsTests (two-commit red → green)
WindowOpenSizeSettingsTestswith the resolver's fixed-size branch omitted → the precedence tests go red.The key assertions: with the fixed-size option enabled a new window resolves to the configured size instead of the persisted geometry; with it disabled the persisted geometry is still used; full session restore always wins. Pure package test — runs without launching the app.
🤖 Generated with Claude Code
Need help on this PR? Tag
/codesmithwith what you need. Autofix is disabled.Note
Medium Risk
Touches main-window creation and launch geometry in AppDelegate; behavior is gated behind a default-off setting and covered by precedence/startup tests, but window sizing affects every user who enables it.
Overview
Adds opt-in
window.*settings so new main windows can open at a fixed width × height (points) instead of restoring the last-used size. Default is off; full session restore still wins over fixed size.Policy layer: New
WindowOpenSizeSettingsandInitialWindowFrameSourceinCmuxSettingsdefine precedence (session → fixed → source window → persisted geometry → default) and a startup gate so persisted geometry is not reapplied on launch when fixed size is enabled.App behavior:
createMainWindowuses the resolver;CmuxMainWindow.fixedSizeContentRectapplies configured sizes (screen-clamped, no 1000×700 floor). Startup only restores persisted geometry when fixed size is disabled.Product surface: Catalog keys, App settings UI (toggle + width/height steppers),
cmux.jsonparse/template/schema, docs, locales, and unit tests for resolver and startup behavior.Reviewed by Cursor Bugbot for commit b0a72e2. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Adds an opt-in
window.*setting to open new main windows at a fixed width × height (points) instead of restoring the last-used size. Default is off; full session restore still wins. Also adds a startup policy gate so fixed-size windows aren’t overwritten on launch.New Features
window.openAtFixedSize,window.width,window.heightacrosscmux.schema.json,cmux.jsonparsing/template, Settings UI (with search anchors), docs, and all locales.CmuxSettings(WindowOpenSizeSettings,InitialWindowFrameSource) with precedence: session restore → fixed size → source-window match (Cmd-Shift-N) → persisted geometry → default;AppDelegateapplies it viaCmuxMainWindow.fixedSizeContentRect(screen-clamped, no 1000×700 floor).Bug Fixes
WindowOpenSizeSettings.shouldRestorePersistedStartupGeometry(), preventing the configured size from being clobbered.Written for commit b0a72e2. Summary will update on new commits.
Summary by CodeRabbit
New Features
Configuration
Behavior
Documentation & Localization
Tests