From 205434a19942e4008e5de0250a93fedd7923a9b0 Mon Sep 17 00:00:00 2001 From: Thomas Churchman Date: Thu, 29 Aug 2024 09:58:36 +0200 Subject: [PATCH 1/3] masonry: fix updating Portal on scrollbar drag Fixed by requesting compose instead of layout. Regression probably caused in 59ee615651266421ffe65dadee6d16663f056c9d or ff7635e4c281ff381433728bd070323347638f29. --- masonry/src/widget/portal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/masonry/src/widget/portal.rs b/masonry/src/widget/portal.rs index 19d9f8ee3..3ef26f5e5 100644 --- a/masonry/src/widget/portal.rs +++ b/masonry/src/widget/portal.rs @@ -298,7 +298,7 @@ impl Widget for Portal { } if scrollbar_moved { - ctx.request_layout(); + ctx.request_compose(); } } From 793f37dd2754f87eb58cc7290240e5d3a0946f00 Mon Sep 17 00:00:00 2001 From: Thomas Churchman Date: Fri, 30 Aug 2024 15:42:24 +0200 Subject: [PATCH 2/3] masonry: fix anchor calculation of scrollbar pointer dragging `PointerEvent` holds global (window) coordinates, so the scrollbar has to calculate the position relative to its window origin. --- masonry/src/widget/scroll_bar.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/masonry/src/widget/scroll_bar.rs b/masonry/src/widget/scroll_bar.rs index c73790667..9763315b9 100644 --- a/masonry/src/widget/scroll_bar.rs +++ b/masonry/src/widget/scroll_bar.rs @@ -133,7 +133,8 @@ impl Widget for ScrollBar { let cursor_min_length = theme::SCROLLBAR_MIN_SIZE; let cursor_rect = self.get_cursor_rect(ctx.size(), cursor_min_length); - let mouse_pos = Point::new(state.position.x, state.position.y); + let mouse_pos = + Point::new(state.position.x, state.position.y) - ctx.window_origin().to_vec2(); if cursor_rect.contains(mouse_pos) { let (z0, z1) = self.axis.major_span(cursor_rect); let mouse_major = self.axis.major_pos(mouse_pos); @@ -147,7 +148,8 @@ impl Widget for ScrollBar { ctx.request_paint(); } PointerEvent::PointerMove(state) => { - let mouse_pos = Point::new(state.position.x, state.position.y); + let mouse_pos = + Point::new(state.position.x, state.position.y) - ctx.window_origin().to_vec2(); if let Some(grab_anchor) = self.grab_anchor { let cursor_min_length = theme::SCROLLBAR_MIN_SIZE; self.cursor_progress = self.progress_from_mouse_pos( From 1cb61eca096ce0c2619b75392144835baddebf52 Mon Sep 17 00:00:00 2001 From: Thomas Churchman Date: Fri, 30 Aug 2024 14:37:54 +0200 Subject: [PATCH 3/3] masonry: when querying widgets by pos, in case of overlap take last This takes the last child as returned by Widget::children_ids, i.e., the last in "z-order". --- masonry/src/widget/widget_ref.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/masonry/src/widget/widget_ref.rs b/masonry/src/widget/widget_ref.rs index 2f85ea5ba..56d4d1e71 100644 --- a/masonry/src/widget/widget_ref.rs +++ b/masonry/src/widget/widget_ref.rs @@ -170,6 +170,9 @@ impl<'w> WidgetRef<'w, dyn Widget> { /// Recursively find innermost widget at given position. /// + /// If multiple overlapping children of a widget contain the given position in their layout + /// boxes, the last child as determined by [`Widget::children_ids`] is chosen. + /// /// **pos** - the position in local coordinates (zero being the top-left of the /// inner widget). pub fn find_widget_at_pos(&self, pos: Point) -> Option> { @@ -190,7 +193,7 @@ impl<'w> WidgetRef<'w, dyn Widget> { } } // TODO - Use Widget::get_child_at_pos method - if let Some(child) = innermost_widget.children().into_iter().find(|child| { + if let Some(child) = innermost_widget.children().into_iter().rev().find(|child| { !child.widget.skip_pointer() && child.state().window_layout_rect().contains(pos) }) { innermost_widget = child;