app, event_loop/run: add App::window_resizable() so a window_size_hint can declare a permanently fixed-size toplevel
Some checks failed
CI / build + test (push) Has been cancelled
CI / cargo audit (push) Has been cancelled

`window_size_hint()` pins `min_size == max_size` before the first commit so the compositor's first configure honours the requested size, and the runtime then releases `max_size` from the first configure handler (the `pending_size_hint_unpin` latch) to leave the surface user-resizable. That release is wrong for kiosk-style windows such as the installer's `--windowsize` test mode: the moment the pin is gone the compositor is free to resize the toplevel, and a compositor with per-app geometry persistence (forge, eydos #7) will happily restore a remembered rect over the requested one — which is exactly how the installer kept opening at 1600x900 after a single `make start-desktop` run had been recorded, no matter what `--windowsize` asked for.
New defaulted trait method `App::window_resizable() -> bool` (default `true`, existing apps unaffected). When it returns `false` and a `window_size_hint` is set, the unpin latch is never armed: the `min == max` pin stays in place for the lifetime of the toplevel, declaring a fixed-size window that compositors must not resize or restore a remembered geometry over. Ignored when `window_size_hint()` is `None` — fullscreen and compositor-sized windows keep their current behaviour.
Pairs with the forge-side change that makes both the geometry-restore hook skip windows whose current constraints report `min == max` and the reparenting XWM aware of them; ltk keeping the pin alive is what makes that detection possible past the first configure.
This commit is contained in:
2026-07-29 10:20:45 +02:00
parent 142096827e
commit 0062bc565c
2 changed files with 17 additions and 1 deletions

View File

@@ -816,6 +816,22 @@ pub trait App: 'static
/// **Default**: `None` (let the compositor pick).
fn window_size_hint( &self ) -> Option<( u32, u32 )> { None }
/// Whether the user may resize an xdg-shell window.
///
/// When [`Self::window_size_hint`] is set, ltk pins
/// `min_size == max_size` before the first commit so the compositor's
/// first configure honours the requested size, and then releases
/// `max_size` from the first configure so the surface becomes
/// user-resizable. Returning `false` skips that release: the pin stays
/// in place for the lifetime of the toplevel, declaring a fixed-size
/// window that compositors must not resize or restore a remembered
/// geometry over.
///
/// Ignored when [`Self::window_size_hint`] returns `None`.
///
/// **Default**: `true`.
fn window_resizable( &self ) -> bool { true }
/// Request fullscreen on the toplevel before its first commit.
///
/// When `true`, ltk calls `xdg_toplevel.set_fullscreen( None )` so

View File

@@ -257,7 +257,7 @@ pub( crate ) fn try_run<A: App>( app: A ) -> Result<(), RunError>
let titlebar_title = force_window.map( |( t, _ )| t ).unwrap_or_default();
let pending_fullscreen = app.start_fullscreen();
let pending_size_hint_unpin = !app.start_fullscreen() && app.window_size_hint().is_some();
let pending_size_hint_unpin = !app.start_fullscreen() && app.window_size_hint().is_some() && app.window_resizable();
let mut data = AppData
{