From cc97f4131bcc252fd243327e86c3d308c66a9a00 Mon Sep 17 00:00:00 2001 From: smit <0xtimsb@gmail.com> Date: Wed, 12 Feb 2025 22:52:22 +0530 Subject: [PATCH] editor: Fix horizontal scroll when soft wrap is active (#24735) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #22252 This PR fixes the bug introduced in https://github.com/zed-industries/zed/pull/19495 by: Problem: The vertical scrollbar is currently rendered absolutely on top of the editor. When calculating soft wrap, the editor uses its width to decide how many words fit on a line. This causes words to overlap with the vertical scrollbar because it doesn't account for the scrollbar's width. To fix the overlap, extra overflow is added to the scrollbar, which solves the issue but creates unnecessary scrolling in soft wrap mode. Fix: The editor width is adjusted to account for the scrollbar's width. This makes sure the correct number of words fit on a line and prevents overlapping with the scrollbar in soft wrap mode. Since the scrollbar width is now accounted for in the editor's width, there's no need to add extra overflow, unless there’s no soft wrap. In that case, when text overflows the editor’s width, we still need to add extra overscroll to match the scrollbar width. Without this, long lines will overlap with the scrollbar. Release Notes: - Fixed issue where horizontal scrollbar would scroll few characters width when soft wrap is active. --- crates/editor/src/element.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 61542ac006..18b81d707a 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -6773,7 +6773,8 @@ impl Element for EditorElement { .unwrap_or_default(); let text_width = bounds.size.width - gutter_dimensions.width; - let editor_width = text_width - gutter_dimensions.margin - em_width; + let editor_width = + text_width - gutter_dimensions.margin - em_width - style.scrollbar_width; snapshot = self.editor.update(cx, |editor, cx| { editor.last_bounds = Some(bounds); @@ -7108,6 +7109,7 @@ impl Element for EditorElement { longest_line_width, longest_line_blame_width, &style, + editor_width, cx, ); @@ -7716,6 +7718,7 @@ struct ScrollbarRangeData { } impl ScrollbarRangeData { + #[allow(clippy::too_many_arguments)] pub fn new( scrollbar_bounds: Bounds, letter_size: Size, @@ -7723,15 +7726,13 @@ impl ScrollbarRangeData { longest_line_width: Pixels, longest_line_blame_width: Pixels, style: &EditorStyle, - + editor_width: Pixels, cx: &mut App, ) -> ScrollbarRangeData { // TODO: Simplify this function down, it requires a lot of parameters let max_row = snapshot.max_point().row(); let text_bounds_size = size(longest_line_width, max_row.0 as f32 * letter_size.height); - let scrollbar_width = style.scrollbar_width; - let settings = EditorSettings::get_global(cx); let scroll_beyond_last_line: Pixels = match settings.scroll_beyond_last_line { ScrollBeyondLastLine::OnePage => px(scrollbar_bounds.size.height / letter_size.height), @@ -7739,8 +7740,14 @@ impl ScrollbarRangeData { ScrollBeyondLastLine::VerticalScrollMargin => px(1.0 + settings.vertical_scroll_margin), }; + let right_margin = if longest_line_width + longest_line_blame_width >= editor_width { + letter_size.width + style.scrollbar_width + } else { + px(0.0) + }; + let overscroll = size( - scrollbar_width + (letter_size.width / 2.0) + longest_line_blame_width, + right_margin + longest_line_blame_width, letter_size.height * scroll_beyond_last_line, );