Skip to content

Commit

Permalink
Accumulate mouse scrolls for smoother scrolling
Browse files Browse the repository at this point in the history
  • Loading branch information
ArthurCose authored and jackpot51 committed Nov 9, 2024
1 parent 222d3fb commit 1743730
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 27 deletions.
79 changes: 54 additions & 25 deletions src/mouse_reporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const SCROLL_SPEED: u32 = 3;
pub struct MouseReporter {
last_movment_x: Option<u32>,
last_movment_y: Option<u32>,
accumulated_scroll_x: f32,
accumulated_scroll_y: f32,
button: Option<Button>,
}

Expand Down Expand Up @@ -167,44 +169,71 @@ impl MouseReporter {
}

#[allow(clippy::too_many_arguments)]
pub fn report_sgr_mouse_wheel_scroll(
terminal: &Terminal,
pub fn sgr_mouse_wheel_scroll(
&mut self,
term_cell_width: f32,
term_cell_height: f32,
delta: ScrollDelta,
modifiers: &Modifiers,
x: u32,
y: u32,
) {
let (delta_x, delta_y) = match delta {
ScrollDelta::Lines { x, y } => (x, y),
ScrollDelta::Pixels { x, y } => (x / term_cell_width, y / term_cell_height),
};
let (mut button_no, amount) = if delta_y > 0.0 {
(64, delta_y.abs()) //Wheel UP
} else if delta_y < 0.0 {
(65, delta_y.abs()) //Wheel Down
} else if delta_x < 0.0 {
(66, delta_x.abs()) //Wheel Left
} else if delta_x > 0.0 {
(67, delta_x.abs()) //Wheel Right
} else {
return;
) -> impl Iterator<Item = Vec<u8>> {
let (lines_x, lines_y) = match delta {
ScrollDelta::Lines { x, y } => (x as i32, y as i32),
ScrollDelta::Pixels { x, y } => {
//Accumulate change
self.accumulated_scroll_x += x / term_cell_width;
self.accumulated_scroll_y += y / term_cell_height;

//Resolve lines crossed
let lines_x = self.accumulated_scroll_x as i32;
let lines_y = self.accumulated_scroll_y as i32;

//Subtract accounted lines from accumulators
self.accumulated_scroll_x -= lines_x as f32;
self.accumulated_scroll_y -= lines_y as f32;

(lines_x, lines_y)
}
};

//Resolve modifier flags
let mut modifier_flags = 0;

if modifiers.shift() {
button_no += 4;
modifier_flags += 4;
}
if modifiers.alt() {
button_no += 8;
modifier_flags += 8;
}
if modifiers.control() {
button_no += 16;
}
let term_code = format!("\x1b[<{};{};{}M", button_no, x + 1, y + 1);
for _ in 0..amount as u32 {
terminal.input_no_scroll(term_code.as_bytes().to_vec());
}
modifier_flags += 16;
};

//Resolve base inputs
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
Expand Down
10 changes: 8 additions & 2 deletions src/terminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,7 @@ impl Terminal {
) {
let term_lock = self.term.lock();
let mode = term_lock.mode();

#[allow(clippy::collapsible_else_if)]
if mode.contains(TermMode::SGR_MOUSE) {
if let Some(code) = self.mouse_reporter.sgr_mouse_code(event, modifiers, x, y) {
Expand All @@ -896,6 +897,7 @@ impl Terminal {
}
}
}

pub fn scroll_mouse(
&mut self,
delta: ScrollDelta,
Expand All @@ -905,16 +907,20 @@ impl Terminal {
) {
let term_lock = self.term.lock();
let mode = term_lock.mode();

if mode.contains(TermMode::SGR_MOUSE) {
MouseReporter::report_sgr_mouse_wheel_scroll(
self,
let codes = self.mouse_reporter.sgr_mouse_wheel_scroll(
self.size().cell_width,
self.size().cell_height,
delta,
modifiers,
x,
y,
);

for code in codes {
self.notifier.notify(code);
}
} else {
MouseReporter::report_mouse_wheel_as_arrows(
self,
Expand Down

0 comments on commit 1743730

Please sign in to comment.