2018-10-04 22:37:43 +00:00
|
|
|
use super::{roles::*, SubsurfaceRole, SurfaceAttributes};
|
2017-06-04 15:47:37 +00:00
|
|
|
use std::sync::Mutex;
|
2019-02-22 20:46:26 +00:00
|
|
|
use wayland_server::protocol::wl_surface::WlSurface;
|
2017-06-04 15:47:37 +00:00
|
|
|
|
|
|
|
/// Node of a subsurface tree, holding some user specified data type U
|
|
|
|
/// at each node
|
|
|
|
///
|
|
|
|
/// This type is internal to Smithay, and should not appear in the
|
|
|
|
/// public API
|
|
|
|
///
|
2018-10-30 12:56:30 +00:00
|
|
|
/// It is a bidirectional tree, meaning we can move along it in both
|
2017-06-04 15:47:37 +00:00
|
|
|
/// direction (top-bottom or bottom-up). We are taking advantage of the
|
2018-10-30 12:56:30 +00:00
|
|
|
/// fact that lifetime of objects are decided by Wayland-server to ensure
|
2017-06-04 15:47:37 +00:00
|
|
|
/// the cleanup will be done properly, and we won't leak anything.
|
|
|
|
///
|
|
|
|
/// This implementation is not strictly a tree, but rather a directed graph
|
|
|
|
/// with the constraint that node can have at most one incoming edge. Aka like
|
2018-10-30 12:56:30 +00:00
|
|
|
/// a tree, but with loops allowed. This is because the Wayland protocol does not
|
2017-06-04 15:47:37 +00:00
|
|
|
/// have a failure case to forbid this. Note that if any node in such a graph does not
|
|
|
|
/// have a parent, then the graph is a tree and this node is its root.
|
2017-09-03 17:53:29 +00:00
|
|
|
pub struct SurfaceData<U, R> {
|
2019-02-22 16:55:00 +00:00
|
|
|
parent: Option<WlSurface>,
|
|
|
|
children: Vec<WlSurface>,
|
2017-09-03 17:53:29 +00:00
|
|
|
role: R,
|
2017-06-04 15:47:37 +00:00
|
|
|
attributes: SurfaceAttributes<U>,
|
|
|
|
}
|
|
|
|
|
2017-06-04 20:41:42 +00:00
|
|
|
pub enum Location {
|
|
|
|
Before,
|
|
|
|
After,
|
|
|
|
}
|
|
|
|
|
2017-06-13 15:38:25 +00:00
|
|
|
/// 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,
|
|
|
|
}
|
|
|
|
|
2017-09-03 17:53:29 +00:00
|
|
|
impl<U: Default, R: Default> SurfaceData<U, R> {
|
2018-09-24 22:30:39 +00:00
|
|
|
pub fn new() -> Mutex<SurfaceData<U, R>> {
|
|
|
|
Mutex::new(SurfaceData {
|
2017-06-04 15:47:37 +00:00
|
|
|
parent: None,
|
|
|
|
children: Vec::new(),
|
2017-09-03 17:53:29 +00:00
|
|
|
role: Default::default(),
|
2017-06-04 15:47:37 +00:00
|
|
|
attributes: Default::default(),
|
2018-09-24 22:30:39 +00:00
|
|
|
})
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
impl<U, R> SurfaceData<U, R>
|
|
|
|
where
|
|
|
|
U: 'static,
|
|
|
|
R: 'static,
|
|
|
|
{
|
2019-02-22 16:55:00 +00:00
|
|
|
/// Cleans the `as_ref().user_data` of that surface, must be called when it is destroyed
|
|
|
|
pub fn cleanup(surface: &WlSurface) {
|
|
|
|
let my_data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2018-09-24 22:30:39 +00:00
|
|
|
let mut my_data = my_data_mutex.lock().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
if let Some(old_parent) = my_data.parent.take() {
|
2019-02-22 16:55:00 +00:00
|
|
|
if !old_parent.as_ref().equals(surface.as_ref()) {
|
2017-06-04 15:47:37 +00:00
|
|
|
// We had a parent that is not ourselves, lets unregister ourselves from it
|
2019-02-22 16:55:00 +00:00
|
|
|
let old_parent_mutex = old_parent
|
|
|
|
.as_ref()
|
|
|
|
.user_data::<Mutex<SurfaceData<U, R>>>()
|
|
|
|
.unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut old_parent_guard = old_parent_mutex.lock().unwrap();
|
2019-02-22 16:55:00 +00:00
|
|
|
old_parent_guard
|
|
|
|
.children
|
|
|
|
.retain(|c| !c.as_ref().equals(surface.as_ref()));
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// orphan all our children
|
|
|
|
for child in &my_data.children {
|
|
|
|
// don't do anything if this child is ourselves
|
2019-02-22 16:55:00 +00:00
|
|
|
if child.as_ref().equals(surface.as_ref()) {
|
2017-06-04 15:47:37 +00:00
|
|
|
continue;
|
|
|
|
}
|
2019-02-22 16:55:00 +00:00
|
|
|
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut child_guard = child_mutex.lock().unwrap();
|
|
|
|
child_guard.parent = None;
|
|
|
|
}
|
|
|
|
}
|
2017-09-03 17:53:29 +00:00
|
|
|
}
|
2017-06-04 15:47:37 +00:00
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
impl<U: 'static, R: RoleType + 'static> SurfaceData<U, R> {
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn has_a_role(surface: &WlSurface) -> bool {
|
|
|
|
debug_assert!(surface.as_ref().is_alive());
|
|
|
|
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let data_guard = data_mutex.lock().unwrap();
|
2017-09-03 17:53:29 +00:00
|
|
|
<R as RoleType>::has_role(&data_guard.role)
|
|
|
|
}
|
|
|
|
|
2018-10-30 12:56:30 +00:00
|
|
|
/// Check whether a surface has a given role
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn has_role<RoleData>(surface: &WlSurface) -> bool
|
2017-09-03 17:53:29 +00:00
|
|
|
where
|
|
|
|
R: Role<RoleData>,
|
|
|
|
{
|
2019-02-22 16:55:00 +00:00
|
|
|
debug_assert!(surface.as_ref().is_alive());
|
|
|
|
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-09-03 17:53:29 +00:00
|
|
|
let data_guard = data_mutex.lock().unwrap();
|
|
|
|
<R as Role<RoleData>>::has(&data_guard.role)
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Register that this surface has a role, fails if it already has one
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn give_role<RoleData>(surface: &WlSurface) -> Result<(), ()>
|
2017-09-03 17:53:29 +00:00
|
|
|
where
|
|
|
|
R: Role<RoleData>,
|
|
|
|
RoleData: Default,
|
|
|
|
{
|
2019-02-22 16:55:00 +00:00
|
|
|
debug_assert!(surface.as_ref().is_alive());
|
|
|
|
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut data_guard = data_mutex.lock().unwrap();
|
2017-09-03 17:53:29 +00:00
|
|
|
<R as Role<RoleData>>::set(&mut data_guard.role)
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-03 17:53:29 +00:00
|
|
|
/// Register that this surface has a role with given data
|
|
|
|
///
|
|
|
|
/// Fails if it already has one and returns the data
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn give_role_with<RoleData>(surface: &WlSurface, data: RoleData) -> Result<(), RoleData>
|
2017-09-03 17:53:29 +00:00
|
|
|
where
|
|
|
|
R: Role<RoleData>,
|
|
|
|
{
|
2019-02-22 16:55:00 +00:00
|
|
|
debug_assert!(surface.as_ref().is_alive());
|
|
|
|
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-09-03 17:53:29 +00:00
|
|
|
let mut data_guard = data_mutex.lock().unwrap();
|
|
|
|
<R as Role<RoleData>>::set_with(&mut data_guard.role, data)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Register that this surface has no role and returns the data
|
2017-06-04 15:47:37 +00:00
|
|
|
///
|
|
|
|
/// It is a noop if this surface already didn't have one, but fails if
|
|
|
|
/// the role was "subsurface", it must be removed by the `unset_parent` method.
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn remove_role<RoleData>(surface: &WlSurface) -> Result<RoleData, WrongRole>
|
2017-09-03 17:53:29 +00:00
|
|
|
where
|
|
|
|
R: Role<RoleData>,
|
|
|
|
{
|
2019-02-22 16:55:00 +00:00
|
|
|
debug_assert!(surface.as_ref().is_alive());
|
|
|
|
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut data_guard = data_mutex.lock().unwrap();
|
2017-09-03 17:53:29 +00:00
|
|
|
<R as Role<RoleData>>::unset(&mut data_guard.role)
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
2017-09-03 17:53:29 +00:00
|
|
|
/// Access to the role data
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn with_role_data<RoleData, F, T>(surface: &WlSurface, f: F) -> Result<T, WrongRole>
|
2017-09-03 17:53:29 +00:00
|
|
|
where
|
|
|
|
R: Role<RoleData>,
|
|
|
|
F: FnOnce(&mut RoleData) -> T,
|
|
|
|
{
|
2019-02-22 16:55:00 +00:00
|
|
|
debug_assert!(surface.as_ref().is_alive());
|
|
|
|
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-09-03 17:53:29 +00:00
|
|
|
let mut data_guard = data_mutex.lock().unwrap();
|
|
|
|
let data = <R as Role<RoleData>>::data_mut(&mut data_guard.role)?;
|
|
|
|
Ok(f(data))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
impl<U: 'static, R: RoleType + Role<SubsurfaceRole> + 'static> SurfaceData<U, R> {
|
2017-06-04 15:47:37 +00:00
|
|
|
/// Sets the parent of a surface
|
2017-09-03 17:53:29 +00:00
|
|
|
///
|
2017-06-04 15:47:37 +00:00
|
|
|
/// if this surface already has a role, does nothing and fails, otherwise
|
|
|
|
/// its role is now to be a subsurface
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn set_parent(child: &WlSurface, parent: &WlSurface) -> Result<(), ()> {
|
|
|
|
debug_assert!(child.as_ref().is_alive());
|
|
|
|
debug_assert!(parent.as_ref().is_alive());
|
2017-06-04 15:47:37 +00:00
|
|
|
|
|
|
|
// change child's parent
|
|
|
|
{
|
2019-02-22 16:55:00 +00:00
|
|
|
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut child_guard = child_mutex.lock().unwrap();
|
2017-09-03 17:53:29 +00:00
|
|
|
// if surface already has a role, it cannot become a subsurface
|
|
|
|
<R as Role<SubsurfaceRole>>::set(&mut child_guard.role)?;
|
2017-06-04 15:47:37 +00:00
|
|
|
debug_assert!(child_guard.parent.is_none());
|
2018-04-17 09:03:42 +00:00
|
|
|
child_guard.parent = Some(parent.clone());
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
// register child to new parent
|
|
|
|
// double scoping is to be robust to have a child be its own parent
|
|
|
|
{
|
2019-02-22 16:55:00 +00:00
|
|
|
let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut parent_guard = parent_mutex.lock().unwrap();
|
2018-04-17 09:03:42 +00:00
|
|
|
parent_guard.children.push(child.clone())
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Remove a pre-existing parent of this child
|
|
|
|
///
|
|
|
|
/// Does nothing if it has no parent
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn unset_parent(child: &WlSurface) {
|
|
|
|
debug_assert!(child.as_ref().is_alive());
|
2017-06-04 15:47:37 +00:00
|
|
|
let old_parent = {
|
2019-02-22 16:55:00 +00:00
|
|
|
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut child_guard = child_mutex.lock().unwrap();
|
|
|
|
let old_parent = child_guard.parent.take();
|
|
|
|
if old_parent.is_some() {
|
|
|
|
// We had a parent, so this does not have a role any more
|
2017-09-03 17:53:29 +00:00
|
|
|
<R as Role<SubsurfaceRole>>::unset(&mut child_guard.role)
|
|
|
|
.expect("Surface had a parent but not the subsurface role?!");
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
old_parent
|
|
|
|
};
|
|
|
|
// unregister from our parent
|
|
|
|
if let Some(old_parent) = old_parent {
|
2019-02-22 16:55:00 +00:00
|
|
|
let parent_mutex = old_parent
|
|
|
|
.as_ref()
|
|
|
|
.user_data::<Mutex<SurfaceData<U, R>>>()
|
|
|
|
.unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut parent_guard = parent_mutex.lock().unwrap();
|
2019-02-22 16:55:00 +00:00
|
|
|
parent_guard
|
|
|
|
.children
|
|
|
|
.retain(|c| !c.as_ref().equals(child.as_ref()));
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Retrieve the parent surface (if any) of this surface
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn get_parent(child: &WlSurface) -> Option<WlSurface> {
|
|
|
|
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let child_guard = child_mutex.lock().unwrap();
|
2018-06-28 09:33:49 +00:00
|
|
|
child_guard.parent.as_ref().cloned()
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
|
2017-06-11 12:31:42 +00:00
|
|
|
/// Retrieve the parent surface (if any) of this surface
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn get_children(child: &WlSurface) -> Vec<WlSurface> {
|
|
|
|
let child_mutex = child.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-11 12:31:42 +00:00
|
|
|
let child_guard = child_mutex.lock().unwrap();
|
2018-06-28 09:33:49 +00:00
|
|
|
child_guard.children.to_vec()
|
2017-06-11 12:31:42 +00:00
|
|
|
}
|
|
|
|
|
2017-06-04 20:41:42 +00:00
|
|
|
/// Reorders a surface relative to one of its sibling
|
|
|
|
///
|
|
|
|
/// Fails if `relative_to` is not a sibling or parent of `surface`.
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn reorder(surface: &WlSurface, to: Location, relative_to: &WlSurface) -> Result<(), ()> {
|
2017-06-04 20:41:42 +00:00
|
|
|
let parent = {
|
2019-02-22 16:55:00 +00:00
|
|
|
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 20:41:42 +00:00
|
|
|
let data_guard = data_mutex.lock().unwrap();
|
2018-06-28 09:33:49 +00:00
|
|
|
data_guard.parent.as_ref().cloned().unwrap()
|
2017-06-04 20:41:42 +00:00
|
|
|
};
|
2019-02-22 16:55:00 +00:00
|
|
|
if parent.as_ref().equals(relative_to.as_ref()) {
|
2017-06-04 20:41:42 +00:00
|
|
|
// TODO: handle positioning relative to parent
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2019-02-22 16:55:00 +00:00
|
|
|
fn index_of(surface: &WlSurface, slice: &[WlSurface]) -> Option<usize> {
|
2017-06-04 20:41:42 +00:00
|
|
|
for (i, s) in slice.iter().enumerate() {
|
2019-02-22 16:55:00 +00:00
|
|
|
if s.as_ref().equals(surface.as_ref()) {
|
2017-06-04 20:41:42 +00:00
|
|
|
return Some(i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
|
|
|
|
2019-02-22 16:55:00 +00:00
|
|
|
let parent_mutex = parent.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 20:41:42 +00:00
|
|
|
let mut parent_guard = parent_mutex.lock().unwrap();
|
|
|
|
let my_index = index_of(surface, &parent_guard.children).unwrap();
|
|
|
|
let mut other_index = match index_of(surface, &parent_guard.children) {
|
|
|
|
Some(idx) => idx,
|
|
|
|
None => return Err(()),
|
|
|
|
};
|
|
|
|
let me = parent_guard.children.remove(my_index);
|
|
|
|
if my_index < other_index {
|
|
|
|
other_index -= 1;
|
|
|
|
}
|
|
|
|
let new_index = match to {
|
|
|
|
Location::Before => other_index,
|
|
|
|
Location::After => other_index + 1,
|
|
|
|
};
|
|
|
|
parent_guard.children.insert(new_index, me);
|
|
|
|
Ok(())
|
|
|
|
}
|
2017-09-03 17:53:29 +00:00
|
|
|
}
|
2017-06-04 20:41:42 +00:00
|
|
|
|
2017-09-20 07:57:43 +00:00
|
|
|
impl<U: 'static, R: 'static> SurfaceData<U, R> {
|
2017-06-04 15:47:37 +00:00
|
|
|
/// Access the attributes associated with a surface
|
|
|
|
///
|
|
|
|
/// Note that an internal lock is taken during access of this data,
|
|
|
|
/// so the tree cannot be manipulated at the same time
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn with_data<T, F>(surface: &WlSurface, f: F) -> T
|
2017-06-23 13:40:28 +00:00
|
|
|
where
|
2017-09-03 17:53:29 +00:00
|
|
|
F: FnOnce(&mut SurfaceAttributes<U>) -> T,
|
2017-06-04 15:47:37 +00:00
|
|
|
{
|
2018-09-24 22:30:39 +00:00
|
|
|
let data_mutex = surface
|
2019-02-22 16:55:00 +00:00
|
|
|
.as_ref()
|
2018-09-24 22:30:39 +00:00
|
|
|
.user_data::<Mutex<SurfaceData<U, R>>>()
|
|
|
|
.expect("Accessing the data of foreign surfaces is not supported.");
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut data_guard = data_mutex.lock().unwrap();
|
|
|
|
f(&mut data_guard.attributes)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Access sequentially the attributes associated with a surface tree,
|
2017-09-22 09:12:49 +00:00
|
|
|
/// in a depth-first order.
|
2017-06-04 15:47:37 +00:00
|
|
|
///
|
|
|
|
/// Note that an internal lock is taken during access of this data,
|
|
|
|
/// so the tree cannot be manipulated at the same time.
|
|
|
|
///
|
2018-10-30 12:56:30 +00:00
|
|
|
/// The callback returns whether the traversal should continue or not. Returning
|
2017-06-04 15:47:37 +00:00
|
|
|
/// false will cause an early-stopping.
|
2019-02-22 16:55:00 +00:00
|
|
|
pub fn map_tree<F, T>(root: &WlSurface, initial: T, mut f: F, reverse: bool)
|
2017-06-23 13:40:28 +00:00
|
|
|
where
|
2019-02-22 16:55:00 +00:00
|
|
|
F: FnMut(&WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
2017-06-04 15:47:37 +00:00
|
|
|
{
|
|
|
|
// helper function for recursion
|
2018-09-24 22:30:39 +00:00
|
|
|
fn map<U: 'static, R: 'static, F, T>(
|
2019-02-22 16:55:00 +00:00
|
|
|
surface: &WlSurface,
|
|
|
|
root: &WlSurface,
|
2018-04-17 09:03:42 +00:00
|
|
|
initial: &T,
|
|
|
|
f: &mut F,
|
2017-12-15 17:38:10 +00:00
|
|
|
reverse: bool,
|
|
|
|
) -> bool
|
2017-06-23 13:40:28 +00:00
|
|
|
where
|
2019-02-22 16:55:00 +00:00
|
|
|
F: FnMut(&WlSurface, &mut SurfaceAttributes<U>, &mut R, &T) -> TraversalAction<T>,
|
2017-06-04 15:47:37 +00:00
|
|
|
{
|
|
|
|
// stop if we met the root, so to not deadlock/inifinte loop
|
2019-02-22 16:55:00 +00:00
|
|
|
if surface.as_ref().equals(root.as_ref()) {
|
2017-06-04 15:47:37 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-02-22 16:55:00 +00:00
|
|
|
let data_mutex = surface.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut data_guard = data_mutex.lock().unwrap();
|
2017-09-03 17:53:29 +00:00
|
|
|
let data_guard = &mut *data_guard;
|
2017-06-04 15:47:37 +00:00
|
|
|
// call the callback on ourselves
|
2018-09-24 22:30:39 +00:00
|
|
|
match f(surface, &mut data_guard.attributes, &mut data_guard.role, initial) {
|
2017-06-13 15:38:25 +00:00
|
|
|
TraversalAction::DoChildren(t) => {
|
|
|
|
// loop over children
|
2017-09-22 09:12:49 +00:00
|
|
|
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;
|
|
|
|
}
|
2017-06-13 15:38:25 +00:00
|
|
|
}
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
2017-06-13 15:38:25 +00:00
|
|
|
true
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
2017-06-13 15:38:25 +00:00
|
|
|
TraversalAction::SkipChildren => true,
|
|
|
|
TraversalAction::Break => false,
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-22 16:55:00 +00:00
|
|
|
let data_mutex = root.as_ref().user_data::<Mutex<SurfaceData<U, R>>>().unwrap();
|
2017-06-04 15:47:37 +00:00
|
|
|
let mut data_guard = data_mutex.lock().unwrap();
|
2017-09-03 17:53:29 +00:00
|
|
|
let data_guard = &mut *data_guard;
|
2017-06-04 15:47:37 +00:00
|
|
|
// call the callback on ourselves
|
2018-09-24 22:30:39 +00:00
|
|
|
if let TraversalAction::DoChildren(t) =
|
|
|
|
f(root, &mut data_guard.attributes, &mut data_guard.role, &initial)
|
|
|
|
{
|
2017-10-05 20:13:14 +00:00
|
|
|
// loop over children
|
|
|
|
if reverse {
|
|
|
|
for c in data_guard.children.iter().rev() {
|
|
|
|
if !map::<U, R, _, _>(c, root, &t, &mut f, true) {
|
|
|
|
break;
|
2017-09-22 09:12:49 +00:00
|
|
|
}
|
2017-10-05 20:13:14 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for c in &data_guard.children {
|
|
|
|
if !map::<U, R, _, _>(c, root, &t, &mut f, false) {
|
|
|
|
break;
|
2017-06-13 15:38:25 +00:00
|
|
|
}
|
2017-06-04 15:47:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|