fix: accumulate fractional wheel-line scroll deltas
This commit is contained in:
parent
1d3d8837df
commit
1e49511fcf
1 changed files with 63 additions and 4 deletions
|
|
@ -1553,16 +1553,22 @@ where
|
||||||
} else {
|
} else {
|
||||||
match delta {
|
match delta {
|
||||||
ScrollDelta::Lines { x: _, y } => {
|
ScrollDelta::Lines { x: _, y } => {
|
||||||
//TODO: this adjustment is just a guess!
|
// High-resolution wheels deliver a notch as many
|
||||||
|
// fractional deltas; accumulate them so nothing
|
||||||
|
// below one whole line is lost (see
|
||||||
|
// accumulate_wheel_lines).
|
||||||
state.scroll_pixels = 0.0;
|
state.scroll_pixels = 0.0;
|
||||||
let lines = (-y * 6.0) as i32;
|
let (lines, remainder) =
|
||||||
|
accumulate_wheel_lines(*y, state.scroll_lines);
|
||||||
|
state.scroll_lines = remainder;
|
||||||
if lines != 0 {
|
if lines != 0 {
|
||||||
terminal.scroll(TerminalScroll::Delta(-lines));
|
terminal.scroll(TerminalScroll::Delta(lines));
|
||||||
}
|
}
|
||||||
shell.capture_event();
|
shell.capture_event();
|
||||||
}
|
}
|
||||||
ScrollDelta::Pixels { x: _, y } => {
|
ScrollDelta::Pixels { x: _, y } => {
|
||||||
//TODO: this adjustment is just a guess!
|
//TODO: this adjustment is just a guess!
|
||||||
|
state.scroll_lines = 0.0;
|
||||||
state.scroll_pixels -= y * 6.0;
|
state.scroll_pixels -= y * 6.0;
|
||||||
let mut lines = 0;
|
let mut lines = 0;
|
||||||
let metrics = terminal.with_buffer(|buffer| buffer.metrics());
|
let metrics = terminal.with_buffer(|buffer| buffer.metrics());
|
||||||
|
|
@ -1728,6 +1734,26 @@ fn update_active_regex_match(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Whole lines scrolled per unit of wheel `Lines` delta.
|
||||||
|
//TODO: this adjustment is just a guess!
|
||||||
|
const SCROLL_LINE_MULTIPLIER: f32 = 6.0;
|
||||||
|
|
||||||
|
/// Convert a wheel `Lines` delta into whole lines to scroll, accumulating the
|
||||||
|
/// fractional remainder across events.
|
||||||
|
///
|
||||||
|
/// High-resolution wheels deliver a single physical notch as many fractional
|
||||||
|
/// deltas (e.g. `y = 0.125`). Scaling by [`SCROLL_LINE_MULTIPLIER`] and
|
||||||
|
/// truncating per event discards anything below one whole line, so most of
|
||||||
|
/// those events would scroll nothing. Carrying the remainder forward means the
|
||||||
|
/// fractions add up and a full notch scrolls the intended amount.
|
||||||
|
///
|
||||||
|
/// Returns `(whole_lines, new_accumulator)`.
|
||||||
|
fn accumulate_wheel_lines(y: f32, accumulator: f32) -> (i32, f32) {
|
||||||
|
let total = accumulator + y * SCROLL_LINE_MULTIPLIER;
|
||||||
|
let lines = total.trunc() as i32;
|
||||||
|
(lines, total - lines as f32)
|
||||||
|
}
|
||||||
|
|
||||||
fn shade(color: cosmic_text::Color, is_focused: bool) -> cosmic_text::Color {
|
fn shade(color: cosmic_text::Color, is_focused: bool) -> cosmic_text::Color {
|
||||||
if is_focused {
|
if is_focused {
|
||||||
color
|
color
|
||||||
|
|
@ -1929,6 +1955,7 @@ pub struct State {
|
||||||
dragging: Option<Dragging>,
|
dragging: Option<Dragging>,
|
||||||
is_focused: bool,
|
is_focused: bool,
|
||||||
scroll_pixels: f32,
|
scroll_pixels: f32,
|
||||||
|
scroll_lines: f32,
|
||||||
scrollbar_rect: Cell<Rectangle<f32>>,
|
scrollbar_rect: Cell<Rectangle<f32>>,
|
||||||
autoscroll: DragAutoscroll,
|
autoscroll: DragAutoscroll,
|
||||||
preedit: Option<input_method::Preedit>,
|
preedit: Option<input_method::Preedit>,
|
||||||
|
|
@ -1943,6 +1970,7 @@ impl State {
|
||||||
dragging: None,
|
dragging: None,
|
||||||
is_focused: false,
|
is_focused: false,
|
||||||
scroll_pixels: 0.0,
|
scroll_pixels: 0.0,
|
||||||
|
scroll_lines: 0.0,
|
||||||
scrollbar_rect: Cell::new(Rectangle::default()),
|
scrollbar_rect: Cell::new(Rectangle::default()),
|
||||||
autoscroll: DragAutoscroll::new(AUTOSCROLL_INTERVAL),
|
autoscroll: DragAutoscroll::new(AUTOSCROLL_INTERVAL),
|
||||||
preedit: None,
|
preedit: None,
|
||||||
|
|
@ -2022,7 +2050,38 @@ fn ss3(code: &str, modifiers: u8) -> Option<Vec<u8>> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{EdgeScrollDirection, edge_scroll_adjustment};
|
use super::{EdgeScrollDirection, accumulate_wheel_lines, edge_scroll_adjustment};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wheel_lines_single_fractional_event_keeps_remainder() {
|
||||||
|
// A high-res wheel notch arrives as fractional deltas. A lone 0.125
|
||||||
|
// event is less than one whole line, but must not be discarded.
|
||||||
|
let (lines, remainder) = accumulate_wheel_lines(0.125, 0.0);
|
||||||
|
assert_eq!(lines, 0);
|
||||||
|
assert!((remainder - 0.75).abs() < f32::EPSILON);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wheel_lines_accumulate_into_whole_lines() {
|
||||||
|
// Eight 0.125 deltas make up one physical notch and must scroll the
|
||||||
|
// full SCROLL_LINE_MULTIPLIER (6) lines, not be lost to truncation.
|
||||||
|
let mut accumulator = 0.0;
|
||||||
|
let mut total = 0;
|
||||||
|
for _ in 0..8 {
|
||||||
|
let (lines, remainder) = accumulate_wheel_lines(0.125, accumulator);
|
||||||
|
accumulator = remainder;
|
||||||
|
total += lines;
|
||||||
|
}
|
||||||
|
assert_eq!(total, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn wheel_lines_preserve_direction() {
|
||||||
|
let (down, _) = accumulate_wheel_lines(0.25, 0.0);
|
||||||
|
let (up, _) = accumulate_wheel_lines(-0.25, 0.0);
|
||||||
|
assert_eq!(down, 1);
|
||||||
|
assert_eq!(up, -1);
|
||||||
|
}
|
||||||
|
|
||||||
const BUFFER_HEIGHT: f32 = 200.0;
|
const BUFFER_HEIGHT: f32 = 200.0;
|
||||||
const CELL_HEIGHT: f32 = 20.0;
|
const CELL_HEIGHT: f32 = 20.0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue