From c5fffd6e2c48aa7fb8b45b8bdcd972bbd8ce900b Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Fri, 29 Nov 2024 21:11:02 +0300 Subject: Initial WIP floating window implementation --- src/window/mod.rs | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'src/window') diff --git a/src/window/mod.rs b/src/window/mod.rs index 98c26e7f..4f4b6674 100644 --- a/src/window/mod.rs +++ b/src/window/mod.rs @@ -3,7 +3,10 @@ use std::cmp::{max, min}; use niri_config::{BlockOutFrom, BorderRule, CornerRadius, Match, WindowRule}; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel; use smithay::utils::{Logical, Size}; -use smithay::wayland::shell::xdg::{ToplevelSurface, XdgToplevelSurfaceRoleAttributes}; +use smithay::wayland::compositor::with_states; +use smithay::wayland::shell::xdg::{ + SurfaceCachedState, ToplevelSurface, XdgToplevelSurfaceRoleAttributes, +}; use crate::layout::scrolling::ColumnWidth; use crate::utils::with_toplevel_role; @@ -43,6 +46,9 @@ pub struct ResolvedWindowRules { /// Whether the window should open fullscreen. pub open_fullscreen: Option, + /// Whether the window should open floating. + pub open_floating: Option, + /// Extra bound on the minimum window width. pub min_width: Option, /// Extra bound on the minimum window height. @@ -109,6 +115,7 @@ impl ResolvedWindowRules { open_on_workspace: None, open_maximized: None, open_fullscreen: None, + open_floating: None, min_width: None, min_height: None, max_width: None, @@ -197,6 +204,10 @@ impl ResolvedWindowRules { resolved.open_fullscreen = Some(x); } + if let Some(x) = rule.open_floating { + resolved.open_floating = Some(x); + } + if let Some(x) = rule.min_width { resolved.min_width = Some(x); } @@ -273,6 +284,28 @@ impl ResolvedWindowRules { size } + + pub fn compute_open_floating(&self, toplevel: &ToplevelSurface) -> bool { + if let Some(res) = self.open_floating { + return res; + } + + // Windows with a parent (usually dialogs) open as floating by default. + if toplevel.parent().is_some() { + return true; + } + + let (mut min_size, mut max_size) = with_states(toplevel.wl_surface(), |state| { + let mut guard = state.cached_state.get::(); + 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); + + // We open fixed-height windows as floating. + min_size.h > 0 && min_size.h == max_size.h + } } fn window_matches(window: WindowRef, role: &XdgToplevelSurfaceRoleAttributes, m: &Match) -> bool { -- cgit