diff --git a/core/src/widget/operation.rs b/core/src/widget/operation.rs index 17948599..ff0c920d 100644 --- a/core/src/widget/operation.rs +++ b/core/src/widget/operation.rs @@ -78,6 +78,9 @@ pub trait Operation: Send { /// Track the active window id being processed if relevant to the operation fn set_window_id(&mut self, _id: window::Id) {} + + /// Used to mark the beginning of operations for a widget and its children + fn pre_operation(&mut self, _id: Option<&Id>) {} } impl Operation for Box @@ -147,6 +150,10 @@ where fn set_window_id(&mut self, id: window::Id) { self.as_mut().set_window_id(id); } + + fn pre_operation(&mut self, id: Option<&Id>) { + self.as_mut().pre_operation(id); + } } /// The result of an [`Operation`]. @@ -251,6 +258,10 @@ where Outcome::None } + fn pre_operation(&mut self, id: Option<&Id>) { + self.operation.pre_operation(id); + } + fn set_window_id(&mut self, id: window::Id) { self.operation.set_window_id(id); } @@ -352,6 +363,10 @@ where ) { self.operation.custom(id, bounds, state); } + + fn pre_operation(&mut self, id: Option<&Id>) { + self.operation.pre_operation(id); + } } self.operation.traverse(&mut |operation| { @@ -425,6 +440,10 @@ where fn set_window_id(&mut self, id: window::Id) { self.operation.set_window_id(id); } + + fn pre_operation(&mut self, id: Option<&Id>) { + self.operation.pre_operation(id); + } } Map { @@ -534,6 +553,10 @@ where fn set_window_id(&mut self, id: window::Id) { self.operation.set_window_id(id); } + + fn pre_operation(&mut self, id: Option<&Id>) { + self.operation.pre_operation(id); + } } Chain { @@ -586,6 +609,10 @@ pub fn scoped( } } + fn pre_operation(&mut self, id: Option<&Id>) { + self.operation.pre_operation(id); + } + fn set_window_id(&mut self, id: window::Id) { self.operation.set_window_id(id); } diff --git a/selector/src/find.rs b/selector/src/find.rs index 06f85140..e4b01e66 100644 --- a/selector/src/find.rs +++ b/selector/src/find.rs @@ -285,4 +285,8 @@ where fn set_window_id(&mut self, id: window::Id) { self.strategy.set_window_id(id); } + + fn pre_operation(&mut self, id: Option<&Id>) { + self.strategy.feed(Candidate::PreOperation { id }); + } } diff --git a/selector/src/lib.rs b/selector/src/lib.rs index 99809a78..e07d9262 100644 --- a/selector/src/lib.rs +++ b/selector/src/lib.rs @@ -193,6 +193,8 @@ pub fn focus() -> impl Selector { )) } else if matches!(candidate, Candidate::Scrollable { .. }) { Some((false, Target::from(candidate), self.cur_window_id)) + } else if matches!(candidate, Candidate::PreOperation { .. }) { + Some((false, Target::from(candidate), self.cur_window_id)) } else { None } diff --git a/selector/src/target.rs b/selector/src/target.rs index d2d20651..5aa29920 100644 --- a/selector/src/target.rs +++ b/selector/src/target.rs @@ -42,6 +42,9 @@ pub enum Target { bounds: Rectangle, visible_bounds: Option, }, + PreOperation { + id: Option, + }, } impl Target { @@ -54,6 +57,7 @@ impl Target { | Target::TextInput { bounds, .. } | Target::Text { bounds, .. } | Target::Custom { bounds, .. } => *bounds, + Target::PreOperation { .. } => Rectangle::default(), } } @@ -66,6 +70,7 @@ impl Target { | Target::TextInput { visible_bounds, .. } | Target::Text { visible_bounds, .. } | Target::Custom { visible_bounds, .. } => *visible_bounds, + Target::PreOperation { .. } => None, } } } @@ -138,6 +143,9 @@ impl From> for Target { bounds, visible_bounds, }, + Candidate::PreOperation { id } => { + Self::PreOperation { id: id.cloned() } + } } } } @@ -195,6 +203,8 @@ pub enum Candidate<'a> { visible_bounds: Option, state: &'a dyn Any, }, + /// Used to mark the beginning of operations for a widget and its children + PreOperation { id: Option<&'a Id> }, } impl<'a> Candidate<'a> { @@ -206,7 +216,8 @@ impl<'a> Candidate<'a> { | Candidate::Scrollable { id, .. } | Candidate::TextInput { id, .. } | Candidate::Text { id, .. } - | Candidate::Custom { id, .. } => *id, + | Candidate::Custom { id, .. } + | Candidate::PreOperation { id } => *id, } } @@ -219,6 +230,7 @@ impl<'a> Candidate<'a> { | Candidate::TextInput { bounds, .. } | Candidate::Text { bounds, .. } | Candidate::Custom { bounds, .. } => *bounds, + Candidate::PreOperation { .. } => Rectangle::default(), } } @@ -231,6 +243,7 @@ impl<'a> Candidate<'a> { | Candidate::TextInput { visible_bounds, .. } | Candidate::Text { visible_bounds, .. } | Candidate::Custom { visible_bounds, .. } => *visible_bounds, + Candidate::PreOperation { .. } => None, } } } diff --git a/widget/src/scrollable.rs b/widget/src/scrollable.rs index 8065bb8a..43782ea7 100644 --- a/widget/src/scrollable.rs +++ b/widget/src/scrollable.rs @@ -676,6 +676,8 @@ where let translation = state.translation(self.direction, bounds, content_bounds); + operation.pre_operation(Some(&self.id)); + operation.traverse(&mut |operation| { self.content.as_widget_mut().operate( &mut tree.children[0],