-
Notifications
You must be signed in to change notification settings - Fork 126
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
Implement update_scrolls pass #550
Conversation
And that's the last pass implemented! Once we've merged all of them, the next step will be to replace |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any way in the current examples to test this?
Actual code changes look reasonable, presuming that the panning maths is correct
run_targeted_update_pass(root, Some(target), |widget, ctx| { | ||
let event = LifeCycle::RequestPanToChild(rect); | ||
widget.lifecycle(ctx, &event); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How will smooth scroll would be handled?
The best logic I can see if to "get where the widget will be", and all the parents scroll to that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends what you mean by smooth scroll. Do you mean on a touchscreen?
I think the most straightforward solution is to have CSS-style animatable properties, and have scroll progress be one of them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't mean on a touchscreen, I mean scrolling to a position over a certain amount of time.
Right, yeah. This logic would have to change at that point, but it's also deliberately unaddressed at the moment.
let _span = info_span!("update_scroll").entered(); | ||
|
||
let scroll_request_targets = std::mem::take(&mut root.state.scroll_request_targets); | ||
for (target, rect) in scroll_request_targets { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the order matter here? Is it meaningful to document that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The order doesn't matter. scroll_request_target
was initially an option, and I turned it to a Vec just to cover hypothetical cases where someone would want to pan several scroll areas at once.
I guess several targets could interfere if they're in the same scroll region. I think this will be rare enough that we won't need to document it.
masonry/src/widget/portal.rs
Outdated
// Note - Rect is in child coordinates | ||
// TODO - Merge with pan_viewport_to | ||
// Right now these functions are just different enough to be a pain to merge. | ||
pub fn pan_viewport_to_raw( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is pub, so needs a doc comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not supposed to be pub. Fixed.
viewport.min_y()..viewport.max_y(), | ||
target.min_y()..target.max_y(), | ||
) | ||
.start; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we prefer the top-left
of the rectangle to go into view. That seems reasonable, but should probably be documented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added in a comment on the pass function. I'll do a more thorough documentation pass later.
The |
The scroll functionality in the suggested example is completely broken by this change
Thanks, checked it out and I can see that it is now impossible to scroll in that example. |
That doesn't sound right, it worked when I tested it. Maybe I forgot to push some changes? Will look into it. |
Ah, this is #424 . Indeed, applying diff --git a/masonry/src/widget/textbox.rs b/masonry/src/widget/textbox.rs
index 8a85f2d8e..7ab850e26 100644
--- a/masonry/src/widget/textbox.rs
+++ b/masonry/src/widget/textbox.rs
@@ -13,6 +13,7 @@ use vello::{
peniko::{BlendMode, Color},
Scene,
};
+use winit::event::Ime;
use crate::widget::{LineBreaking, WidgetMut};
use crate::{
@@ -208,7 +209,9 @@ impl Widget for Textbox {
// If focused on a link and enter pressed, follow it?
if result.is_handled() {
// TODO - Use request_scroll_to with cursor rect
- ctx.request_scroll_to_this();
+ if !matches!(event, TextEvent::Ime(Ime::Preedit(..))) {
+ ctx.request_scroll_to_this();
+ }
ctx.set_handled();
// TODO: only some handlers need this repaint
ctx.request_layout();
makes this work |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the workaround mentioned above, this now works well.
Some remaining concerns are documenting the preferred part of the rectangle which is shown, and fixing the scrollbars properly.
masonry/src/widget/portal.rs
Outdated
let portal_size = ctx.size(); | ||
let content_size = ctx.get_raw_ref(&mut self.child).ctx().layout_rect().size(); | ||
|
||
// FIXME - Update scrollbars |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to do this in this PR, or explain why it's hard. The behaviour without that is quite bad.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
masonry/src/widget/textbox.rs
Outdated
@@ -207,6 +207,8 @@ impl Widget for Textbox { | |||
let result = self.editor.text_event(ctx, event); | |||
// If focused on a link and enter pressed, follow it? | |||
if result.is_handled() { | |||
// TODO - Use request_scroll_to with cursor rect |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I imagine this will happen in #515 ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably.
Note: This PRs comes with a lot of new TODO items. Addressing most of these items is difficult without major refactors. This pass is still mostly functional.
54b607b
to
7f359c8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One small remaining proposed tweak.
masonry/src/widget/textbox.rs
Outdated
if result.is_handled() { | ||
// Some platforms will send a lot of spurious Preedit events. | ||
// We only want to request a scroll on user input. | ||
if !matches!(event, TextEvent::Ime(Ime::Preedit(..))) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooh, apparently we can do
if !matches!(event, TextEvent::Ime(Ime::Preedit(..))) { | |
if !matches!(event, TextEvent::Ime(Ime::Preedit(preedit, ..)) if preedit.is_empty()) { |
which in my testing has better behaviour (but is not the easiest to reason about in its current form)
This is part of the Pass Specification RFC: linebender/rfcs#7
Note: This PRs comes with a lot of new TODO items. Addressing most of these items is difficult without major refactors, because Portal code deals with accessing values across multiple widgets, which is still hard to do elegantly.