From 8edcdf5cd04a89ddba7865866e25e74fda6afd48 Mon Sep 17 00:00:00 2001 From: Christian Meissl Date: Sat, 8 Jan 2022 12:22:59 +0100 Subject: [PATCH] add a window surface type --- src/desktop/layer.rs | 7 +++++-- src/desktop/utils.rs | 27 ++++++++++++++++++--------- src/desktop/window.rs | 40 +++++++++++++++++++++++++++++----------- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/desktop/layer.rs b/src/desktop/layer.rs index 1dc4b9a..a01f8e9 100644 --- a/src/desktop/layer.rs +++ b/src/desktop/layer.rs @@ -21,6 +21,8 @@ use std::{ sync::{Arc, Mutex, Weak}, }; +use super::WindowSurfaceType; + crate::utils::ids::id_gen!(next_layer_id, LAYER_ID, LAYER_IDS); /// Map of [`LayerSurface`]s on an [`Output`] @@ -428,6 +430,7 @@ impl LayerSurface { pub fn surface_under>>( &self, point: P, + surface_type: WindowSurfaceType, ) -> Option<(WlSurface, Point)> { let point = point.into(); if let Some(surface) = self.get_surface() { @@ -438,13 +441,13 @@ impl LayerSurface { { if let Some(result) = popup .get_surface() - .and_then(|surface| under_from_surface_tree(surface, point, location)) + .and_then(|surface| under_from_surface_tree(surface, point, location, surface_type)) { return Some(result); } } - under_from_surface_tree(surface, point, (0, 0)) + under_from_surface_tree(surface, point, (0, 0), surface_type) } else { None } diff --git a/src/desktop/utils.rs b/src/desktop/utils.rs index 380ae4e..f8d774c 100644 --- a/src/desktop/utils.rs +++ b/src/desktop/utils.rs @@ -16,6 +16,8 @@ use wayland_server::protocol::wl_surface; use std::cell::RefCell; +use super::WindowSurfaceType; + impl SurfaceState { /// Returns the size of the surface. pub fn size(&self) -> Option> { @@ -174,6 +176,7 @@ pub fn under_from_surface_tree

( surface: &wl_surface::WlSurface, point: Point, location: P, + surface_type: WindowSurfaceType, ) -> Option<(wl_surface::WlSurface, Point)> where P: Into>, @@ -191,17 +194,23 @@ where location += current.location; } - let contains_the_point = data - .map(|data| { - data.borrow() - .contains_point(&*states.cached_state.current(), point - location.to_f64()) - }) - .unwrap_or(false); - if contains_the_point { - *found.borrow_mut() = Some((wl_surface.clone(), location)); + if states.role == Some("subsurface") || surface_type.contains(WindowSurfaceType::TOPLEVEL) { + let contains_the_point = data + .map(|data| { + data.borrow() + .contains_point(&*states.cached_state.current(), point - location.to_f64()) + }) + .unwrap_or(false); + if contains_the_point { + *found.borrow_mut() = Some((wl_surface.clone(), location)); + } } - TraversalAction::DoChildren(location) + if surface_type.contains(WindowSurfaceType::SUBSURFACE) { + TraversalAction::DoChildren(location) + } else { + TraversalAction::SkipChildren + } }, |_, _, _| {}, |_, _, _| { diff --git a/src/desktop/window.rs b/src/desktop/window.rs index 1c57b1a..4e5761f 100644 --- a/src/desktop/window.rs +++ b/src/desktop/window.rs @@ -109,6 +109,21 @@ impl Hash for Window { } } +bitflags::bitflags! { + /// Defines the surface types that can be + /// queried with [`Window::surface_under`] + pub struct WindowSurfaceType: u32 { + /// Include the toplevel surface + const TOPLEVEL = 1; + /// Include all subsurfaces + const SUBSURFACE = 2; + /// Include all popup surfaces + const POPUP = 4; + /// Query all surfaces + const ALL = Self::TOPLEVEL.bits | Self::SUBSURFACE.bits | Self::POPUP.bits; + } +} + impl Window { /// Construct a new [`Window`] from a given compatible toplevel surface pub fn new(toplevel: Kind) -> Window { @@ -222,24 +237,27 @@ impl Window { pub fn surface_under>>( &self, point: P, + surface_type: WindowSurfaceType, ) -> Option<(wl_surface::WlSurface, Point)> { let point = point.into(); if let Some(surface) = self.0.toplevel.get_surface() { - for (popup, location) in PopupManager::popups_for_surface(surface) - .ok() - .into_iter() - .flatten() - { - let offset = self.geometry().loc + location - popup.geometry().loc; - if let Some(result) = popup - .get_surface() - .and_then(|surface| under_from_surface_tree(surface, point, offset)) + if surface_type.contains(WindowSurfaceType::POPUP) { + for (popup, location) in PopupManager::popups_for_surface(surface) + .ok() + .into_iter() + .flatten() { - return Some(result); + let offset = self.geometry().loc + location - popup.geometry().loc; + if let Some(result) = popup + .get_surface() + .and_then(|surface| under_from_surface_tree(surface, point, offset, surface_type)) + { + return Some(result); + } } } - under_from_surface_tree(surface, point, (0, 0)) + under_from_surface_tree(surface, point, (0, 0), surface_type) } else { None }