Fix delay when changing scrolling direction (#13867)

Peter Tripp and Antonio Scandurra created

Fixes: #13720.

Co-authored-by: Antonio Scandurra <antonio@zed.dev>

Change summary

crates/gpui/src/geometry.rs    | 12 ++++++++++++
crates/gpui/src/interactive.rs | 35 +++++++++++++++++++++++++++++++----
2 files changed, 43 insertions(+), 4 deletions(-)

Detailed changes

crates/gpui/src/geometry.rs 🔗

@@ -2320,6 +2320,18 @@ impl Pixels {
         Self(self.0.abs())
     }
 
+    /// Returns the sign of the `Pixels` value.
+    ///
+    /// # Returns
+    ///
+    /// Returns:
+    /// * `1.0` if the value is positive
+    /// * `-1.0` if the value is negative
+    /// * `0.0` if the value is zero
+    pub fn signum(&self) -> f32 {
+        self.0.signum()
+    }
+
     /// Returns the f64 value of `Pixels`.
     ///
     /// # Returns

crates/gpui/src/interactive.rs 🔗

@@ -291,14 +291,41 @@ impl ScrollDelta {
     }
 
     /// Combines two scroll deltas into one.
+    /// If the signs of the deltas are the same (both positive or both negative),
+    /// the deltas are added together. If the signs are opposite, the second delta
+    /// (other) is used, effectively overriding the first delta.
     pub fn coalesce(self, other: ScrollDelta) -> ScrollDelta {
         match (self, other) {
-            (ScrollDelta::Pixels(px_a), ScrollDelta::Pixels(px_b)) => {
-                ScrollDelta::Pixels(px_a + px_b)
+            (ScrollDelta::Pixels(a), ScrollDelta::Pixels(b)) => {
+                let x = if a.x.signum() * b.x.signum() >= 0. {
+                    a.x + b.x
+                } else {
+                    b.x
+                };
+
+                let y = if a.y.signum() * b.y.signum() >= 0. {
+                    a.y + b.y
+                } else {
+                    b.y
+                };
+
+                ScrollDelta::Pixels(point(x, y))
             }
 
-            (ScrollDelta::Lines(lines_a), ScrollDelta::Lines(lines_b)) => {
-                ScrollDelta::Lines(lines_a + lines_b)
+            (ScrollDelta::Lines(a), ScrollDelta::Lines(b)) => {
+                let x = if a.x.signum() * b.x.signum() >= 0. {
+                    a.x + b.x
+                } else {
+                    b.x
+                };
+
+                let y = if a.y.signum() * b.y.signum() >= 0. {
+                    a.y + b.y
+                } else {
+                    b.y
+                };
+
+                ScrollDelta::Lines(point(x, y))
             }
 
             _ => other,