Skip to content

Let a repeated Maximize restore the window's previous size and position (opt-in) - #1837

Merged
rxhanson merged 1 commit into
rxhanson:mainfrom
maxing-labs:repeated-maximize-restores-previous
Sep 7, 2026
Merged

Let a repeated Maximize restore the window's previous size and position (opt-in)#1837
rxhanson merged 1 commit into
rxhanson:mainfrom
maxing-labs:repeated-maximize-restores-previous

Conversation

@X-Wei

@X-Wei X-Wei commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds an opt-in mode in which running Maximize (or Almost Maximize) again on a window Rectangle has just maximized moves it back to the size and position it had right before, so the shortcut toggles between maximized and the previous frame — the way toggling maximize works on KDE.

Today repeating Maximize on an already-maximized window does nothing, and getting the window back means the Restore shortcut, which also undoes every other Rectangle action since you last placed the window. This keeps Maximize and Restore as they are and only adds "press again to go back", behind a single default.

Off by default (repeatedMaximizeRestoresPrevious); nothing changes unless it is enabled.

Related: discussion #894 (requested there; you implemented it in Rectangle Pro). This is the narrow free-Rectangle version — no new shortcut, one self-contained type, one default. Same shape as #1824.

Behavior when enabled

  • Maximize on a window Rectangle just maximized → the window returns to its previous frame. Maximize again → maximized again. (Same for Almost Maximize.)
  • Only the same action repeated restores: Maximize then Almost Maximize (or the reverse) switches between the two, as today.
  • A window maximized by something else, or moved/resized between the two presses, is maximized as usual — the previous frame is used only when Maximize was the last thing Rectangle did to the window and it has not moved since.
  • Restoring reuses the Restore action's semantics (clears the window's last-action history; leaves the Restore rect untouched).
  • With the repeated-command setting on "Cycle through displays", the restore takes precedence over display cycling for these two actions.
  • Works from the shortcut, the menu bar and the URL scheme.

How it works

  • The frame is captured in WindowHistory.preMaximizeRects whenever Maximize / Almost Maximize runs.
  • The repeat is recognized from the window history exactly like the title-bar double-click restore (TitleBarManager): the window's last action is the same action and it has not moved since. No new geometry or heuristics.
  • All the decision logic lives in one new type, RepeatedMaximizeRestore, consulted in WindowManager.execute (and in the display-cycling shortcut path).

Docs / Tests

I'm happy to drop the checkbox and keep it Terminal-only if you'd prefer, like some of the other hidden defaults.

@rxhanson

rxhanson commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Thanks for taking this one on. Would you mind keeping all of the Maximize logic within the MaximizeCalculation, instead of in the WindowManager? Ideally we want to keep execute in the WindowManager as free from special cases for specific window actions as possible.

Executing Maximize or Almost Maximize on a window that is already in that
state does nothing, so getting the window back takes the Restore shortcut,
which also undoes every other Rectangle action since the user last placed
the window. Behind the new repeatedMaximizeRestoresPrevious default, the
same action executed again on a window Rectangle has just maximized (or
almost maximized) moves it back to the frame it had right before, so the
shortcut toggles between the two.

The frame to come back to is recorded in WindowHistory.preMaximizeRects
whenever one of the two calculations runs. The repeat is recognized from the
window history the way the title bar double-click restore does: the last
action on the window is the same action and the window has not been moved
since, so a window maximized by other means is maximized as usual, and so is
a window whose last action was the other one of the two (Maximize and Almost
Maximize keep switching between each other). The restore is reported as
.restore, so it is applied without gaps and the next execution of the action
maximizes the window again, calculated from scratch. With the
repeated-command setting on "Cycle through displays" the restore takes
precedence over the display cycling for those two actions. The default is
off; with it off nothing changes.

- Add RepeatedMaximizeRestore.swift with the decision logic
- Consult it from the Maximize and Almost Maximize calculations, and in the
  display-cycling check
- Add RepeatedMaximizeRestoreTests (13 cases)
- Document the default in TerminalCommands.md
- Expose it as a "Repeated Maximize restores the previous size and
  position" checkbox, unchecked by default, at the bottom of the Extras
  popover in the General settings tab (title and tooltip registered in
  Main.xcstrings)
@X-Wei
X-Wei force-pushed the repeated-maximize-restores-previous branch from 6f6789b to c5f979b Compare September 6, 2026 14:04
@X-Wei

X-Wei commented Sep 6, 2026

Copy link
Copy Markdown
Contributor Author

Done — all of the logic lives in the calculations now, and WindowManager is back to a zero diff against main.

  • MaximizeCalculation and AlmostMaximizeCalculation each got a one-line calculate(_:) override that consults RepeatedMaximizeRestore first and otherwise falls through to super.
  • It has to sit in calculate(_:) rather than calculateRect(_:): NextPrevDisplayCalculation calls maximizeCalculation.calculateRect(_:) directly for the auto-maximize path, and that one shouldn't turn into a restore.
  • The restore is returned as a regular calculation result reported as .restore, instead of setting the frame directly. So it goes through the usual pipeline, gets no gaps, and because the window's last action is then a restore, the next execution of the shortcut maximizes it again, calculated from scratch rather than reusing an older frame.
  • The one thing left outside the calculation is a one-line guard in ShortcutManager, so that the restore wins over display cycling when the repeated-command setting is "Cycle through displays". Happy to drop that as well if you'd rather leave that path alone.

Tests went from 7 to 13 cases and the full suite is green. Also rebased onto current main.

@rxhanson
rxhanson merged commit 1840ff2 into rxhanson:main Sep 7, 2026
1 check 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.

2 participants