add a window surface type

This commit is contained in:
Christian Meissl 2022-01-08 12:22:59 +01:00
parent 050c648bff
commit 8edcdf5cd0
3 changed files with 52 additions and 22 deletions

View File

@ -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<P: Into<Point<f64, Logical>>>(
&self,
point: P,
surface_type: WindowSurfaceType,
) -> Option<(WlSurface, Point<i32, Logical>)> {
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
}

View File

@ -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<Size<i32, Logical>> {
@ -174,6 +176,7 @@ pub fn under_from_surface_tree<P>(
surface: &wl_surface::WlSurface,
point: Point<f64, Logical>,
location: P,
surface_type: WindowSurfaceType,
) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)>
where
P: Into<Point<i32, Logical>>,
@ -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
}
},
|_, _, _| {},
|_, _, _| {

View File

@ -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<P: Into<Point<f64, Logical>>>(
&self,
point: P,
surface_type: WindowSurfaceType,
) -> Option<(wl_surface::WlSurface, Point<i32, Logical>)> {
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
}