compositor: TraversalAction for tree traversal
This commit is contained in:
parent
19634f30ed
commit
a487c5963a
|
@ -147,18 +147,21 @@ fn main() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// this surface is a root of a subsurface tree that needs to be drawn
|
// this surface is a root of a subsurface tree that needs to be drawn
|
||||||
compositor_token.with_surface_tree(surface, |surface, attributes| {
|
compositor_token.with_surface_tree(surface, (100, 100), |surface,
|
||||||
|
attributes,
|
||||||
|
&(mut x, mut y)| {
|
||||||
if let Some((ref contents, (w, h))) = attributes.user_data.buffer {
|
if let Some((ref contents, (w, h))) = attributes.user_data.buffer {
|
||||||
// there is actually something to draw !
|
// there is actually something to draw !
|
||||||
let mut x = 100;
|
|
||||||
let mut y = 100;
|
|
||||||
if let Some(ref subdata) = attributes.subsurface_attributes {
|
if let Some(ref subdata) = attributes.subsurface_attributes {
|
||||||
x += subdata.x;
|
x += subdata.x;
|
||||||
y += subdata.y;
|
y += subdata.y;
|
||||||
}
|
}
|
||||||
drawer.draw(&mut frame, contents, (w, h), (x, y), screen_dimensions);
|
drawer.draw(&mut frame, contents, (w, h), (x, y), screen_dimensions);
|
||||||
|
TraversalAction::DoChildren((x, y))
|
||||||
|
} else {
|
||||||
|
// we are not display, so our children are neither
|
||||||
|
TraversalAction::SkipChildren
|
||||||
}
|
}
|
||||||
true
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,7 @@ mod tree;
|
||||||
mod region;
|
mod region;
|
||||||
|
|
||||||
use self::region::RegionData;
|
use self::region::RegionData;
|
||||||
pub use self::tree::RoleStatus;
|
pub use self::tree::{RoleStatus, TraversalAction};
|
||||||
use self::tree::SurfaceData;
|
use self::tree::SurfaceData;
|
||||||
use wayland_server::{Client, EventLoopHandle, Init, resource_is_registered};
|
use wayland_server::{Client, EventLoopHandle, Init, resource_is_registered};
|
||||||
|
|
||||||
|
@ -302,13 +302,13 @@ impl<U: Send + 'static, H: Handler<U> + Send + 'static> CompositorToken<U, H> {
|
||||||
///
|
///
|
||||||
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
/// If the surface is not managed by the CompositorGlobal that provided this token, this
|
||||||
/// will panic (having more than one compositor is not supported).
|
/// will panic (having more than one compositor is not supported).
|
||||||
pub fn with_surface_tree<F>(&self, surface: &wl_surface::WlSurface, f: F) -> Result<(), ()>
|
pub fn with_surface_tree<F, T>(&self, surface: &wl_surface::WlSurface, initial: T, f: F) -> Result<(), ()>
|
||||||
where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>) -> bool
|
where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &T) -> TraversalAction<T>
|
||||||
{
|
{
|
||||||
assert!(resource_is_registered::<_, CompositorHandler<U, H>>(surface, self.hid),
|
assert!(resource_is_registered::<_, CompositorHandler<U, H>>(surface, self.hid),
|
||||||
"Accessing the data of foreign surfaces is not supported.");
|
"Accessing the data of foreign surfaces is not supported.");
|
||||||
unsafe {
|
unsafe {
|
||||||
SurfaceData::<U>::map_tree(surface, f);
|
SurfaceData::<U>::map_tree(surface, initial, f);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,16 @@ pub enum Location {
|
||||||
After,
|
After,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Possible actions to do after handling a node diring tree traversal
|
||||||
|
pub enum TraversalAction<T> {
|
||||||
|
/// Traverse its children as well, providing them the data T
|
||||||
|
DoChildren(T),
|
||||||
|
/// Skip its children
|
||||||
|
SkipChildren,
|
||||||
|
/// Stop traversal completely
|
||||||
|
Break,
|
||||||
|
}
|
||||||
|
|
||||||
impl<U: Default> SurfaceData<U> {
|
impl<U: Default> SurfaceData<U> {
|
||||||
fn new() -> SurfaceData<U> {
|
fn new() -> SurfaceData<U> {
|
||||||
SurfaceData {
|
SurfaceData {
|
||||||
|
@ -275,12 +285,14 @@ impl<U> SurfaceData<U> {
|
||||||
///
|
///
|
||||||
/// The callback returns wether the traversal should continue or not. Returning
|
/// The callback returns wether the traversal should continue or not. Returning
|
||||||
/// false will cause an early-stopping.
|
/// false will cause an early-stopping.
|
||||||
pub unsafe fn map_tree<F>(root: &wl_surface::WlSurface, mut f: F)
|
pub unsafe fn map_tree<F, T>(root: &wl_surface::WlSurface, initial: T, mut f: F)
|
||||||
where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>) -> bool
|
where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &T) -> TraversalAction<T>
|
||||||
{
|
{
|
||||||
// helper function for recursion
|
// helper function for recursion
|
||||||
unsafe fn map<U, F>(surface: &wl_surface::WlSurface, root: &wl_surface::WlSurface, f: &mut F) -> bool
|
unsafe fn map<U, F, T>(surface: &wl_surface::WlSurface, root: &wl_surface::WlSurface, initial: &T,
|
||||||
where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>) -> bool
|
f: &mut F)
|
||||||
|
-> bool
|
||||||
|
where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &T) -> TraversalAction<T>
|
||||||
{
|
{
|
||||||
// stop if we met the root, so to not deadlock/inifinte loop
|
// stop if we met the root, so to not deadlock/inifinte loop
|
||||||
if surface.equals(root) {
|
if surface.equals(root) {
|
||||||
|
@ -290,27 +302,34 @@ impl<U> SurfaceData<U> {
|
||||||
let data_mutex = SurfaceData::<U>::get_data(surface);
|
let data_mutex = SurfaceData::<U>::get_data(surface);
|
||||||
let mut data_guard = data_mutex.lock().unwrap();
|
let mut data_guard = data_mutex.lock().unwrap();
|
||||||
// call the callback on ourselves
|
// call the callback on ourselves
|
||||||
if f(surface, &mut data_guard.attributes) {
|
match f(surface, &mut data_guard.attributes, initial) {
|
||||||
// loop over children
|
TraversalAction::DoChildren(t) => {
|
||||||
for c in &data_guard.children {
|
// loop over children
|
||||||
if !map(c, root, f) {
|
for c in &data_guard.children {
|
||||||
return false;
|
if !map(c, root, &t, f) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
TraversalAction::SkipChildren => true,
|
||||||
|
TraversalAction::Break => false,
|
||||||
}
|
}
|
||||||
true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let data_mutex = Self::get_data(root);
|
let data_mutex = Self::get_data(root);
|
||||||
let mut data_guard = data_mutex.lock().unwrap();
|
let mut data_guard = data_mutex.lock().unwrap();
|
||||||
// call the callback on ourselves
|
// call the callback on ourselves
|
||||||
if f(root, &mut data_guard.attributes) {
|
match f(root, &mut data_guard.attributes, &initial) {
|
||||||
// loop over children
|
TraversalAction::DoChildren(t) => {
|
||||||
for c in &data_guard.children {
|
// loop over children
|
||||||
if !map::<U, _>(c, root, &mut f) {
|
for c in &data_guard.children {
|
||||||
break;
|
if !map::<U, _, _>(c, root, &t, &mut f) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue