From 0062bc565c088c72d192324844d73bcbf0fa48ef Mon Sep 17 00:00:00 2001 From: "Pedro M. de Echanove Pasquin" Date: Wed, 29 Jul 2026 10:20:45 +0200 Subject: [PATCH] =?UTF-8?q?app,=20event=5Floop/run:=20add=20`App::window?= =?UTF-8?q?=5Fresizable()`=20so=20a=20window=5Fsize=5Fhint=20can=20declare?= =?UTF-8?q?=20a=20permanently=20fixed-size=20toplevel=20`window=5Fsize=5Fh?= =?UTF-8?q?int()`=20pins=20`min=5Fsize=20=3D=3D=20max=5Fsize`=20before=20t?= =?UTF-8?q?he=20first=20commit=20so=20the=20compositor's=20first=20configu?= =?UTF-8?q?re=20honours=20the=20requested=20size,=20and=20the=20runtime=20?= =?UTF-8?q?then=20releases=20`max=5Fsize`=20from=20the=20first=20configure?= =?UTF-8?q?=20handler=20(the=20`pending=5Fsize=5Fhint=5Funpin`=20latch)=20?= =?UTF-8?q?to=20leave=20the=20surface=20user-resizable.=20That=20release?= =?UTF-8?q?=20is=20wrong=20for=20kiosk-style=20windows=20such=20as=20the?= =?UTF-8?q?=20installer's=20`--windowsize`=20test=20mode:=20the=20moment?= =?UTF-8?q?=20the=20pin=20is=20gone=20the=20compositor=20is=20free=20to=20?= =?UTF-8?q?resize=20the=20toplevel,=20and=20a=20compositor=20with=20per-ap?= =?UTF-8?q?p=20geometry=20persistence=20(forge,=20eydos=20#7)=20will=20hap?= =?UTF-8?q?pily=20restore=20a=20remembered=20rect=20over=20the=20requested?= =?UTF-8?q?=20one=20=E2=80=94=20which=20is=20exactly=20how=20the=20install?= =?UTF-8?q?er=20kept=20opening=20at=201600x900=20after=20a=20single=20`mak?= =?UTF-8?q?e=20start-desktop`=20run=20had=20been=20recorded,=20no=20matter?= =?UTF-8?q?=20what=20`--windowsize`=20asked=20for.=20New=20defaulted=20tra?= =?UTF-8?q?it=20method=20`App::window=5Fresizable()=20->=20bool`=20(defaul?= =?UTF-8?q?t=20`true`,=20existing=20apps=20unaffected).=20When=20it=20retu?= =?UTF-8?q?rns=20`false`=20and=20a=20`window=5Fsize=5Fhint`=20is=20set,=20?= =?UTF-8?q?the=20unpin=20latch=20is=20never=20armed:=20the=20`min=20=3D=3D?= =?UTF-8?q?=20max`=20pin=20stays=20in=20place=20for=20the=20lifetime=20of?= =?UTF-8?q?=20the=20toplevel,=20declaring=20a=20fixed-size=20window=20that?= =?UTF-8?q?=20compositors=20must=20not=20resize=20or=20restore=20a=20remem?= =?UTF-8?q?bered=20geometry=20over.=20Ignored=20when=20`window=5Fsize=5Fhi?= =?UTF-8?q?nt()`=20is=20`None`=20=E2=80=94=20fullscreen=20and=20compositor?= =?UTF-8?q?-sized=20windows=20keep=20their=20current=20behaviour.=20Pairs?= =?UTF-8?q?=20with=20the=20forge-side=20change=20that=20makes=20both=20the?= =?UTF-8?q?=20geometry-restore=20hook=20skip=20windows=20whose=20current?= =?UTF-8?q?=20constraints=20report=20`min=20=3D=3D=20max`=20and=20the=20re?= =?UTF-8?q?parenting=20XWM=20aware=20of=20them;=20ltk=20keeping=20the=20pi?= =?UTF-8?q?n=20alive=20is=20what=20makes=20that=20detection=20possible=20p?= =?UTF-8?q?ast=20the=20first=20configure.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app.rs | 16 ++++++++++++++++ src/event_loop/run.rs | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/app.rs b/src/app.rs index ea99b48..549adb3 100644 --- a/src/app.rs +++ b/src/app.rs @@ -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 diff --git a/src/event_loop/run.rs b/src/event_loop/run.rs index abe7d29..40bb30c 100644 --- a/src/event_loop/run.rs +++ b/src/event_loop/run.rs @@ -257,7 +257,7 @@ pub( crate ) fn try_run( 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 {