From 648da00c6a0305ae4b920673ec66b051977efb4d Mon Sep 17 00:00:00 2001 From: Victor Berger Date: Fri, 22 Sep 2017 11:12:49 +0200 Subject: [PATCH] compositor: allow the choice or iteration direction in subsurface trees --- src/compositor/mod.rs | 33 ++++++++++++++++++++++++++++++--- src/compositor/tree.rs | 35 ++++++++++++++++++++++++++--------- 2 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/compositor/mod.rs b/src/compositor/mod.rs index cc9dd9d..ec819ed 100644 --- a/src/compositor/mod.rs +++ b/src/compositor/mod.rs @@ -298,7 +298,7 @@ where R: RoleType + Role + '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(&self, surface: &wl_surface::WlSurface, initial: T, f: F) -> Result<(), ()> + pub fn with_surface_tree_upward(&self, surface: &wl_surface::WlSurface, initial: T, f: F) + -> Result<(), ()> where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes, &mut R, &T) -> TraversalAction, @@ -327,7 +328,33 @@ where "Accessing the data of foreign surfaces is not supported." ); unsafe { - SurfaceData::::map_tree(surface, initial, f); + SurfaceData::::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(&self, surface: &wl_surface::WlSurface, initial: T, f: F) + -> Result<(), ()> + where + F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes, &mut R, &T) + -> TraversalAction, + { + assert!( + resource_is_registered( + surface, + &self::handlers::surface_implementation::() + ), + "Accessing the data of foreign surfaces is not supported." + ); + unsafe { + SurfaceData::::map_tree(surface, initial, f, true); } Ok(()) } diff --git a/src/compositor/tree.rs b/src/compositor/tree.rs index 10b2a55..6d261f8 100644 --- a/src/compositor/tree.rs +++ b/src/compositor/tree.rs @@ -307,21 +307,22 @@ impl SurfaceData { } /// 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(root: &wl_surface::WlSurface, initial: T, mut f: F) + pub unsafe fn map_tree(root: &wl_surface::WlSurface, initial: T, mut f: F, reverse: bool) where F: FnMut(&wl_surface::WlSurface, &mut SurfaceAttributes, &mut R, &T) -> TraversalAction, { // helper function for recursion unsafe fn map(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, &mut R, &T) @@ -344,9 +345,17 @@ impl SurfaceData { ) { TraversalAction::DoChildren(t) => { // loop over children - for c in &data_guard.children { - if !map::(c, root, &t, f) { - return false; + if reverse { + for c in data_guard.children.iter().rev() { + if !map::(c, root, &t, f, true) { + return false; + } + } + } else { + for c in &data_guard.children { + if !map::(c, root, &t, f, false) { + return false; + } } } true @@ -368,9 +377,17 @@ impl SurfaceData { ) { TraversalAction::DoChildren(t) => { // loop over children - for c in &data_guard.children { - if !map::(c, root, &t, &mut f) { - break; + if reverse { + for c in data_guard.children.iter().rev() { + if !map::(c, root, &t, &mut f, true) { + break; + } + } + } else { + for c in &data_guard.children { + if !map::(c, root, &t, &mut f, false) { + break; + } } } }