compositor: allow the choice or iteration direction in subsurface trees

This commit is contained in:
Victor Berger 2017-09-22 11:12:49 +02:00
parent 3dd559cdf1
commit 648da00c6a
2 changed files with 56 additions and 12 deletions

View File

@ -298,7 +298,7 @@ where
R: RoleType + Role<SubsurfaceRole> + 'static, R: RoleType + Role<SubsurfaceRole> + 'static,
ID: 'static, ID: 'static,
{ {
/// Access the data of a surface tree /// Access the data of a surface tree from bottom to top
/// ///
/// The provided closure is called successively on the surface and all its child subsurfaces, /// The provided closure is called successively on the surface and all its child subsurfaces,
/// in a depth-first order. This matches the order in which the surfaces are supposed to be /// in a depth-first order. This matches the order in which the surfaces are supposed to be
@ -314,7 +314,8 @@ where
/// ///
/// If the surface not managed by the CompositorGlobal that provided this token, this /// If the surface 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, T>(&self, surface: &wl_surface::WlSurface, initial: T, f: F) -> Result<(), ()> pub fn with_surface_tree_upward<F, T>(&self, surface: &wl_surface::WlSurface, initial: T, f: F)
-> Result<(), ()>
where where
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T)
-> TraversalAction<T>, -> TraversalAction<T>,
@ -327,7 +328,33 @@ where
"Accessing the data of foreign surfaces is not supported." "Accessing the data of foreign surfaces is not supported."
); );
unsafe { unsafe {
SurfaceData::<U, R>::map_tree(surface, initial, f); SurfaceData::<U, R>::map_tree(surface, initial, f, false);
}
Ok(())
}
/// Access the data of a surface tree from top to bottom
///
/// The provided closure is called successively on the surface and all its child subsurfaces,
/// in a depth-first order. This matches the reverse of the order in which the surfaces are
/// supposed to be drawn: top-most first.
///
/// Behavior is the same as `with_surface_tree_upward`.
pub fn with_surface_tree_downward<F, T>(&self, surface: &wl_surface::WlSurface, initial: T, f: F)
-> Result<(), ()>
where
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T)
-> TraversalAction<T>,
{
assert!(
resource_is_registered(
surface,
&self::handlers::surface_implementation::<U, R, ID>()
),
"Accessing the data of foreign surfaces is not supported."
);
unsafe {
SurfaceData::<U, R>::map_tree(surface, initial, f, true);
} }
Ok(()) Ok(())
} }

View File

@ -307,21 +307,22 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
} }
/// Access sequentially the attributes associated with a surface tree, /// Access sequentially the attributes associated with a surface tree,
/// in a depth-first order /// in a depth-first order.
/// ///
/// Note that an internal lock is taken during access of this data, /// Note that an internal lock is taken during access of this data,
/// so the tree cannot be manipulated at the same time. /// so the tree cannot be manipulated at the same time.
/// ///
/// 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, T>(root: &wl_surface::WlSurface, initial: T, mut f: F) pub unsafe fn map_tree<F, T>(root: &wl_surface::WlSurface, initial: T, mut f: F, reverse: bool)
where where
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T)
-> TraversalAction<T>, -> TraversalAction<T>,
{ {
// helper function for recursion // helper function for recursion
unsafe fn map<U: 'static, R: 'static, F, T>(surface: &wl_surface::WlSurface, unsafe fn map<U: 'static, R: 'static, F, T>(surface: &wl_surface::WlSurface,
root: &wl_surface::WlSurface, initial: &T, f: &mut F) root: &wl_surface::WlSurface, initial: &T, f: &mut F,
reverse: bool)
-> bool -> bool
where where
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T)
@ -344,11 +345,19 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
) { ) {
TraversalAction::DoChildren(t) => { TraversalAction::DoChildren(t) => {
// loop over children // loop over children
for c in &data_guard.children { if reverse {
if !map::<U, R, _, _>(c, root, &t, f) { for c in data_guard.children.iter().rev() {
if !map::<U, R, _, _>(c, root, &t, f, true) {
return false; return false;
} }
} }
} else {
for c in &data_guard.children {
if !map::<U, R, _, _>(c, root, &t, f, false) {
return false;
}
}
}
true true
} }
TraversalAction::SkipChildren => true, TraversalAction::SkipChildren => true,
@ -368,11 +377,19 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
) { ) {
TraversalAction::DoChildren(t) => { TraversalAction::DoChildren(t) => {
// loop over children // loop over children
for c in &data_guard.children { if reverse {
if !map::<U, R, _, _>(c, root, &t, &mut f) { for c in data_guard.children.iter().rev() {
if !map::<U, R, _, _>(c, root, &t, &mut f, true) {
break; break;
} }
} }
} else {
for c in &data_guard.children {
if !map::<U, R, _, _>(c, root, &t, &mut f, false) {
break;
}
}
}
} }
_ => {} _ => {}
} }