From 133a1f09c044cbc2ec9bc0740567ea00ed4cf33f Mon Sep 17 00:00:00 2001 From: Philipp Mildenberger Date: Sat, 23 Nov 2024 01:54:22 +0100 Subject: [PATCH] Make find_widget_at_pos behavior more correct --- masonry/src/widget/widget.rs | 44 ++++++++++++++++++++++++++++---- masonry/src/widget/widget_ref.rs | 27 +------------------- 2 files changed, 40 insertions(+), 31 deletions(-) diff --git a/masonry/src/widget/widget.rs b/masonry/src/widget/widget.rs index 2e19c07c6..34735490f 100644 --- a/masonry/src/widget/widget.rs +++ b/masonry/src/widget/widget.rs @@ -281,11 +281,13 @@ pub trait Widget: AsAny + AsDynWidget { ctx: QueryCtx<'c>, pos: Point, ) -> Option> { - (WidgetRef { - widget: self.as_dyn(), - ctx, - }) - .find_widget_at_pos(pos) + find_widget_at_pos( + &WidgetRef { + widget: self.as_dyn(), + ctx, + }, + pos, + ) } /// Get the (verbose) type name of the widget for debugging purposes. @@ -327,6 +329,38 @@ pub trait Widget: AsAny + AsDynWidget { } } +pub(crate) fn find_widget_at_pos<'c>( + widget: &WidgetRef<'c, dyn Widget>, + pos: Point, +) -> Option> { + if widget.ctx.widget_state.bbox.contains(pos) { + let local_pos = widget.ctx().widget_state.window_transform.inverse() * pos; + + if Some(false) == widget.ctx.clip_path().map(|clip| clip.contains(local_pos)) { + return None; + } + + // Assumes `Self::children_ids` is in increasing "z-order", picking the last child in case + // of overlapping children. + for child_id in widget.children_ids().iter().rev() { + let child_ref = widget.ctx.get(*child_id); + if let Some(child) = child_ref.widget.find_widget_at_pos(child_ref.ctx, pos) { + return Some(child); + } + } + if !widget.ctx.is_stashed() + && widget.ctx.accepts_pointer_interaction() + && widget.ctx.size().to_rect().contains(local_pos) + { + Some(*widget) + } else { + None + } + } else { + None + } +} + /// Marker trait for Widgets whose parents can get a raw mutable reference to them. /// /// "Raw mut" means using a mutable reference (eg `&mut MyWidget`) to the data diff --git a/masonry/src/widget/widget_ref.rs b/masonry/src/widget/widget_ref.rs index 34aec9fe8..5ac745c4b 100644 --- a/masonry/src/widget/widget_ref.rs +++ b/masonry/src/widget/widget_ref.rs @@ -165,32 +165,7 @@ impl<'w> WidgetRef<'w, dyn Widget> { /// **pos** - the position in global coordinates (e.g. `(0,0)` is the top-left corner of the /// window). pub fn find_widget_at_pos(&self, pos: Point) -> Option> { - if self.ctx.widget_state.bbox.contains(pos) { - let local_pos = self.ctx().widget_state.window_transform.inverse() * pos; - - if Some(false) == self.ctx.clip_path().map(|clip| clip.contains(local_pos)) { - return None; - } - - // Assumes `Self::children_ids` is in increasing "z-order", picking the last child in case - // of overlapping children. - for child_id in self.children_ids().iter().rev() { - let child_ref = self.ctx.get(*child_id); - if let Some(child) = child_ref.widget.find_widget_at_pos(child_ref.ctx, pos) { - return Some(child); - } - } - if !self.ctx.is_stashed() - && self.ctx.accepts_pointer_interaction() - && self.ctx.size().to_rect().contains(local_pos) - { - Some(*self) - } else { - None - } - } else { - None - } + self.widget.find_widget_at_pos(self.ctx, pos) } }