Add a setting to control the vertical and horizontal scroll sensitivity (#10244)

Carter Olsen created

Some people (like myself) use touchpads for development and I find Zed's
default scroll sensitivity to be slower than I like. This change adds a
scroll sensitivity multiplier that allows users to customize the speed
of their scrolling.

Release Notes:

- Added a setting under "scroll_sensitivity" that allows user to control
the scroll sensitivity. This value acts as a multiplier for the
horizontal and vertical scroll speed.

Change summary

assets/settings/default.json         |  3 +++
crates/editor/src/editor_settings.rs |  8 +++++++-
crates/editor/src/element.rs         | 11 +++++++++--
3 files changed, 19 insertions(+), 3 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -171,6 +171,9 @@
   },
   // The number of lines to keep above/below the cursor when scrolling.
   "vertical_scroll_margin": 3,
+  // Scroll sensitivity multiplier. This multiplier is applied 
+  // to both the horizontal and vertical delta values while scrolling.
+  "scroll_sensitivity": 1.0,
   "relative_line_numbers": false,
   // When to populate a new search's query based on the text under the cursor.
   // This setting can take the following three values:

crates/editor/src/editor_settings.rs 🔗

@@ -15,6 +15,7 @@ pub struct EditorSettings {
     pub scrollbar: Scrollbar,
     pub gutter: Gutter,
     pub vertical_scroll_margin: f32,
+    pub scroll_sensitivity: f32,
     pub relative_line_numbers: bool,
     pub seed_search_query_from_cursor: SeedQuerySetting,
     pub multi_cursor_modifier: MultiCursorModifier,
@@ -138,6 +139,11 @@ pub struct EditorSettingsContent {
     ///
     /// Default: 3.
     pub vertical_scroll_margin: Option<f32>,
+    /// Scroll sensitivity multiplier. This multiplier is applied
+    /// to both the horizontal and vertical delta values while scrolling.
+    ///
+    /// Default: 1.0
+    pub scroll_sensitivity: Option<f32>,
     /// Whether the line numbers on editors gutter are relative or not.
     ///
     /// Default: false
@@ -178,7 +184,7 @@ pub struct ToolbarContent {
 }
 
 /// Scrollbar related settings
-#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
 pub struct ScrollbarContent {
     /// When to show the scrollbar in the editor.
     ///

crates/editor/src/element.rs 🔗

@@ -2817,6 +2817,10 @@ impl EditorElement {
             let hitbox = layout.hitbox.clone();
             let mut delta = ScrollDelta::default();
 
+            // Set a minimum scroll_sensitivity of 0.01 to make sure the user doesn't
+            // accidentally turn off their scrolling.
+            let scroll_sensitivity = EditorSettings::get_global(cx).scroll_sensitivity.max(0.01);
+
             move |event: &ScrollWheelEvent, phase, cx| {
                 if phase == DispatchPhase::Bubble && hitbox.is_hovered(cx) {
                     delta = delta.coalesce(event.delta);
@@ -2841,8 +2845,11 @@ impl EditorElement {
                         };
 
                         let scroll_position = position_map.snapshot.scroll_position();
-                        let x = (scroll_position.x * max_glyph_width - delta.x) / max_glyph_width;
-                        let y = (scroll_position.y * line_height - delta.y) / line_height;
+                        let x = (scroll_position.x * max_glyph_width
+                            - (delta.x * scroll_sensitivity))
+                            / max_glyph_width;
+                        let y = (scroll_position.y * line_height - (delta.y * scroll_sensitivity))
+                            / line_height;
                         let scroll_position =
                             point(x, y).clamp(&point(0., 0.), &position_map.scroll_max);
                         editor.scroll(scroll_position, axis, cx);