diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index 2a8cebab..dfcb87e3 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -468,61 +468,16 @@ impl CosmicMapped { pub fn min_size(&self) -> Option> { match &self.element { - CosmicMappedInternal::Stack(stack) => { - stack.surfaces().fold(None, |min_size, window| { - let win_min_size = window.min_size(); - match (min_size, win_min_size) { - (None, None) => None, - (None, x) | (x, None) => x, - (Some(min1), Some(min2)) => { - Some((min1.w.max(min2.w), min1.h.max(min2.h)).into()) - } - } - }) - } - CosmicMappedInternal::Window(window) => window.surface().min_size(), + CosmicMappedInternal::Stack(stack) => stack.min_size(), + CosmicMappedInternal::Window(window) => window.min_size(), _ => unreachable!(), } } pub fn max_size(&self) -> Option> { match &self.element { - CosmicMappedInternal::Stack(stack) => { - let theoretical_max = stack.surfaces().fold(None, |max_size, window| { - let win_max_size = window.max_size(); - match (max_size, win_max_size) { - (None, None) => None, - (None, x) | (x, None) => x, - (Some(max1), Some(max2)) => Some( - ( - if max1.w == 0 { - max2.w - } else if max2.w == 0 { - max1.w - } else { - max1.w.min(max2.w) - }, - if max1.h == 0 { - max2.h - } else if max2.h == 0 { - max1.h - } else { - max1.h.min(max2.h) - }, - ) - .into(), - ), - } - }); - // The problem is, with accumulated sizes, the minimum size could be larger than our maximum... - let min_size = self.min_size(); - match (theoretical_max, min_size) { - (None, _) => None, - (Some(max), None) => Some(max), - (Some(max), Some(min)) => Some((max.w.max(min.w), max.h.max(min.h)).into()), - } - } - CosmicMappedInternal::Window(window) => window.surface().max_size(), + CosmicMappedInternal::Stack(stack) => stack.max_size(), + CosmicMappedInternal::Window(window) => window.max_size(), _ => unreachable!(), } } @@ -911,6 +866,15 @@ impl CosmicMapped { _ => unreachable!(), }) } + + pub fn ssd_height(&self, pending: bool) -> Option { + match &self.element { + CosmicMappedInternal::Window(w) => (!w.surface().is_decorated(pending)) + .then(|| crate::shell::element::window::SSD_HEIGHT), + CosmicMappedInternal::Stack(s) => Some(crate::shell::element::stack::TAB_HEIGHT), + _ => unreachable!(), + } + } } impl IsAlive for CosmicMapped { diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index 90ae4d22..da49f5b2 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -1,4 +1,7 @@ -use super::{surface::RESIZE_BORDER, window::Focus, CosmicSurface}; +use super::{ + window::{Focus, RESIZE_BORDER}, + CosmicSurface, +}; use crate::{ backend::render::cursor::CursorState, shell::{ @@ -658,6 +661,59 @@ impl CosmicStack { } } } + + pub fn min_size(&self) -> Option> { + self.surfaces() + .fold(None, |min_size, window| { + let win_min_size = window.min_size_without_ssd(); + match (min_size, win_min_size) { + (None, None) => None, + (None, x) | (x, None) => x, + (Some(min1), Some(min2)) => { + Some((min1.w.max(min2.w), min1.h.max(min2.h)).into()) + } + } + }) + .map(|size| size + (0, TAB_HEIGHT).into()) + } + pub fn max_size(&self) -> Option> { + let theoretical_max = self + .surfaces() + .fold(None, |max_size, window| { + let win_max_size = window.max_size_without_ssd(); + match (max_size, win_max_size) { + (None, None) => None, + (None, x) | (x, None) => x, + (Some(max1), Some(max2)) => Some( + ( + if max1.w == 0 { + max2.w + } else if max2.w == 0 { + max1.w + } else { + max1.w.min(max2.w) + }, + if max1.h == 0 { + max2.h + } else if max2.h == 0 { + max1.h + } else { + max1.h.min(max2.h) + }, + ) + .into(), + ), + } + }) + .map(|size| size + (0, TAB_HEIGHT).into()); + // The problem is, with accumulated sizes, the minimum size could be larger than our maximum... + let min_size = self.min_size(); + match (theoretical_max, min_size) { + (None, _) => None, + (Some(max), None) => Some(max), + (Some(max), Some(min)) => Some((max.w.max(min.w), max.h.max(min.h)).into()), + } + } } #[derive(Debug, Clone, Copy)] diff --git a/src/shell/element/surface.rs b/src/shell/element/surface.rs index 3c6ad3f2..c8451f79 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -94,9 +94,6 @@ struct Sticky(AtomicBool); #[derive(Default)] struct GlobalGeometry(Mutex>>); -pub const SSD_HEIGHT: i32 = 36; -pub const RESIZE_BORDER: i32 = 10; - impl CosmicSurface { pub fn title(&self) -> String { match self.0.underlying_surface() { @@ -451,7 +448,7 @@ impl CosmicSurface { } } - pub fn min_size(&self) -> Option> { + pub fn min_size_without_ssd(&self) -> Option> { match self.0.underlying_surface() { WindowSurface::Wayland(toplevel) => { Some(with_states(toplevel.wl_surface(), |states| { @@ -465,16 +462,9 @@ impl CosmicSurface { } WindowSurface::X11(surface) => surface.min_size(), } - .map(|size| { - if self.is_decorated(false) { - size - } else { - size + (0, SSD_HEIGHT).into() - } - }) } - pub fn max_size(&self) -> Option> { + pub fn max_size_without_ssd(&self) -> Option> { match self.0.underlying_surface() { WindowSurface::Wayland(toplevel) => { Some(with_states(toplevel.wl_surface(), |states| { @@ -488,13 +478,6 @@ impl CosmicSurface { } WindowSurface::X11(surface) => surface.max_size(), } - .map(|size| { - if self.is_decorated(false) { - size - } else { - size + (0, SSD_HEIGHT).into() - } - }) } pub fn serial_acked(&self, serial: &Serial) -> bool { diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index c88c6121..54c0626a 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -55,10 +55,10 @@ use std::{ }; use wayland_backend::server::ObjectId; -use super::{ - surface::{RESIZE_BORDER, SSD_HEIGHT}, - CosmicSurface, -}; +use super::CosmicSurface; + +pub const SSD_HEIGHT: i32 = 36; +pub const RESIZE_BORDER: i32 = 10; #[derive(Clone, PartialEq, Eq, Hash)] pub struct CosmicWindow(pub(super) IcedElement); @@ -386,6 +386,29 @@ impl CosmicWindow { pub(crate) fn force_redraw(&self) { self.0.force_redraw(); } + + pub fn min_size(&self) -> Option> { + self.0 + .with_program(|p| p.window.min_size_without_ssd()) + .map(|size| { + if self.0.with_program(|p| !p.window.is_decorated(false)) { + size + (0, SSD_HEIGHT).into() + } else { + size + } + }) + } + pub fn max_size(&self) -> Option> { + self.0 + .with_program(|p| p.window.max_size_without_ssd()) + .map(|size| { + if self.0.with_program(|p| !p.window.is_decorated(false)) { + size + (0, SSD_HEIGHT).into() + } else { + size + } + }) + } } #[derive(Debug, Clone, Copy)] diff --git a/src/shell/layout/mod.rs b/src/shell/layout/mod.rs index 852a75ce..a2475411 100644 --- a/src/shell/layout/mod.rs +++ b/src/shell/layout/mod.rs @@ -44,8 +44,8 @@ pub fn is_dialog(window: &CosmicSurface) -> bool { }; // Check if sizing suggest dialog - let max_size = window.max_size(); - let min_size = window.min_size(); + let max_size = window.max_size_without_ssd(); + let min_size = window.min_size_without_ssd(); if min_size.is_some() && min_size == max_size { return true; diff --git a/src/xwayland.rs b/src/xwayland.rs index bec87771..2ccfd0d3 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -2,10 +2,7 @@ use std::{ffi::OsString, os::unix::io::OwnedFd, process::Stdio}; use crate::{ backend::render::cursor::{load_cursor_theme, Cursor}, - shell::{ - element::surface::SSD_HEIGHT, focus::target::KeyboardFocusTarget, grabs::ReleaseMode, - CosmicSurface, Shell, - }, + shell::{focus::target::KeyboardFocusTarget, grabs::ReleaseMode, CosmicSurface, Shell}, state::State, utils::prelude::*, wayland::handlers::{ @@ -473,7 +470,7 @@ impl XwmHandler for State { }; if let Some(current_geo) = current_geo { - let ssd_height = if window.is_decorated() { 0 } else { SSD_HEIGHT }; + let ssd_height = mapped.ssd_height(false).unwrap_or(0); mapped.set_geometry(Rectangle::from_loc_and_size( current_geo.loc, (