tiling: Better heuristic

This commit is contained in:
Victoria Brekenfeld 2022-03-30 16:27:39 +02:00
parent 3ebeab17b7
commit d132722bd0
2 changed files with 53 additions and 51 deletions

View file

@ -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<A: Layout, B: Layout> {
second: B,
windows_a: Vec<Window>,
windows_b: Vec<Window>,
filter: Box<dyn Fn(Option<&str>, Option<&str>) -> bool>,
filter: Box<dyn Fn(&Window) -> bool>,
}
impl<A: Layout, B: Layout> Combined<A, B> {
pub fn new(
first: A,
second: B,
filter: impl Fn(Option<&str>, Option<&str>) -> bool + 'static,
) -> Combined<A, B> {
pub fn new(first: A, second: B, filter: impl Fn(&Window) -> bool + 'static) -> Combined<A, B> {
Combined {
first,
second,
@ -45,40 +38,23 @@ impl<A: Layout, B: Layout> Layout for Combined<A, B> {
seat: &Seat,
focus_stack: Box<dyn Iterator<Item = &'a Window> + 'a>,
) {
if let Some(surface) = window.toplevel().get_surface() {
let filtered = with_states(surface, |states| {
let attrs = states
.data_map
.get::<Mutex<XdgToplevelSurfaceRoleAttributes>>()
.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::<Filtered>().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::<Filtered>().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::<Filtered>().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::<Filtered>().is_none())),
);
}
fn refresh(&mut self, space: &mut Space) {

View file

@ -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<dyn Layout> {
Box::new(combined::Combined::new(
tiling::TilingLayout::new(idx),
floating::FloatingLayout,
|app_id, title| {
slog_scope::debug!(
"New filter input: ({}:{})",
app_id.unwrap_or("<unknown>"),
title.unwrap_or("<no title>")
);
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::<Mutex<XdgToplevelSurfaceRoleAttributes>>()
.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
}
},
))