@@ -1461,7 +1461,7 @@ impl EditorElement {
window: &mut Window,
cx: &mut App,
) -> Option<EditorScrollbars> {
- if !snapshot.mode.is_full() || !self.editor.read(cx).show_scrollbars {
+ if !self.editor.read(cx).show_scrollbars || self.style.scrollbar_width.is_zero() {
return None;
}
@@ -1604,6 +1604,7 @@ impl EditorElement {
minimap_line_height,
scroll_position,
minimap_scroll_top,
+ show_thumb,
);
minimap_editor.update(cx, |editor, cx| {
@@ -1633,7 +1634,6 @@ impl EditorElement {
Some(MinimapLayout {
minimap,
thumb_layout: layout,
- show_thumb,
thumb_border_style: minimap_settings.thumb_border,
minimap_line_height,
minimap_scroll_top,
@@ -5236,8 +5236,6 @@ impl EditorElement {
for (scrollbar_layout, axis) in scrollbars_layout.iter_scrollbars() {
let hitbox = &scrollbar_layout.hitbox;
- let thumb_bounds = scrollbar_layout.thumb_bounds();
-
if scrollbars_layout.visible {
let scrollbar_edges = match axis {
ScrollbarAxis::Horizontal => Edges {
@@ -5279,26 +5277,31 @@ impl EditorElement {
}
}
- let scrollbar_thumb_color = match scrollbar_layout.thumb_state {
- ScrollbarThumbState::Dragging => {
- cx.theme().colors().scrollbar_thumb_active_background
- }
- ScrollbarThumbState::Hovered => {
- cx.theme().colors().scrollbar_thumb_hover_background
- }
- ScrollbarThumbState::Idle => cx.theme().colors().scrollbar_thumb_background,
- };
- window.paint_quad(quad(
- thumb_bounds,
- Corners::default(),
- scrollbar_thumb_color,
- scrollbar_edges,
- cx.theme().colors().scrollbar_thumb_border,
- BorderStyle::Solid,
- ));
+ if let Some(thumb_bounds) = scrollbar_layout.thumb_bounds {
+ let scrollbar_thumb_color = match scrollbar_layout.thumb_state {
+ ScrollbarThumbState::Dragging => {
+ cx.theme().colors().scrollbar_thumb_active_background
+ }
+ ScrollbarThumbState::Hovered => {
+ cx.theme().colors().scrollbar_thumb_hover_background
+ }
+ ScrollbarThumbState::Idle => {
+ cx.theme().colors().scrollbar_thumb_background
+ }
+ };
+ window.paint_quad(quad(
+ thumb_bounds,
+ Corners::default(),
+ scrollbar_thumb_color,
+ scrollbar_edges,
+ cx.theme().colors().scrollbar_thumb_border,
+ BorderStyle::Solid,
+ ));
+
+ window.set_cursor_style(CursorStyle::Arrow, Some(&hitbox));
+ }
})
}
- window.set_cursor_style(CursorStyle::Arrow, Some(&hitbox));
}
window.on_mouse_event({
@@ -5343,7 +5346,10 @@ impl EditorElement {
cx.stop_propagation();
} else if let Some((layout, axis)) = scrollbars_layout.get_hovered_axis(window)
{
- if layout.thumb_bounds().contains(&event.position) {
+ if layout
+ .thumb_bounds
+ .is_some_and(|bounds| bounds.contains(&event.position))
+ {
editor
.scroll_manager
.set_hovered_scroll_thumb_axis(axis, cx);
@@ -5398,10 +5404,13 @@ impl EditorElement {
hitbox,
visible_range,
text_unit_size,
+ thumb_bounds,
..
} = scrollbar_layout;
- let thumb_bounds = scrollbar_layout.thumb_bounds();
+ let Some(thumb_bounds) = thumb_bounds else {
+ return;
+ };
editor.update(cx, |editor, cx| {
editor
@@ -5731,12 +5740,11 @@ impl EditorElement {
fn paint_minimap(&self, layout: &mut EditorLayout, window: &mut Window, cx: &mut App) {
if let Some(mut layout) = layout.minimap.take() {
let minimap_hitbox = layout.thumb_layout.hitbox.clone();
- let thumb_bounds = layout.thumb_layout.thumb_bounds();
window.paint_layer(layout.thumb_layout.hitbox.bounds, |window| {
window.with_element_namespace("minimap", |window| {
layout.minimap.paint(window, cx);
- if layout.show_thumb {
+ if let Some(thumb_bounds) = layout.thumb_layout.thumb_bounds {
let minimap_thumb_border = match layout.thumb_border_style {
MinimapThumbBorder::Full => Edges::all(ScrollbarLayout::BORDER_WIDTH),
MinimapThumbBorder::LeftOnly => Edges {
@@ -5853,6 +5861,10 @@ impl EditorElement {
let event_position = event.position;
+ let Some(thumb_bounds) = layout.thumb_layout.thumb_bounds else {
+ return;
+ };
+
editor.update(cx, |editor, cx| {
if !thumb_bounds.contains(&event_position) {
let click_position =
@@ -8426,6 +8438,7 @@ impl EditorScrollbars {
glyph_grid_cell.along(axis),
content_offset.along(axis),
scroll_position.along(axis),
+ show_scrollbars,
thumb_state,
axis,
)
@@ -8460,10 +8473,8 @@ struct ScrollbarLayout {
hitbox: Hitbox,
visible_range: Range<f32>,
text_unit_size: Pixels,
- content_offset: Pixels,
- thumb_size: Pixels,
+ thumb_bounds: Option<Bounds<Pixels>>,
thumb_state: ScrollbarThumbState,
- axis: ScrollbarAxis,
}
impl ScrollbarLayout {
@@ -8479,6 +8490,7 @@ impl ScrollbarLayout {
glyph_space: Pixels,
content_offset: Pixels,
scroll_position: f32,
+ show_thumb: bool,
thumb_state: ScrollbarThumbState,
axis: ScrollbarAxis,
) -> Self {
@@ -8495,6 +8507,7 @@ impl ScrollbarLayout {
glyph_space,
content_offset,
scroll_position,
+ show_thumb,
thumb_state,
axis,
)
@@ -8507,6 +8520,7 @@ impl ScrollbarLayout {
minimap_line_height: Pixels,
scroll_position: f32,
minimap_scroll_top: f32,
+ show_thumb: bool,
) -> Self {
// The scrollbar thumb size is calculated as
// (visible_content/total_content) × scrollbar_track_length.
@@ -8535,6 +8549,7 @@ impl ScrollbarLayout {
minimap_line_height,
track_top_offset,
scroll_position,
+ show_thumb,
ScrollbarThumbState::Idle,
ScrollbarAxis::Vertical,
)
@@ -8548,6 +8563,7 @@ impl ScrollbarLayout {
glyph_space: Pixels,
content_offset: Pixels,
scroll_position: f32,
+ show_thumb: bool,
thumb_state: ScrollbarThumbState,
axis: ScrollbarAxis,
) -> Self {
@@ -8559,36 +8575,54 @@ impl ScrollbarLayout {
let thumb_size = (track_length * thumb_percentage)
.max(ScrollbarLayout::MIN_THUMB_SIZE)
.min(track_length);
- let text_unit_size =
- (track_length - thumb_size) / (total_text_units - text_units_per_page).max(0.);
+
+ let text_unit_divisor = (total_text_units - text_units_per_page).max(0.);
+
+ let content_larger_than_viewport = text_unit_divisor > 0.;
+
+ let text_unit_size = if content_larger_than_viewport {
+ (track_length - thumb_size) / text_unit_divisor
+ } else {
+ glyph_space
+ };
+
+ let thumb_bounds = (show_thumb && content_larger_than_viewport).then(|| {
+ Self::thumb_bounds(
+ &scrollbar_track_hitbox,
+ content_offset,
+ visible_range.start,
+ text_unit_size,
+ thumb_size,
+ axis,
+ )
+ });
ScrollbarLayout {
hitbox: scrollbar_track_hitbox,
visible_range,
text_unit_size,
- content_offset,
- thumb_size,
+ thumb_bounds,
thumb_state,
- axis,
}
}
- fn thumb_bounds(&self) -> Bounds<Pixels> {
- let scrollbar_track = &self.hitbox.bounds;
+ fn thumb_bounds(
+ scrollbar_track: &Hitbox,
+ content_offset: Pixels,
+ visible_range_start: f32,
+ text_unit_size: Pixels,
+ thumb_size: Pixels,
+ axis: ScrollbarAxis,
+ ) -> Bounds<Pixels> {
+ let thumb_origin = scrollbar_track.origin.apply_along(axis, |origin| {
+ origin + content_offset + visible_range_start * text_unit_size
+ });
Bounds::new(
- scrollbar_track
- .origin
- .apply_along(self.axis, |origin| self.thumb_origin(origin)),
- scrollbar_track
- .size
- .apply_along(self.axis, |_| self.thumb_size),
+ thumb_origin,
+ scrollbar_track.size.apply_along(axis, |_| thumb_size),
)
}
- fn thumb_origin(&self, origin: Pixels) -> Pixels {
- origin + self.content_offset + self.visible_range.start * self.text_unit_size
- }
-
fn marker_quads_for_ranges(
&self,
row_ranges: impl IntoIterator<Item = ColoredRange<DisplayRow>>,
@@ -8677,7 +8711,6 @@ struct MinimapLayout {
pub minimap_scroll_top: f32,
pub minimap_line_height: Pixels,
pub thumb_border_style: MinimapThumbBorder,
- pub show_thumb: bool,
pub max_scroll_top: f32,
}