feat(editor): Implement pixel-based scrolling for the Editor (#418)

Refactors the Editor's scrolling implementation to be pixel-based instead of line-based. This provides smoother and more granular scrolling, which works more consistently across different input devices (like trackpads).

- The `Action::Scroll` variant now takes `pixels: f32`.
- The `Editor` now processes scroll actions using pixel values directly.
- Examples have been updated to reflect the new scrolling behavior.
This commit is contained in:
shadow3 2025-09-08 02:39:38 +08:00 committed by GitHub
parent f7033bb043
commit 750e1a4dd1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 23 additions and 31 deletions

View file

@ -65,7 +65,6 @@ fn main() {
let mut mouse_x = 0.0;
let mut mouse_y = 0.0;
let mut mouse_left = ElementState::Released;
let mut unapplied_scroll_delta = 0.0;
event_loop
.run(|event, elwt| {
@ -294,9 +293,9 @@ fn main() {
// Scroll if cursor is near edge of window while dragging
if mouse_y <= 5.0 {
editor.action(Action::Scroll { lines: -1 });
editor.action(Action::Scroll { pixels: -20.0 });
} else if mouse_y - 5.0 >= window.inner_size().height as f64 {
editor.action(Action::Scroll { lines: 1 });
editor.action(Action::Scroll { pixels: 20.0 });
}
window.request_redraw();
@ -323,17 +322,14 @@ fn main() {
delta,
phase: _,
} => {
let line_delta = match delta {
MouseScrollDelta::LineDelta(_x, y) => y as i32,
MouseScrollDelta::PixelDelta(PhysicalPosition { x: _, y }) => {
unapplied_scroll_delta += y;
let line_delta = (unapplied_scroll_delta / 20.0).floor();
unapplied_scroll_delta -= line_delta * 20.0;
line_delta as i32
}
let pixel_delta = match delta {
MouseScrollDelta::LineDelta(_x, y) => y * 20.0,
MouseScrollDelta::PixelDelta(PhysicalPosition { x: _, y }) => y as f32,
};
if line_delta != 0 {
editor.action(Action::Scroll { lines: -line_delta });
if pixel_delta != 0.0 {
editor.action(Action::Scroll {
pixels: -pixel_delta,
});
}
window.request_redraw();
}

View file

@ -186,7 +186,6 @@ fn main() {
let mut mouse_x = 0.0;
let mut mouse_y = 0.0;
let mut mouse_left = ElementState::Released;
let mut unapplied_scroll_delta = 0.0;
let bg_color = tiny_skia::Color::from_rgba8(0x34, 0x34, 0x34, 0xFF);
let font_color = Color::rgb(0xFF, 0xFF, 0xFF);
@ -340,9 +339,9 @@ fn main() {
// Scroll if cursor is near edge of window while dragging
if mouse_y <= 5.0 {
editor.action(Action::Scroll { lines: -1 });
editor.action(Action::Scroll { pixels: -20.0 });
} else if mouse_y - 5.0 >= window.inner_size().height as f64 {
editor.action(Action::Scroll { lines: 1 });
editor.action(Action::Scroll { pixels: 20.0 });
}
window.request_redraw();
@ -369,17 +368,14 @@ fn main() {
delta,
phase: _,
} => {
let line_delta = match delta {
MouseScrollDelta::LineDelta(_x, y) => y as i32,
MouseScrollDelta::PixelDelta(PhysicalPosition { x: _, y }) => {
unapplied_scroll_delta += y;
let line_delta = (unapplied_scroll_delta / 20.0).floor();
unapplied_scroll_delta -= line_delta * 20.0;
line_delta as i32
}
let pixel_delta = match delta {
MouseScrollDelta::LineDelta(_x, y) => y * 20.0,
MouseScrollDelta::PixelDelta(PhysicalPosition { x: _, y }) => y as f32,
};
if line_delta != 0 {
editor.action(Action::Scroll { lines: -line_delta });
if pixel_delta != 0.0 {
editor.action(Action::Scroll {
pixels: -pixel_delta,
});
}
window.request_redraw();
}

View file

@ -858,11 +858,11 @@ impl<'buffer> Edit<'buffer> for Editor<'buffer> {
}
}
}
Action::Scroll { lines } => {
Action::Scroll { pixels } => {
self.with_buffer_mut(|buffer| {
let mut scroll = buffer.scroll();
//TODO: align to layout lines
scroll.vertical += lines as f32 * buffer.metrics().line_height;
scroll.vertical += pixels;
buffer.set_scroll(scroll);
});
}

View file

@ -20,7 +20,7 @@ pub use self::vi::*;
mod vi;
/// An action to perform on an [`Editor`]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Action {
/// Move the cursor with some motion
Motion(Motion),
@ -58,9 +58,9 @@ pub enum Action {
x: i32,
y: i32,
},
/// Scroll specified number of lines
/// Scroll specified number of pixels
Scroll {
lines: i32,
pixels: f32,
},
}