GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
fix: trackpad scrolling on sliders converts pixels at 15/notch, not 120
Pixel (trackpad) scroll deltas were divided by 120 — the Windows wheel
convention — before the 0.02-per-notch value step, so sweeping a slider's
full range took ~6000px of finger travel and small swipes moved nothing
visible. The DE's own convention is 15 axis units per notch (ccectl
pointer-scroll), which is what trackpad deltas actually resemble: 8x
more sensitive, one 0.01 readout tick per ~26px of swipe.
New MouseScrollDelta::notches_y() owns the conversion; Slider,
RangeSlider, and the ParametersBg float3 rows all use it.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/widget/container/parameters_bg.rs | 5 +----
src/widget/input/slider.rs | 14 ++++----------
src/widget/mod.rs | 14 ++++++++++++++
3 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/src/widget/container/parameters_bg.rs b/src/widget/container/parameters_bg.rs
index 2b018d7..1beea9d 100644
--- a/src/widget/container/parameters_bg.rs
+++ b/src/widget/container/parameters_bg.rs
@@ -2241,10 +2241,7 @@ impl Input for ParametersBg {
for j in 0..3 {
let r_inner = rects_inner[j];
if py >= r_inner.1 && py <= r_inner.1 + r_inner.3 {
- let scroll_amount = match delta {
- MouseScrollDelta::LineDelta(_x, y) => *y,
- MouseScrollDelta::PixelDelta(pos) => (pos.y as f32) / 120.0,
- };
+ let scroll_amount = delta.notches_y();
let step = 0.02;
let new_val = (f.values[j] - scroll_amount * step).clamp(0.0, 1.0);
if (new_val - f.values[j]).abs() > 0.0001 {
diff --git a/src/widget/input/slider.rs b/src/widget/input/slider.rs
index a1c8bfb..64e2346 100644
--- a/src/widget/input/slider.rs
+++ b/src/widget/input/slider.rs
@@ -11,7 +11,7 @@ use crate::scene::layout::{Rect, Size};
use crate::scene::paint::PaintCtx;
use crate::widget::{
Adapted, ElementState, Event, EventCtx, Input, Key, Layout, MouseButton,
- MouseScrollDelta, NamedKey, Paint, TextEditorState,
+ NamedKey, Paint, TextEditorState,
};
/// The track/readout/thumb geometry shared by the paint and input paths, derived from the
@@ -653,10 +653,7 @@ impl Input for Slider {
if band || ui.scroll_gesture_new {
ui.scroll_initiate_widget_id = Some(ectx.id);
}
- let scroll_amount = match delta {
- MouseScrollDelta::LineDelta(_x, y) => *y,
- MouseScrollDelta::PixelDelta(pos) => (pos.y as f32) / 120.0,
- };
+ let scroll_amount = delta.notches_y();
let new_val = (self.value - scroll_amount * 0.02).clamp(0.0, 1.0);
self.set_value_marking(new_val);
return true;
@@ -910,10 +907,7 @@ impl Input for RangeSlider {
let center_high = x + self.value_high * range + thumb_size / 2.0;
let dist_low = (px - center_low).abs();
let dist_high = (px - center_high).abs();
- let scroll_amount = match delta {
- MouseScrollDelta::LineDelta(_x, y) => *y,
- MouseScrollDelta::PixelDelta(pos) => (pos.y as f32) / 120.0,
- };
+ let scroll_amount = delta.notches_y();
let step = 0.02;
let adjust_low = if dist_low < dist_high {
true
@@ -1012,7 +1006,7 @@ impl Input for RangeSlider {
#[cfg(test)]
mod tests {
use super::*;
- use crate::widget::{WidgetHost, UiContext};
+ use crate::widget::{MouseScrollDelta, WidgetHost, UiContext};
/// The legacy rangeslider interaction test, driven through the WidgetHost drag forwards
/// (hosts call these directly): thumb selection by proximity, constrained updates.
diff --git a/src/widget/mod.rs b/src/widget/mod.rs
index 68c7153..ba01b73 100644
--- a/src/widget/mod.rs
+++ b/src/widget/mod.rs
@@ -26,6 +26,20 @@ pub enum MouseScrollDelta {
PixelDelta(Position),
}
+impl MouseScrollDelta {
+ /// Vertical scroll in wheel-notch equivalents. Pixel (trackpad) deltas
+ /// convert at the DE's 15-axis-units-per-notch convention (see `ccectl
+ /// pointer-scroll`: "15 = one notch") — NOT the 120-unit wheel standard,
+ /// which makes value widgets feel dead under trackpad swipes (a full
+ /// slider sweep would take ~6000px of finger travel).
+ pub fn notches_y(&self) -> f32 {
+ match self {
+ MouseScrollDelta::LineDelta(_x, y) => *y,
+ MouseScrollDelta::PixelDelta(pos) => (pos.y as f32) / 15.0,
+ }
+ }
+}
+
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Key {
Named(NamedKey),