diff --git a/CHANGELOG.md b/CHANGELOG.md index 86c3a83c78..760439ab2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ And please only add new entries to the top of this list, right below the `# Unre sent a cancel or frame event. - On iOS, send `RedrawEventsCleared` even if there are no redraw events, consistent with other platforms. - **Breaking:** Replaced `Window::with_app_id` and `Window::with_class` with `Window::with_name` on `WindowBuilderExtUnix`. +- On Wayland and X11, fix window not resizing with `Window::set_inner_size` after calling `Window:set_resizable(false)`. # 0.26.1 (2022-01-05) diff --git a/src/platform_impl/linux/wayland/window/mod.rs b/src/platform_impl/linux/wayland/window/mod.rs index 4ef8bd2f81..4cff918f3e 100644 --- a/src/platform_impl/linux/wayland/window/mod.rs +++ b/src/platform_impl/linux/wayland/window/mod.rs @@ -220,6 +220,9 @@ impl Window { window_requests.clone(), ); + // Set resizable state, so we can determine how to handle `Window::set_inner_size`. + window_handle.is_resizable.set(attributes.resizable); + let mut winit_state = event_loop_window_target.state.borrow_mut(); winit_state.window_map.insert(window_id, window_handle); diff --git a/src/platform_impl/linux/wayland/window/shim.rs b/src/platform_impl/linux/wayland/window/shim.rs index 60247b317e..90695be533 100644 --- a/src/platform_impl/linux/wayland/window/shim.rs +++ b/src/platform_impl/linux/wayland/window/shim.rs @@ -154,6 +154,9 @@ pub struct WindowHandle { /// Current cursor icon. pub cursor_icon: Cell, + /// Whether the window is resizable. + pub is_resizable: Cell, + /// Visible cursor or not. cursor_visible: Cell, @@ -193,6 +196,7 @@ impl WindowHandle { size, pending_window_requests, cursor_icon: Cell::new(CursorIcon::Default), + is_resizable: Cell::new(true), confined: Cell::new(false), cursor_visible: Cell::new(true), pointers: Vec::new(), @@ -443,7 +447,14 @@ pub fn handle_window_requests(winit_state: &mut WinitState) { window_update.redraw_requested = true; } WindowRequest::FrameSize(size) => { - // Set new size. + if !window_handle.is_resizable.get() { + // On Wayland non-resizable window is achieved by setting both min and max + // size of the window to the same value. + let size = Some((size.width, size.height)); + window_handle.window.set_max_size(size); + window_handle.window.set_min_size(size); + } + window_handle.window.resize(size.width, size.height); // We should refresh the frame after resize. diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 1be2f7cc41..e370796075 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -1115,8 +1115,15 @@ impl UnownedWindow { #[inline] pub fn set_inner_size(&self, size: Size) { let scale_factor = self.scale_factor(); - let (width, height) = size.to_physical::(scale_factor).into(); - self.set_inner_size_physical(width, height); + let size = size.to_physical::(scale_factor).into(); + if !self.shared_state.lock().is_resizable { + self.update_normal_hints(|normal_hints| { + normal_hints.set_min_size(Some(size)); + normal_hints.set_max_size(Some(size)); + }) + .expect("Failed to call `XSetWMNormalHints`"); + } + self.set_inner_size_physical(size.0, size.1); } fn update_normal_hints(&self, callback: F) -> Result<(), XError> diff --git a/src/window.rs b/src/window.rs index f03033256b..a1f11070d7 100644 --- a/src/window.rs +++ b/src/window.rs @@ -665,8 +665,9 @@ impl Window { /// Sets whether the window is resizable or not. /// - /// Note that making the window unresizable doesn't exempt you from handling `Resized`, as that event can still be - /// triggered by DPI scaling, entering fullscreen mode, etc. + /// Note that making the window unresizable doesn't exempt you from handling `Resized`, as that + /// event can still be triggered by DPI scaling, entering fullscreen mode, etc. Also, the + /// window could still be resized by calling `[Window::set_inner_size]`. /// /// ## Platform-specific ///