compositor: TraversalAction for tree traversal
This commit is contained in:
parent
19634f30ed
commit
a487c5963a
|
@ -147,18 +147,21 @@ fn main() {
|
|||
continue;
|
||||
}
|
||||
// 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 {
|
||||
// there is actually something to draw !
|
||||
let mut x = 100;
|
||||
let mut y = 100;
|
||||
if let Some(ref subdata) = attributes.subsurface_attributes {
|
||||
x += subdata.x;
|
||||
y += subdata.y;
|
||||
}
|
||||
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;
|
||||
|
||||
use self::region::RegionData;
|
||||
pub use self::tree::RoleStatus;
|
||||
pub use self::tree::{RoleStatus, TraversalAction};
|
||||
use self::tree::SurfaceData;
|
||||
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
|
||||
/// will panic (having more than one compositor is not supported).
|
||||
pub fn with_surface_tree<F>(&self, surface: &wl_surface::WlSurface, f: F) -> Result<(), ()>
|
||||
where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>) -> bool
|
||||
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>, &T) -> TraversalAction<T>
|
||||
{
|
||||
assert!(resource_is_registered::<_, CompositorHandler<U, H>>(surface, self.hid),
|
||||
"Accessing the data of foreign surfaces is not supported.");
|
||||
unsafe {
|
||||
SurfaceData::<U>::map_tree(surface, f);
|
||||
SurfaceData::<U>::map_tree(surface, initial, f);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -48,6 +48,16 @@ pub enum Location {
|
|||
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> {
|
||||
fn new() -> SurfaceData<U> {
|
||||
SurfaceData {
|
||||
|
@ -275,12 +285,14 @@ impl<U> SurfaceData<U> {
|
|||
///
|
||||
/// The callback returns wether the traversal should continue or not. Returning
|
||||
/// false will cause an early-stopping.
|
||||
pub unsafe fn map_tree<F>(root: &wl_surface::WlSurface, mut f: F)
|
||||
where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>) -> bool
|
||||
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>, &T) -> TraversalAction<T>
|
||||
{
|
||||
// helper function for recursion
|
||||
unsafe fn map<U, F>(surface: &wl_surface::WlSurface, root: &wl_surface::WlSurface, f: &mut F) -> bool
|
||||
where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>) -> bool
|
||||
unsafe fn map<U, F, T>(surface: &wl_surface::WlSurface, root: &wl_surface::WlSurface, initial: &T,
|
||||
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
|
||||
if surface.equals(root) {
|
||||
|
@ -290,27 +302,34 @@ impl<U> SurfaceData<U> {
|
|||
let data_mutex = SurfaceData::<U>::get_data(surface);
|
||||
let mut data_guard = data_mutex.lock().unwrap();
|
||||
// call the callback on ourselves
|
||||
if f(surface, &mut data_guard.attributes) {
|
||||
// loop over children
|
||||
for c in &data_guard.children {
|
||||
if !map(c, root, f) {
|
||||
return false;
|
||||
match f(surface, &mut data_guard.attributes, initial) {
|
||||
TraversalAction::DoChildren(t) => {
|
||||
// loop over children
|
||||
for c in &data_guard.children {
|
||||
if !map(c, root, &t, f) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
TraversalAction::SkipChildren => true,
|
||||
TraversalAction::Break => false,
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
let data_mutex = Self::get_data(root);
|
||||
let mut data_guard = data_mutex.lock().unwrap();
|
||||
// call the callback on ourselves
|
||||
if f(root, &mut data_guard.attributes) {
|
||||
// loop over children
|
||||
for c in &data_guard.children {
|
||||
if !map::<U, _>(c, root, &mut f) {
|
||||
break;
|
||||
match f(root, &mut data_guard.attributes, &initial) {
|
||||
TraversalAction::DoChildren(t) => {
|
||||
// loop over children
|
||||
for c in &data_guard.children {
|
||||
if !map::<U, _, _>(c, root, &t, &mut f) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue