Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

masonry: fix updating Portal on scrollbar drag #563

Merged
merged 3 commits into from
Sep 2, 2024

Conversation

tomcur
Copy link
Contributor

@tomcur tomcur commented Aug 29, 2024

Fixes scrolling Portal on scrollbar drag by recomposing instead of relayouting.

Regression probably caused in 59ee615 (#488) or ff7635e (#522).

Fixed by requesting compose instead of layout. Regression probably
caused in 59ee615 or
ff7635e.
@tomcur tomcur changed the title masonry: recompose instead of relayout Portal on scrollbar drag masonry: fix updating Portal on scrollbar drag Aug 29, 2024
@jaredoconnell
Copy link
Contributor

This seems right, but I can't test it due to a bug that appears to be present in both main and this PR:

Node #166 of TreeUpdate includes duplicate child #165;

@PoignardAzur
Copy link
Contributor

Huh. That's odd, I thought layout automatically triggered a compose. Maybe it hasn't merged yet.

@PoignardAzur
Copy link
Contributor

I tested it (with the panic fix). Dragging the scrollbar still doesn't seem to work.

@tomcur
Copy link
Contributor Author

tomcur commented Aug 30, 2024

I tested it (with the panic fix). Dragging the scrollbar still doesn't seem to work.

The scrollbars currently do not receive the pointer events due to a separate bug; the events are instead passed to the inner widget of the Portal, perhaps I should've provided that context in this PR. This patch by @DJMcNab fixes that separate issue, PR #565 also fixes it:

diff --git a/masonry/src/widget/widget_ref.rs b/masonry/src/widget/widget_ref.rs
index 2f85ea5ba..6bd00a32c 100644
--- a/masonry/src/widget/widget_ref.rs
+++ b/masonry/src/widget/widget_ref.rs
@@ -190,7 +190,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;

(Zulip thread here: https://xi.zulipchat.com/#narrow/stream/317477-masonry/topic/Portal.20Scrollbars.20click-and-drag)

@PoignardAzur
Copy link
Contributor

PR #565 is unlikely to be merged today.

If you could include that change in the current PR, we could test it and merge it now.

@tomcur
Copy link
Contributor Author

tomcur commented Aug 30, 2024

If you could include that change in the current PR, we could test it and merge it now.

Done. The scroll bar should be responsive now, but note there is still an issue related to the drag anchor, so the scroll bar jumps around a bit. My patch on Zulip fixes that (https://xi.zulipchat.com/#narrow/stream/317477-masonry/topic/Portal.20Scrollbars.20click-and-drag), but that patch should only be used if PointerState::position (LogicalPosition) is intended to not be relative to the widget origin.

diff --git a/masonry/src/widget/scroll_bar.rs b/masonry/src/widget/scroll_bar.rs
index 3434a01..5a4e3fe 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(

@PoignardAzur
Copy link
Contributor

but that patch should only be used if PointerState::position (LogicalPosition) is intended to not be relative to the widget origin.

It's not, it's supposed to be global. (Events are passed unmodified to all widgets right now.)

@tomcur
Copy link
Contributor Author

tomcur commented Aug 30, 2024

It's not, it's supposed to be global. (Events are passed unmodified to all widgets right now.)

Shall I add the anchor fix to this PR as well?

@PoignardAzur
Copy link
Contributor

Sure.

`PointerEvent` holds global (window) coordinates, so the scrollbar has
to calculate the position relative to its window origin.
This takes the last child as returned by Widget::children_ids, i.e., the
last in "z-order".
@tomcur
Copy link
Contributor Author

tomcur commented Aug 30, 2024

@PoignardAzur This is ready for testing.

Copy link
Contributor

@PoignardAzur PoignardAzur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

To-do list example now works on my machine.

@DJMcNab
Copy link
Member

DJMcNab commented Sep 2, 2024

@tomcur if you're happy for this to land, I'll merge.

For context, we normally use an author-merges policy, but you aren't an org member yet (I expect you to be added in the 2024-09-05 office hours). See https://xi.zulipchat.com/#narrow/stream/419691-linebender/topic/Organisation.20members

@DJMcNab
Copy link
Member

DJMcNab commented Sep 2, 2024

I can confirm this now works as expected on Android as well. Thank you!

@tomcur
Copy link
Contributor Author

tomcur commented Sep 2, 2024

I'm happy for this to be merged, thank you. Nice to hear you're proposing to add me as org member!

@DJMcNab DJMcNab added this pull request to the merge queue Sep 2, 2024
Merged via the queue into linebender:main with commit e337cf7 Sep 2, 2024
17 checks passed
@tomcur tomcur deleted the recompose-portal branch September 3, 2024 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants