Skip to content

feat(desktop): persist and restore main window geometry and maximized state - #29

Merged
thtbee merged 3 commits into
thtbee:mainfrom
jochenkirstaetter:feat/window-geometry
Oct 19, 2026
Merged

thtbee merged 3 commits into
thtbee:mainfrom
jochenkirstaetter:feat/window-geometry

Conversation

@jochenkirstaetter

@jochenkirstaetter jochenkirstaetter commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

persist and restore main window geometry and maximized state

What and why

Referring #26 and how this fixes matters.
It was part of other commits and this is the isolated PR.

How it was tested

Includes round-trip persistence assertions in save_and_load_round_trip plus a dedicated window_geometry_sanitization_and_runtime_state test covering min/max dimension clamping (MIN_WINDOW_WIDTH..=7680, MIN_WINDOW_HEIGHT..=4320), partial coordinate sanitization, and set_window_geometry / window_geometry.

Checklist

  • ./scripts/check.ps1 passes (or the CI equivalent for the parts I changed)
  • User-facing strings are translatable, and new UI works with keyboard and screen readers
  • No personal content (notification text, messages, file names, keys) is logged
  • Commits are signed off (git commit -s), see CONTRIBUTING.md

@jochenkirstaetter
jochenkirstaetter marked this pull request as ready for review October 18, 2026 20:57

@thtbee thtbee left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for this. It's a big step up from today, where nothing is saved at all. A few things before it can go in:

  1. The minimum size differs between QML and Rust. Tokens.qml has minWindow: [880, 600], but MIN_WINDOW_WIDTH and MIN_WINDOW_HEIGHT are 900 and 620, and both save_window_geometry and set_window_geometry clamp to them. A window sized to 880 wide is saved as 900, so it grows a little every time. I'd keep one source: the Rust side can store what it gets, with only a sanity range.
  2. Which monitor it was on. As we discussed on #26, the position should be kept per monitor (its name, plus the offset on it). Right now it's stored in desktop coordinates, so after monitors are rearranged or swapped, restoreAndBringToFront either keeps a spot on the wrong monitor or falls back. The fallback also clamps against Screen.desktopAvailableWidth, which is the screen the window is on right now rather than the primary one, and lets x go down to -targetW + 120, so the window can open mostly off screen. Opening centered on the primary screen in that case would be safer.
  3. The wantBackdrop change is already part of #23, so the two would conflict. Could you leave it out here?
  4. The test changes global state. window_geometry_sanitization_and_runtime_state sets WINDOW_GEOMETRY, and another test in settings.rs calls apply_runtime() on defaults in parallel, which resets it. Testing sanitized() and the clamping without touching the static would avoid flaky runs.

On Wayland, x and y read as 0 and setting them does nothing, so only size and maximized come back. That's fine, but a short comment in restoreAndBringToFront saying so would help the next reader.

@jochenkirstaetter jochenkirstaetter changed the title feat(desktop): persist and restore main window geometry and maximized… feat(desktop): persist and restore main window geometry and maximized state Oct 18, 2026
@jochenkirstaetter

Copy link
Copy Markdown
Contributor Author

Hi @thtbee

Ahh yes, I was too quick on the Request Review button(s).
Of course, I'll review and amend those issue you provided me feedback for. Let me put this back to draft mode until then.

Cheers

@jochenkirstaetter
jochenkirstaetter marked this pull request as draft October 18, 2026 21:09
@jochenkirstaetter
jochenkirstaetter force-pushed the feat/window-geometry branch 2 times, most recently from 4597b69 to 972e2da Compare October 18, 2026 21:36
@jochenkirstaetter
jochenkirstaetter marked this pull request as ready for review October 18, 2026 21:45
… state

Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>

@thtbee thtbee left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks for working through all of that so quickly. Saving the monitor with a position relative to it, centering on the primary when it's gone, one minimum size, and the Wayland note all look right, and the test no longer touches global state.

One thing I checked on Windows: Qt names monitors there \.\DISPLAY1, \.\DISPLAY2 and so on. Those numbers are assigned by Windows and can swap when monitors are reconnected or a laptop docks, so the window could come back on the wrong monitor. On this PC the same screen reports a manufacturer and a serial number (BOE, 103), which stay with the monitor. Could screenKey prefer manufacturer, model and serial when they're there, and fall back to the name? Linux's connector names (DP-1, HDMI-A-1) have the same issue to a lesser degree, so it helps there too.

With that, this looks ready to me.

jochenkirstaetter and others added 2 commits October 19, 2026 05:17
Windows assigns display numbers (\.\DISPLAY1, \.\DISPLAY2) dynamically and
Linux connector names (DP-1, HDMI-A-1) can change across ports. Prefer the
monitor's EDID-backed manufacturer, model, and serialNumber when available,
falling back to s.name.

Signed-off-by: Jochen Kirstätter <7329802+jochenkirstaetter@users.noreply.github.com>
Signed-off-by: Bee <302257494+thtbee@users.noreply.github.com>

@thtbee thtbee left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Looks good to me now. I pushed one small commit on top: the restore code read desktopAvailableWidth/Height, which covers the whole virtual desktop, so with two monitors the first start centered across both. It uses each monitor's own size now. Everything else from the earlier review is sorted, thanks for working through all of it.

@thtbee
thtbee merged commit f02205a into thtbee:main Oct 19, 2026
6 checks passed
thtbee added a commit that referenced this pull request Oct 19, 2026
The window position change (#29) used two things NativeWindow's QML type
doesn't expose: an onWindowVisibilityChanged handler, which stopped
MainWindow.qml from loading at all, and the `screen` property, which
stopped the restore before the window was shown. Visibility is now
followed through Connections, and the position alone picks the monitor.

On Windows a size set before the first show comes out taller by the
title bar, so the window grew on every start; it's set again once shown.
Maximizing changes the size before the visibility, so the normal size
was overwritten by the maximized one; it's now taken only when the save
runs, which checks the visibility.

Checked on a test copy: same place and size over restarts, maximized
reopens maximized, and un-maximizing returns to the saved size.
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