diff --git a/src/shell/layout/combined.rs b/src/shell/layout/combined.rs index 87cdda68..2e36dc82 100644 --- a/src/shell/layout/combined.rs +++ b/src/shell/layout/combined.rs @@ -3,13 +3,10 @@ use smithay::{ desktop::{Space, Window}, reexports::wayland_protocols::xdg_shell::server::xdg_toplevel::ResizeEdge, wayland::{ - compositor::with_states, seat::{PointerGrabStartData, Seat}, - shell::xdg::XdgToplevelSurfaceRoleAttributes, Serial, }, }; -use std::sync::Mutex; struct Filtered; @@ -18,15 +15,11 @@ pub struct Combined { second: B, windows_a: Vec, windows_b: Vec, - filter: Box, Option<&str>) -> bool>, + filter: Box bool>, } impl Combined { - pub fn new( - first: A, - second: B, - filter: impl Fn(Option<&str>, Option<&str>) -> bool + 'static, - ) -> Combined { + pub fn new(first: A, second: B, filter: impl Fn(&Window) -> bool + 'static) -> Combined { Combined { first, second, @@ -45,40 +38,23 @@ impl Layout for Combined { seat: &Seat, focus_stack: Box + 'a>, ) { - if let Some(surface) = window.toplevel().get_surface() { - let filtered = with_states(surface, |states| { - let attrs = states - .data_map - .get::>() - .unwrap() - .lock() - .unwrap(); - if (self.filter)(attrs.app_id.as_deref(), attrs.title.as_deref()) { - window.user_data().insert_if_missing(|| Filtered); - true - } else { - false - } - }) - .unwrap_or(false); - if filtered { - self.windows_b.push(window.clone()); - return self.second.map_window( - space, - window, - seat, - Box::new(focus_stack.filter(|w| w.user_data().get::().is_some())), - ); - } + if (self.filter)(window) { + self.windows_b.push(window.clone()); + self.second.map_window( + space, + window, + seat, + Box::new(focus_stack.filter(|w| w.user_data().get::().is_some())), + ) + } else { + self.windows_a.push(window.clone()); + self.first.map_window( + space, + window, + seat, + Box::new(focus_stack.filter(|w| w.user_data().get::().is_none())), + ) } - - self.windows_a.push(window.clone()); - return self.first.map_window( - space, - window, - seat, - Box::new(focus_stack.filter(|w| w.user_data().get::().is_none())), - ); } fn refresh(&mut self, space: &mut Space) { diff --git a/src/shell/layout/mod.rs b/src/shell/layout/mod.rs index 124093e6..81e075f6 100644 --- a/src/shell/layout/mod.rs +++ b/src/shell/layout/mod.rs @@ -4,11 +4,14 @@ use smithay::{ desktop::{Space, Window}, reexports::wayland_protocols::xdg_shell::server::xdg_toplevel::ResizeEdge, wayland::{ + compositor::with_states, output::Output, seat::{PointerGrabStartData, Seat}, + shell::xdg::XdgToplevelSurfaceRoleAttributes, Serial, }, }; +use std::sync::Mutex; pub mod combined; pub mod floating; @@ -70,15 +73,38 @@ pub fn new_default_layout(idx: u8) -> Box { Box::new(combined::Combined::new( tiling::TilingLayout::new(idx), floating::FloatingLayout, - |app_id, title| { - slog_scope::debug!( - "New filter input: ({}:{})", - app_id.unwrap_or(""), - title.unwrap_or("") - ); - match (app_id.unwrap_or(""), title.unwrap_or("")) { - ("gcr-prompter", _) => true, - _ => false, + |window| { + if let Some(surface) = window.toplevel().get_surface() { + with_states(surface, |states| { + let attrs = states + .data_map + .get::>() + .unwrap() + .lock() + .unwrap(); + + // simple heuristic taken from + // sway/desktop/xdg_shell.c:188 @ 0ee54a52 + if attrs.parent.is_some() + || (attrs.min_size.w != 0 + && attrs.min_size.h != 0 + && attrs.min_size == attrs.max_size) + { + return true; + } + + // else take a look at our exceptions + match ( + attrs.app_id.as_deref().unwrap_or(""), + attrs.title.as_deref().unwrap_or(""), + ) { + ("gcr-prompter", _) => true, + _ => false, + } + }) + .unwrap_or(false) + } else { + false } }, ))