From 814408507779d602e5629c8e9b848f07551ed93a Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Mon, 24 Nov 2025 17:14:39 +0800 Subject: [PATCH] input: Fix scroll to offset to support soft wrap mode. (#1671) Close #1655 https://github.com/user-attachments/assets/ea7032d0-d15a-4127-9b0b-b035e2c835fe --- crates/ui/src/input/state.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/crates/ui/src/input/state.rs b/crates/ui/src/input/state.rs index 38487eae..80a3dacf 100644 --- a/crates/ui/src/input/state.rs +++ b/crates/ui/src/input/state.rs @@ -4,11 +4,11 @@ //! https://github.com/zed-industries/zed/blob/main/crates/gpui/examples/input.rs use anyhow::Result; use gpui::{ - actions, div, point, prelude::FluentBuilder as _, px, Action, App, AppContext, Bounds, - ClipboardItem, Context, Entity, EntityInputHandler, EventEmitter, FocusHandle, Focusable, - InteractiveElement as _, IntoElement, KeyBinding, KeyDownEvent, MouseButton, MouseDownEvent, - MouseMoveEvent, MouseUpEvent, ParentElement as _, Pixels, Point, Render, ScrollHandle, - ScrollWheelEvent, SharedString, Styled as _, Subscription, Task, UTF16Selection, Window, + Action, App, AppContext, Bounds, ClipboardItem, Context, Entity, EntityInputHandler, + EventEmitter, FocusHandle, Focusable, InteractiveElement as _, IntoElement, KeyBinding, + KeyDownEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, ParentElement as _, + Pixels, Point, Render, ScrollHandle, ScrollWheelEvent, SharedString, Styled as _, Subscription, + Task, UTF16Selection, Window, actions, div, point, prelude::FluentBuilder as _, px, }; use ropey::{Rope, RopeSlice}; use serde::Deserialize; @@ -19,20 +19,20 @@ use sum_tree::Bias; use unicode_segmentation::*; use super::{ - blink_cursor::BlinkCursor, change::Change, element::TextElement, mask_pattern::MaskPattern, - mode::InputMode, number_input, text_wrapper::TextWrapper, TabSize, + TabSize, blink_cursor::BlinkCursor, change::Change, element::TextElement, + mask_pattern::MaskPattern, mode::InputMode, number_input, text_wrapper::TextWrapper, }; use crate::actions::{SelectDown, SelectLeft, SelectRight, SelectUp}; use crate::input::{ + HoverDefinition, Lsp, Position, element::RIGHT_MARGIN, popovers::{ContextMenu, DiagnosticPopover, HoverPopover, MouseContextMenu}, search::{self, SearchPanel}, text_wrapper::LineLayout, - HoverDefinition, Lsp, Position, }; use crate::input::{RopeExt as _, Selection}; +use crate::{Root, history::History, scroll::ScrollbarState}; use crate::{highlighter::DiagnosticSet, input::text_wrapper::LineItem}; -use crate::{history::History, scroll::ScrollbarState, Root}; #[derive(Action, Clone, PartialEq, Eq, Deserialize)] #[action(namespace = input, no_json)] @@ -1343,6 +1343,7 @@ impl InputState { let line_height = last_layout.line_height; let point = self.text.offset_to_point(offset); + let row = point.row; let mut row_offset_y = px(0.); @@ -1358,10 +1359,11 @@ impl InputState { .lines .get(row.saturating_sub(last_layout.visible_range.start)) { - // Check to scroll horizontally + // Check to scroll horizontally and soft wrap lines if let Some(pos) = line.position_for_index(point.column, line_height) { let bounds_width = bounds.size.width - last_layout.line_number_width; let col_offset_x = pos.x; + row_offset_y += pos.y; if col_offset_x - RIGHT_MARGIN < -scroll_offset.x { // If the position is out of the visible area, scroll to make it visible scroll_offset.x = -col_offset_x + RIGHT_MARGIN;