From 646b37e7e3aa5931079c6b9e804f420bb43c74d5 Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Mon, 11 May 2026 16:57:00 +0200 Subject: Fix spawn placement under the top bar, add per-window minimum sizes, and clean up maximize Four reports after restarting into today's build, with a screenshot. The screenshot was measured, not eyeballed: top bar y=0..29, a 4px accent border at y=30..33, titlebar from y=34, bottom border at y=1027..1030, and 49px of bare desktop below it. Windows spawning too close to the top bar. A remembered position was validated only by asking whether it landed on some monitor's full_geometry, which includes the strip a top bar reserves, so an app whose remembered y was small reopened with its titlebar under the bar. That is why it was "sometimes": it depended on the stored value, and the live store holds wezterm at y=44 and firefox at y=69 against a 30px bar. Remembered positions are now clamped into the monitor's usable area. Placement not surviving a logout. Window memory does persist, but five of the eleven entries in the live store were saved with a second monitor attached, at x >= 2000. Those points match no current monitor and were discarded outright, falling back to a fresh cascade, so those apps appeared to remember nothing. Such a position is now clamped onto a monitor that exists instead. Per-window minimum sizes. One global floor is wrong in both directions. Three sources now, in increasing precedence: the global floor, the client's own declared minimum (xdg_toplevel.set_min_size or ICCCM hints), and a min_width/min_height window rule overriding both. A rule wins permanently -- the backend refreshes the client's declared minimum on every decoration redraw and must not undo a deliberate override. Maximize, three faults in one report. A maximized window now draws no border: its edges are the screen's edges, and the only place maximize stops short is the bar strip, which is exactly where the measured line was. maximize_geometry_for no longer subtracts a bottom-anchored dock's exclusive zone, so maximize runs to the bottom of the screen and the dock floats over it; top, left and right are still honoured. general.maximize_covers_dock = false restores the old behaviour. With the border gone the window sits flush under the bar instead of with an accent line crowding it. Verified: seven new tests on the real numbers from the live store, and maximize geometry measured live in a nested instance (a window maximized on a split half reports exactly that half's rect). NOT confirmed on screen: the border removal and the dock behaviour - the nested backend has no bar or dock to reserve a zone, and an attempt to check the border produced a failing control, since srd set border_width only affects windows created after it. 515 tests pass, clippy clean. --- crates/core/src/window.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'crates/core/src/window.rs') diff --git a/crates/core/src/window.rs b/crates/core/src/window.rs index ee9fd23..272d772 100644 --- a/crates/core/src/window.rs +++ b/crates/core/src/window.rs @@ -197,6 +197,25 @@ pub struct Window { /// (GNOME, KDE, Windows) hides or disables it in exactly this case. /// Asked for as titlebars with "buttons of the program/dynamic". pub resizable: bool, + /// This window's own minimum size, in physical pixels. Defaults to the + /// global [`crate::placement::MIN_WINDOW_WIDTH`]/`MIN_WINDOW_HEIGHT`. + /// + /// Two sources, in order of precedence: a `min_size` window rule, and + /// the client's own declared minimum (`xdg_toplevel.set_min_size`, or + /// an XWayland window's ICCCM size hints), which the backend fills in + /// the same way it fills `resizable`. + /// + /// One global minimum for every window is wrong in both directions: it + /// is far too small for an application that needs room to lay out at + /// all, and too large for a small utility or palette window. Asked for + /// as "different windows should have minimum sizes depending on what + /// window is". + pub min_size: (u32, u32), + /// Set when `min_size` came from a `min_size` window rule rather than + /// from the client or the default. The backend refreshes a client's + /// declared minimum on every decoration redraw, and must not overwrite + /// a deliberate rule with it. + pub min_size_from_rule: bool, /// `decorated`'s value from just before entering fullscreen, restored /// on exit - see `WindowManager::toggle_fullscreen`'s doc comment on /// why this can't just hardcode `true` back. @@ -302,6 +321,8 @@ impl Window { decorated: true, is_dialog: false, resizable: true, + min_size: (crate::placement::MIN_WINDOW_WIDTH, crate::placement::MIN_WINDOW_HEIGHT), + min_size_from_rule: false, restore_decorated: None, floating: false, minimized: false, -- cgit v1.2.3