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,
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,
/// 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
/// 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
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T)
-> TraversalAction<T>,
@ -327,7 +328,33 @@ where
"Accessing the data of foreign surfaces is not supported."
);
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(())
}

View File

@ -307,21 +307,22 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
}
/// 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,
/// so the tree cannot be manipulated at the same time.
///
/// The callback returns wether the traversal should continue or not. Returning
/// 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
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T)
-> TraversalAction<T>,
{
// helper function for recursion
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
where
F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes<U>, &mut R, &T)
@ -344,9 +345,17 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
) {
TraversalAction::DoChildren(t) => {
// loop over children
for c in &data_guard.children {
if !map::<U, R, _, _>(c, root, &t, f) {
return false;
if reverse {
for c in data_guard.children.iter().rev() {
if !map::<U, R, _, _>(c, root, &t, f, true) {
return false;
}
}
} else {
for c in &data_guard.children {
if !map::<U, R, _, _>(c, root, &t, f, false) {
return false;
}
}
}
true
@ -368,9 +377,17 @@ impl<U: 'static, R: 'static> SurfaceData<U, R> {
) {
TraversalAction::DoChildren(t) => {
// loop over children
for c in &data_guard.children {
if !map::<U, R, _, _>(c, root, &t, &mut f) {
break;
if reverse {
for c in data_guard.children.iter().rev() {
if !map::<U, R, _, _>(c, root, &t, &mut f, true) {
break;
}
}
} else {
for c in &data_guard.children {
if !map::<U, R, _, _>(c, root, &t, &mut f, false) {
break;
}
}
}
}