EditableText improved scrolling#24268
Conversation
`scroll_editable_text` scrolling calculations changed to support the inset.
…oint` when dragging. So each time the mouse moves during a drag, the current selection is cleared and a new selection is created. As long as the local drag start position is constant this is seamless, but if you scroll the text input view, the start of the drag is now at a different position relative to the text layout, and the start of the selection range changes. Solution: Don't queue the `MoveToPoint` edit.
EditableText scroll with insetEditableText improved scrolling
eswartz
left a comment
There was a problem hiding this comment.
(btw, the sample name in the instructions is misspelled -- it's one letter from "multiline_text_input", which I actually tested before seeing the bug refers to "multiple_text_inputs"!)
It looks nice and feels pretty good. Pasting a long blob leaves the cursor where expected, at the end of the blob.
In the "multiline_text_input" case, which I mostly tested, it seems like this might introduce a regression. When dragging a selection up or down in the window, at some instances the selection outline becomes one pixel tall, either at the top or the bottom depending on scroll direction. I'd expect at least a full text line to be visible.
The keeping of at least a single selected row when scrolling seems to work as expected on main (a7a456b), though it also sometimes shows a single-pixel selection row above that. (Forgive me for testing this PR without seeing any other work on this widget, so I don't know if that's already tracked!)
video from scrolling:
https://github.com/user-attachments/assets/a2ae3a95-adbb-4916-b398-0ffc0815b500
| let max_scroll_y = (info.size.y - view_size.y).max(0.); | ||
|
|
||
| let y = scroll_axis_with_inset( | ||
| editable_text.scroll_inset.y.clamp(0., 0.49) * view_size.y, |
There was a problem hiding this comment.
The use of 0.49 here and on line 568 seems a little magical. Why not 0.5 exactly? Would line 627 then catch the original intended case via e.g.
let new_v_min = if v_size - 2. * inset <= t_size { ?
There was a problem hiding this comment.
The use of
0.49here and on line 568 seems a little magical. Why not 0.5 exactly? Would line 627 then catch the original intended case via e.g.let new_v_min = if v_size - 2. * inset <= t_size {?
0.5 is probably fine, clamping it below 0.49 felt safer though. It's just a defensive measure to preemptively head off the inevitable rounding bugs that pop up everywhere.
No this is really helpful, thank you, I hadn't noticed it losing a line draggging downwards. The single-pixel selection region bleed is down to trusting the selection geometry from Parley too much. Sometimes it's out by a pixel due to its metric quantization, sometimes leading to extra pixel tall selection rects or pixel wide gaps between selection rects on adjacent lines. |
… depending on the scaling. After collecting the rects from Parley, if there is a gap, close it by extending the bottom edge downwards.
Objective
Fix problems:
Solution
EditableTextNeedsScroll, newtypesbool. If set totruethe editor view scrolls next update.bevy_ui::widget::text_input_layout::scroll_axis_with_inset.scroll_insetfield onEditableTextcontrols the size of the view inset (is normalized).TextInputScrollSpeed, sets scrolling speed relative to the text's line height.drag_scroll_text_inputsupdates drag scrolling for current input focused text input.on_pointer_dragclamps the pointer position to within the input's bounds. Drag selecting outside of the input's bounds no longer selects text out of view.Fixes #24293
Testing