Skip to content

Commit

Permalink
input: Ensure resizing the window doesn't force the cursor back into …
Browse files Browse the repository at this point in the history
…view (#370)

Fix #331

It is ensured that the scroll offset remains consistent during parent
container resizing, preventing the cursor from being forced back into
view unless the user interacts with the input, providing a more
consistent user experience in scenarios where automatic scrolling during
resizing is undesirable.

This behavior aligns with common text editors and input fields where
resizing the window doesn't force the cursor back into view.

![2024-10-21 20 27
00](https://github.com/user-attachments/assets/599ef72d-3ec8-4fe5-a26c-10263044db6f)
  • Loading branch information
xda2023 authored Oct 21, 2024
1 parent 38fc226 commit 14ca368
Showing 1 changed file with 32 additions and 20 deletions.
52 changes: 32 additions & 20 deletions crates/ui/src/input/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ pub struct TextInput {
marked_range: Option<Range<usize>>,
last_layout: Option<ShapedLine>,
last_bounds: Option<Bounds<Pixels>>,
last_cursor_offset: Option<usize>,
last_selected_range: Option<Range<usize>>,
scroll_offset: Point<Pixels>,
is_selecting: bool,
disabled: bool,
Expand Down Expand Up @@ -160,6 +162,8 @@ impl TextInput {
marked_range: None,
last_layout: None,
last_bounds: None,
last_cursor_offset: None,
last_selected_range: None,
scroll_offset: point(px(0.), px(0.)),
is_selecting: false,
disabled: false,
Expand Down Expand Up @@ -975,26 +979,30 @@ impl Element for TextElement {
let cursor_pos = line.x_for_index(cursor);
let cursor_start = line.x_for_index(selected_range.start);
let cursor_end = line.x_for_index(selected_range.end);

scroll_offset.x = if scroll_offset.x + cursor_pos > (bounds.size.width - right_margin) {
// cursor is out of right
bounds.size.width - right_margin - cursor_pos
} else if scroll_offset.x + cursor_pos < px(0.) {
// cursor is out of left
scroll_offset.x - cursor_pos
} else {
scroll_offset.x
};

if input.selection_reversed {
if scroll_offset.x + cursor_start < px(0.) {
// selection start is out of left
scroll_offset.x = -cursor_start;
}
} else {
if scroll_offset.x + cursor_end <= px(0.) {
// selection end is out of left
scroll_offset.x = -cursor_end;
let cursor_moved = input.last_cursor_offset != Some(cursor);
let selection_changed = input.last_selected_range != Some(selected_range.clone());

if cursor_moved || selection_changed {
scroll_offset.x = if scroll_offset.x + cursor_pos > (bounds.size.width - right_margin) {
// cursor is out of right
bounds.size.width - right_margin - cursor_pos
} else if scroll_offset.x + cursor_pos < px(0.) {
// cursor is out of left
scroll_offset.x - cursor_pos
} else {
scroll_offset.x
};

if input.selection_reversed {
if scroll_offset.x + cursor_start < px(0.) {
// selection start is out of left
scroll_offset.x = -cursor_start;
}
} else {
if scroll_offset.x + cursor_end <= px(0.) {
// selection end is out of left
scroll_offset.x = -cursor_end;
}
}
}

Expand Down Expand Up @@ -1053,6 +1061,8 @@ impl Element for TextElement {
let focus_handle = self.input.read(cx).focus_handle.clone();
let focused = focus_handle.is_focused(cx);
let bounds = prepaint.bounds;
let selected_range = self.input.read(cx).selected_range.clone();
let cursor = self.input.read(cx).cursor_offset();

cx.handle_input(
&focus_handle,
Expand All @@ -1073,6 +1083,8 @@ impl Element for TextElement {
input.scroll_offset = prepaint.scroll_offset;
input.last_layout = Some(line);
input.last_bounds = Some(bounds);
input.last_cursor_offset = Some(cursor);
input.last_selected_range = Some(selected_range);
});

self.paint_mouse_listeners(cx);
Expand Down

0 comments on commit 14ca368

Please sign in to comment.