Honor min/max size in more places like initial configure

This commit is contained in:
Ivan Molodetskikh
2024-12-11 09:27:38 +03:00
parent c5fffd6e2c
commit 10460191b9
6 changed files with 111 additions and 47 deletions
+6 -2
View File
@@ -159,8 +159,10 @@ impl Layout {
fn add_window(&mut self, mut window: TestWindow, width: Option<ColumnWidth>) {
let ws = self.layout.active_workspace().unwrap();
let min_size = window.min_size();
let max_size = window.max_size();
window.request_size(
ws.new_window_size(width, false, window.rules()),
ws.new_window_size(width, false, window.rules(), (min_size, max_size)),
false,
None,
);
@@ -183,8 +185,10 @@ impl Layout {
width: Option<ColumnWidth>,
) {
let ws = self.layout.active_workspace().unwrap();
let min_size = window.min_size();
let max_size = window.max_size();
window.request_size(
ws.new_window_size(width, false, window.rules()),
ws.new_window_size(width, false, window.rules(), (min_size, max_size)),
false,
None,
);
+28 -22
View File
@@ -1,4 +1,4 @@
use std::cmp::{max, min};
use std::cmp::max;
use std::iter::zip;
use std::rc::Rc;
@@ -16,7 +16,7 @@ use crate::niri_render_elements;
use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::RenderTarget;
use crate::utils::transaction::TransactionBlocker;
use crate::utils::ResizeEdge;
use crate::utils::{ensure_min_max_size, ResizeEdge};
use crate::window::ResolvedWindowRules;
/// Space for floating windows.
@@ -332,13 +332,25 @@ impl<W: LayoutElement> FloatingSpace<W> {
) {
tile.update_config(self.scale, self.options.clone());
if tile.window().is_pending_fullscreen() {
tile.window_mut()
.request_size(Size::from((0, 0)), true, None);
let win = tile.window_mut();
if win.is_pending_fullscreen() {
let mut size = Size::from((0, 0));
// Make sure fixed-size through window rules keeps working.
let min_size = win.min_size();
let max_size = win.max_size();
if min_size.w == max_size.w {
size.w = min_size.w;
}
if min_size.h == max_size.h {
size.h = min_size.h;
}
win.request_size(size, true, None);
}
if activate || self.tiles.is_empty() {
self.active_window_id = Some(tile.window().id().clone());
self.active_window_id = Some(win.id().clone());
}
let mut pos = pos.unwrap_or_else(|| {
@@ -500,15 +512,10 @@ impl<W: LayoutElement> FloatingSpace<W> {
let tile = &mut self.tiles[idx];
let win = tile.window_mut();
let min_w = win.min_size().w;
let max_w = win.max_size().w;
let min_size = win.min_size();
let max_size = win.max_size();
if max_w > 0 {
win_width = min(win_width, max_w);
}
if min_w > 0 {
win_width = max(win_width, min_w);
}
win_width = ensure_min_max_size(win_width, min_size.w, max_size.w);
win_width = max(1, win_width);
let win_height = win
@@ -517,6 +524,8 @@ impl<W: LayoutElement> FloatingSpace<W> {
// If we requested height = 0, then switch to the current height.
.filter(|h| *h != 0)
.unwrap_or_else(|| win.size().h);
let win_height = ensure_min_max_size(win_height, min_size.h, max_size.h);
let win_size = Size::from((win_width, win_height));
win.request_size(win_size, animate, None);
}
@@ -534,15 +543,10 @@ impl<W: LayoutElement> FloatingSpace<W> {
let tile = &mut self.tiles[idx];
let win = tile.window_mut();
let min_h = win.min_size().h;
let max_h = win.max_size().h;
let min_size = win.min_size();
let max_size = win.max_size();
if max_h > 0 {
win_height = min(win_height, max_h);
}
if min_h > 0 {
win_height = max(win_height, min_h);
}
win_height = ensure_min_max_size(win_height, min_size.h, max_size.h);
win_height = max(1, win_height);
let win_width = win
@@ -551,6 +555,8 @@ impl<W: LayoutElement> FloatingSpace<W> {
// If we requested width = 0, then switch to the current width.
.filter(|w| *w != 0)
.unwrap_or_else(|| win.size().w);
let win_width = ensure_min_max_size(win_width, min_size.w, max_size.w);
let win_size = Size::from((win_width, win_height));
win.request_size(win_size, animate, None);
}
+15 -3
View File
@@ -3219,9 +3219,21 @@ impl<W: LayoutElement> Layout<W> {
// prefer-no-csd, and occasionally that last size can become the full-width size
// rather than a smaller size, which is annoying. Need to see if niri can use some
// heuristics to make this case behave better.
if tile.window().is_pending_fullscreen() {
tile.window_mut()
.request_size(Size::from((0, 0)), true, None);
let win = tile.window_mut();
if win.is_pending_fullscreen() {
let mut size = Size::from((0, 0));
// Make sure fixed-size through window rules keeps working.
let min_size = win.min_size();
let max_size = win.max_size();
if min_size.w == max_size.w {
size.w = min_size.w;
}
if min_size.h == max_size.h {
size.h = min_size.h;
}
win.request_size(size, true, None);
}
let mut data = InteractiveMoveData {
+29 -7
View File
@@ -9,6 +9,8 @@ use smithay::output::Output;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::utils::{Logical, Point, Rectangle, Scale, Serial, Size, Transform};
use smithay::wayland::compositor::with_states;
use smithay::wayland::shell::xdg::SurfaceCachedState;
use super::floating::{FloatingSpace, FloatingSpaceRenderElement};
use super::scrolling::{
@@ -22,7 +24,7 @@ use crate::render_helpers::renderer::NiriRenderer;
use crate::render_helpers::RenderTarget;
use crate::utils::id::IdCounter;
use crate::utils::transaction::{Transaction, TransactionBlocker};
use crate::utils::{output_size, send_scale_transform, ResizeEdge};
use crate::utils::{ensure_min_max_size, output_size, send_scale_transform, ResizeEdge};
use crate::window::ResolvedWindowRules;
#[derive(Debug)]
@@ -680,12 +682,28 @@ impl<W: LayoutElement> Workspace<W> {
width: Option<ColumnWidth>,
is_floating: bool,
rules: &ResolvedWindowRules,
(min_size, max_size): (Size<i32, Logical>, Size<i32, Logical>),
) -> Size<i32, Logical> {
if is_floating {
let mut size = if is_floating {
Size::from((0, 0))
} else {
self.scrolling.new_window_size(width, rules)
};
// If the window has a fixed size, or we're picking some fixed size, apply min and max
// size. This is to ensure that a fixed-size window rule works on open, while still
// allowing the window freedom to pick its default size otherwise.
let (min_size, max_size) = rules.apply_min_max_size(min_size, max_size);
if size.w > 0 || min_size.w == max_size.w {
size.w = ensure_min_max_size(size.w, min_size.w, max_size.w);
}
// For scrolling (where height is > 0) only ensure fixed height, since at runtime scrolling
// will only honor fixed height currently.
if min_size.h == max_size.h {
size.h = ensure_min_max_size(size.h, min_size.h, max_size.h);
}
size
}
pub fn configure_new_window(
@@ -699,14 +717,18 @@ impl<W: LayoutElement> Workspace<W> {
send_scale_transform(surface, data, self.scale, self.transform);
});
window
.toplevel()
.expect("no x11 support")
.with_pending_state(|state| {
let toplevel = window.toplevel().expect("no x11 support");
let (min_size, max_size) = with_states(toplevel.wl_surface(), |state| {
let mut guard = state.cached_state.get::<SurfaceCachedState>();
let current = guard.current();
(current.min_size, current.max_size)
});
toplevel.with_pending_state(|state| {
if state.states.contains(xdg_toplevel::State::Fullscreen) {
state.size = Some(self.view_size.to_i32_round());
} else {
state.size = Some(self.new_window_size(width, is_floating, rules));
let size = self.new_window_size(width, is_floating, rules, (min_size, max_size));
state.size = Some(size);
}
if is_floating {
+11
View File
@@ -1,3 +1,4 @@
use std::cmp::{max, min};
use std::ffi::{CString, OsStr};
use std::io::Write;
use std::os::unix::prelude::OsStrExt;
@@ -261,6 +262,16 @@ pub fn get_credentials_for_surface(surface: &WlSurface) -> Option<Credentials> {
client.get_credentials(&dh).ok()
}
pub fn ensure_min_max_size(mut x: i32, min_size: i32, max_size: i32) -> i32 {
if max_size > 0 {
x = min(x, max_size);
}
if min_size > 0 {
x = max(x, min_size);
}
x
}
#[cfg(feature = "dbus")]
pub fn show_screenshot_notification(image_path: Option<PathBuf>) {
let mut notification = notify_rust::Notification::new();
+12 -3
View File
@@ -285,6 +285,16 @@ impl ResolvedWindowRules {
size
}
pub fn apply_min_max_size(
&self,
min_size: Size<i32, Logical>,
max_size: Size<i32, Logical>,
) -> (Size<i32, Logical>, Size<i32, Logical>) {
let min_size = self.apply_min_size(min_size);
let max_size = self.apply_max_size(max_size);
(min_size, max_size)
}
pub fn compute_open_floating(&self, toplevel: &ToplevelSurface) -> bool {
if let Some(res) = self.open_floating {
return res;
@@ -295,13 +305,12 @@ impl ResolvedWindowRules {
return true;
}
let (mut min_size, mut max_size) = with_states(toplevel.wl_surface(), |state| {
let (min_size, max_size) = with_states(toplevel.wl_surface(), |state| {
let mut guard = state.cached_state.get::<SurfaceCachedState>();
let current = guard.current();
(current.min_size, current.max_size)
});
min_size = self.apply_min_size(min_size);
max_size = self.apply_max_size(max_size);
let (min_size, max_size) = self.apply_min_max_size(min_size, max_size);
// We open fixed-height windows as floating.
min_size.h > 0 && min_size.h == max_size.h