Prevent horizontal transcript selection from triggering autoscroll (#47137)

## Why

Dragging horizontally along the top or bottom transcript row could trigger autoscroll, moving the text under the pointer while selecting it.

## What changed

Require vertical pointer movement from the initial press row before selection autoscroll can begin. Remember that movement so a vertical drag can return to its starting edge and still autoscroll, and preserve the original pointer row across wheel scrolling.

## Testing

Extend regression tests and snapshots for horizontal selection at both edges, stable selected text across repeated ticks, wheel scrolling before the first drag, and autoscroll after a vertical drag returns to its starting edge.

GitOrigin-RevId: e13f3a80adbead1eecbeb281301667c8e12e1541
This commit is contained in:
Ian MacLeod
2026-09-22 00:38:29 +00:00
committed by copyberry
parent e4dba902ab
commit 720a21ae66
5 changed files with 97 additions and 10 deletions
@@ -14,6 +14,8 @@ pub(super) struct Selection {
pub(super) end: Anchor,
pub(super) dragging: bool,
pub(super) moved: bool,
moved_vertically: bool,
pointer_origin_row: u16,
pub(super) resume_on_empty: bool,
pub(super) pointer: Option<ScreenPosition>,
pub(super) pressed_link: Option<String>,
@@ -56,6 +58,8 @@ impl TranscriptView {
preferred_column: None,
dragging: true,
moved: false,
moved_vertically: false,
pointer_origin_row: row,
resume_on_empty: was_following,
pointer: Some(ScreenPosition::new(column, row)),
pressed_link: None,
@@ -123,6 +127,7 @@ impl TranscriptView {
};
selection.snapshot.pinned.entry(end.key).or_insert(layout);
selection.moved = true;
selection.moved_vertically |= selection.pointer_origin_row != row;
selection.pointer = Some(ScreenPosition::new(column, row));
selection.preferred_column = None;
self.pin_selection_range(&cells, &mut selection);
@@ -272,7 +277,8 @@ impl TranscriptView {
let Some(selection) = self
.selection
.as_ref()
.filter(|selection| selection.dragging && selection.moved)
// Horizontal selection on an edge row must not move the text under the pointer.
.filter(|selection| selection.dragging && selection.moved_vertically)
else {
return false;
};