From 454334ec9c26b1b9099fdfa70170631b97422c3b Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Tue, 12 May 2026 13:33:32 +0100 Subject: [PATCH 1/2] `on_pointer_drag` queues `MoveToPoint` as well as `ExtendSelectionToPoint` 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. --- crates/bevy_ui_widgets/src/text_input.rs | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/crates/bevy_ui_widgets/src/text_input.rs b/crates/bevy_ui_widgets/src/text_input.rs index fd7a2e6df181c..b65f7bc511bf1 100644 --- a/crates/bevy_ui_widgets/src/text_input.rs +++ b/crates/bevy_ui_widgets/src/text_input.rs @@ -15,7 +15,7 @@ use bevy_input_focus::{ FocusCause, FocusGained, FocusLost, FocusedInput, InputFocus, InputFocusSystems, }; use bevy_math::Vec2; -use bevy_picking::events::{Click, Drag, Pointer, Press, Release}; +use bevy_picking::events::{Click, Drag, DragStart, Pointer, Press, Release}; use bevy_picking::pointer::PointerButton; use bevy_text::{EditableText, PreeditCursor, TextEdit}; use bevy_ui::widget::{scroll_editable_text, update_editable_text_layout, TextScroll}; @@ -285,23 +285,18 @@ fn on_pointer_drag( return; } - let Some((drag_start_local_pos, current_local_pos)) = transform.try_inverse().map(|inverse| { - let transform_pos = |pointer_pos| { - inverse.transform_point2(pointer_pos * target.scale_factor() / ui_scale.0) - - node.content_box().min - + text_scroll.0 - }; - let current_pos = drag.pointer_location.position; - let drag_start_pos = current_pos - drag.distance; - (transform_pos(drag_start_pos), transform_pos(current_pos)) + let Some(current_local_pos) = transform.try_inverse().map(|inverse| { + inverse + .transform_point2(drag.pointer_location.position * target.scale_factor() / ui_scale.0) + - node.content_box().min + + text_scroll.0 }) else { return; }; - editable_text.pending_edits.extend([ - TextEdit::MoveToPoint(drag_start_local_pos), - TextEdit::ExtendSelectionToPoint(current_local_pos), - ]); + editable_text + .pending_edits + .push(TextEdit::ExtendSelectionToPoint(current_local_pos)); drag.propagate(false); } From 2154aad65ed791699a76c63cff4efd6515796396 Mon Sep 17 00:00:00 2001 From: ickshonpe Date: Tue, 12 May 2026 14:16:11 +0100 Subject: [PATCH 2/2] Removed unused import. --- crates/bevy_ui_widgets/src/text_input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_ui_widgets/src/text_input.rs b/crates/bevy_ui_widgets/src/text_input.rs index b65f7bc511bf1..0174191b29074 100644 --- a/crates/bevy_ui_widgets/src/text_input.rs +++ b/crates/bevy_ui_widgets/src/text_input.rs @@ -15,7 +15,7 @@ use bevy_input_focus::{ FocusCause, FocusGained, FocusLost, FocusedInput, InputFocus, InputFocusSystems, }; use bevy_math::Vec2; -use bevy_picking::events::{Click, Drag, DragStart, Pointer, Press, Release}; +use bevy_picking::events::{Click, Drag, Pointer, Press, Release}; use bevy_picking::pointer::PointerButton; use bevy_text::{EditableText, PreeditCursor, TextEdit}; use bevy_ui::widget::{scroll_editable_text, update_editable_text_layout, TextScroll};