diff --git a/src/event_loop/app_data.rs b/src/event_loop/app_data.rs index 50d3e55..9624fed 100644 --- a/src/event_loop/app_data.rs +++ b/src/event_loop/app_data.rs @@ -675,6 +675,9 @@ pub struct AppData pub exit_requested: bool, /// First-configure latch for `App::start_fullscreen`. pub pending_fullscreen: bool, + /// First-configure latch: clears `max_size` after the compositor + /// has honoured the pinned initial size. + pub pending_size_hint_unpin: bool, /// Main application surface. pub main: SurfaceState, /// Auxiliary layer-shell surfaces keyed by their stable [`OverlayId`]. diff --git a/src/event_loop/handlers.rs b/src/event_loop/handlers.rs index c5b8dbe..edadc16 100644 --- a/src/event_loop/handlers.rs +++ b/src/event_loop/handlers.rs @@ -207,8 +207,14 @@ impl WindowHandler for AppData window.set_fullscreen( None ); self.pending_fullscreen = false; } - let w = configure.new_size.0.map( |v| v.get() ).unwrap_or( 800 ); - let h = configure.new_size.1.map( |v| v.get() ).unwrap_or( 600 ); + if self.pending_size_hint_unpin + { + window.set_max_size( None ); + self.pending_size_hint_unpin = false; + } + let ( hint_w, hint_h ) = self.app.window_size_hint().unwrap_or( ( 800, 600 ) ); + let w = configure.new_size.0.map( |v| v.get() ).unwrap_or( hint_w ); + let h = configure.new_size.1.map( |v| v.get() ).unwrap_or( hint_h ); self.on_configure( w, h ); self.app.on_resize( w, h ); } diff --git a/src/event_loop/mod.rs b/src/event_loop/mod.rs index aee1078..1be2b71 100644 --- a/src/event_loop/mod.rs +++ b/src/event_loop/mod.rs @@ -165,9 +165,8 @@ pub( crate ) fn try_run( app: A ) -> Result<(), RunError> .map_err( |e| RunError::MissingProtocol { name: "xdg_wm_base", detail: format!( "{e:?}" ) } ) }; - // Pinning min == max is the standard idiom on xdg-shell for "I - // want this exact size". Skipped when going fullscreen — Mutter - // rejects the fullscreen request if a min_size constrains it. + // Skipped when going fullscreen: Mutter rejects the fullscreen + // request if a min_size constrains it. let apply_size_hint = |window: &smithay_client_toolkit::shell::xdg::window::Window| { if app.start_fullscreen() { return; } @@ -175,14 +174,8 @@ pub( crate ) fn try_run( app: A ) -> Result<(), RunError> { Some( ( w, h ) ) => { - // `set_min_size` doubles as the suggested initial size: - // most compositors send the first configure with this - // value, after which the surface remains user-resizable - // (the runtime adopts whatever size the compositor - // supplies on subsequent configures). `set_max_size` is - // deliberately *not* called — pinning min == max would - // lock the toplevel and refuse user-initiated resize. window.set_min_size( Some( ( w, h ) ) ); + window.set_max_size( Some( ( w, h ) ) ); } None => { @@ -262,7 +255,8 @@ pub( crate ) fn try_run( app: A ) -> Result<(), RunError> let titlebar_height = if force_window.is_some() { 36.0 } else { 0.0 }; let titlebar_title = force_window.map( |( t, _ )| t ).unwrap_or_default(); - let pending_fullscreen = app.start_fullscreen(); + let pending_fullscreen = app.start_fullscreen(); + let pending_size_hint_unpin = !app.start_fullscreen() && app.window_size_hint().is_some(); let mut data = AppData { @@ -304,6 +298,7 @@ pub( crate ) fn try_run( app: A ) -> Result<(), RunError> last_input_serial: 0, exit_requested: false, pending_fullscreen, + pending_size_hint_unpin, main: SurfaceState::::new( surface_kind, titlebar_height, titlebar_title ), overlays: std::collections::HashMap::new(), pointer_focus: SurfaceFocus::Main,