Accumulate mouse scrolls for smoother scrolling

This commit is contained in:
Arthur Cosentino 2024-11-09 07:26:04 -05:00 • committed by Jeremy Soller
parent 222d3fb0a5
commit 1743730fd9
2 changed files with 62 additions and 27 deletions

View file

@ -11,6 +11,8 @@ const SCROLL_SPEED: u32 = 3;
pub struct MouseReporter { pub struct MouseReporter {
last_movment_x: Option<u32>, last_movment_x: Option<u32>,
last_movment_y: Option<u32>, last_movment_y: Option<u32>,
accumulated_scroll_x: f32,
accumulated_scroll_y: f32,
button: Option<Button>, button: Option<Button>,
} }
@ -167,44 +169,71 @@ impl MouseReporter {
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn report_sgr_mouse_wheel_scroll( pub fn sgr_mouse_wheel_scroll(
terminal: &Terminal, &mut self,
term_cell_width: f32, term_cell_width: f32,
term_cell_height: f32, term_cell_height: f32,
delta: ScrollDelta, delta: ScrollDelta,
modifiers: &Modifiers, modifiers: &Modifiers,
x: u32, x: u32,
y: u32, y: u32,
) { ) -> impl Iterator<Item = Vec<u8>> {
let (delta_x, delta_y) = match delta { let (lines_x, lines_y) = match delta {
ScrollDelta::Lines { x, y } => (x, y), ScrollDelta::Lines { x, y } => (x as i32, y as i32),
ScrollDelta::Pixels { x, y } => (x / term_cell_width, y / term_cell_height), ScrollDelta::Pixels { x, y } => {
}; //Accumulate change
let (mut button_no, amount) = if delta_y > 0.0 { self.accumulated_scroll_x += x / term_cell_width;
(64, delta_y.abs()) //Wheel UP self.accumulated_scroll_y += y / term_cell_height;
} else if delta_y < 0.0 {
(65, delta_y.abs()) //Wheel Down //Resolve lines crossed
} else if delta_x < 0.0 { let lines_x = self.accumulated_scroll_x as i32;
(66, delta_x.abs()) //Wheel Left let lines_y = self.accumulated_scroll_y as i32;
} else if delta_x > 0.0 {
(67, delta_x.abs()) //Wheel Right //Subtract accounted lines from accumulators
} else { self.accumulated_scroll_x -= lines_x as f32;
return; self.accumulated_scroll_y -= lines_y as f32;
(lines_x, lines_y)
}
}; };
//Resolve modifier flags
let mut modifier_flags = 0;
if modifiers.shift() { if modifiers.shift() {
button_no += 4; modifier_flags += 4;
} }
if modifiers.alt() { if modifiers.alt() {
button_no += 8; modifier_flags += 8;
} }
if modifiers.control() { if modifiers.control() {
button_no += 16; modifier_flags += 16;
} };
let term_code = format!("\x1b[<{};{};{}M", button_no, x + 1, y + 1);
for _ in 0..amount as u32 { //Resolve base inputs
terminal.input_no_scroll(term_code.as_bytes().to_vec()); let button_no_y = match lines_y.cmp(&0) {
} std::cmp::Ordering::Less => 65, //Wheel Down
std::cmp::Ordering::Greater => 64, //Wheel Up
std::cmp::Ordering::Equal => 0, //Unused
};
let button_no_x = match lines_x.cmp(&0) {
std::cmp::Ordering::Less => 66, //Wheel Left
std::cmp::Ordering::Greater => 67, //Wheel Right
std::cmp::Ordering::Equal => 0, //Unused
};
//Generate term codes
let x_iter = std::iter::repeat_n(button_no_x, lines_x.unsigned_abs() as _);
let y_iter = std::iter::repeat_n(button_no_y, lines_y.unsigned_abs() as _);
x_iter
.chain(y_iter)
.map(move |button_no| button_no + modifier_flags)
.map(move |button_no| {
let term_code = format!("\x1b[<{};{};{}M", button_no, x + 1, y + 1);
term_code.as_bytes().to_vec()
})
} }
//Emulate mouse wheel scroll with up/down arrows. Using mouse spec uses //Emulate mouse wheel scroll with up/down arrows. Using mouse spec uses

View file

@ -879,6 +879,7 @@ impl Terminal {
) { ) {
let term_lock = self.term.lock(); let term_lock = self.term.lock();
let mode = term_lock.mode(); let mode = term_lock.mode();
#[allow(clippy::collapsible_else_if)] #[allow(clippy::collapsible_else_if)]
if mode.contains(TermMode::SGR_MOUSE) { if mode.contains(TermMode::SGR_MOUSE) {
if let Some(code) = self.mouse_reporter.sgr_mouse_code(event, modifiers, x, y) { if let Some(code) = self.mouse_reporter.sgr_mouse_code(event, modifiers, x, y) {
@ -896,6 +897,7 @@ impl Terminal {
} }
} }
} }
pub fn scroll_mouse( pub fn scroll_mouse(
&mut self, &mut self,
delta: ScrollDelta, delta: ScrollDelta,
@ -905,9 +907,9 @@ impl Terminal {
) { ) {
let term_lock = self.term.lock(); let term_lock = self.term.lock();
let mode = term_lock.mode(); let mode = term_lock.mode();
if mode.contains(TermMode::SGR_MOUSE) { if mode.contains(TermMode::SGR_MOUSE) {
MouseReporter::report_sgr_mouse_wheel_scroll( let codes = self.mouse_reporter.sgr_mouse_wheel_scroll(
self,
self.size().cell_width, self.size().cell_width,
self.size().cell_height, self.size().cell_height,
delta, delta,
@ -915,6 +917,10 @@ impl Terminal {
x, x,
y, y,
); );
for code in codes {
self.notifier.notify(code);
}
} else { } else {
MouseReporter::report_mouse_wheel_as_arrows( MouseReporter::report_mouse_wheel_as_arrows(
self, self,