aboutsummaryrefslogtreecommitdiff
path: root/src/layout
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-12-11 09:27:38 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-12-30 20:12:37 +0300
commit10460191b93194ed4d9dc16e1fd7a2eb6f297ae3 (patch)
tree7188b36849ef71caca2a1cf69fc577c351dc4f0f /src/layout
parentc5fffd6e2c48aa7fb8b45b8bdcd972bbd8ce900b (diff)
downloadniri-10460191b93194ed4d9dc16e1fd7a2eb6f297ae3.tar.gz
niri-10460191b93194ed4d9dc16e1fd7a2eb6f297ae3.tar.bz2
niri-10460191b93194ed4d9dc16e1fd7a2eb6f297ae3.zip
Honor min/max size in more places like initial configure
Diffstat (limited to 'src/layout')
-rw-r--r--src/layout/floating.rs50
-rw-r--r--src/layout/mod.rs18
-rw-r--r--src/layout/workspace.rs56
3 files changed, 82 insertions, 42 deletions
diff --git a/src/layout/floating.rs b/src/layout/floating.rs
index 75345eed..64446c61 100644
--- a/src/layout/floating.rs
+++ b/src/layout/floating.rs
@@ -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);
}
diff --git a/src/layout/mod.rs b/src/layout/mod.rs
index 48a7954a..916b6b41 100644
--- a/src/layout/mod.rs
+++ b/src/layout/mod.rs
@@ -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 {
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs
index 21ef208f..1e1ded9d 100644
--- a/src/layout/workspace.rs
+++ b/src/layout/workspace.rs
@@ -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,22 +717,26 @@ impl<W: LayoutElement> Workspace<W> {
send_scale_transform(surface, data, self.scale, self.transform);
});
- window
- .toplevel()
- .expect("no x11 support")
- .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 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 {
+ let size = self.new_window_size(width, is_floating, rules, (min_size, max_size));
+ state.size = Some(size);
+ }
- if is_floating {
- state.bounds = Some(self.floating.toplevel_bounds(rules));
- } else {
- state.bounds = Some(self.scrolling.toplevel_bounds(rules));
- }
- });
+ if is_floating {
+ state.bounds = Some(self.floating.toplevel_bounds(rules));
+ } else {
+ state.bounds = Some(self.scrolling.toplevel_bounds(rules));
+ }
+ });
}
pub fn focus_left(&mut self) -> bool {