fix: do not drop scrolling events from smooth scrolling mice
This commit is contained in:
parent
3d8ca65b75
commit
124931faff
3 changed files with 46 additions and 63 deletions
|
|
@ -3,10 +3,6 @@ use cosmic::{
|
||||||
iced::{Event, keyboard::Modifiers, mouse::Button},
|
iced::{Event, keyboard::Modifiers, mouse::Button},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::terminal::Terminal;
|
|
||||||
|
|
||||||
const SCROLL_SPEED: u32 = 3;
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct MouseReporter {
|
pub struct MouseReporter {
|
||||||
last_movment_x: Option<u32>,
|
last_movment_x: Option<u32>,
|
||||||
|
|
@ -17,6 +13,30 @@ pub struct MouseReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MouseReporter {
|
impl MouseReporter {
|
||||||
|
pub fn accumulate_scroll(
|
||||||
|
&mut self,
|
||||||
|
delta: ScrollDelta,
|
||||||
|
cell_width: f32,
|
||||||
|
cell_height: f32,
|
||||||
|
) -> (i32, i32) {
|
||||||
|
match delta {
|
||||||
|
ScrollDelta::Lines { x, y } => {
|
||||||
|
self.accumulated_scroll_x += x;
|
||||||
|
self.accumulated_scroll_y += y;
|
||||||
|
}
|
||||||
|
ScrollDelta::Pixels { x, y } => {
|
||||||
|
self.accumulated_scroll_x += x / cell_width;
|
||||||
|
self.accumulated_scroll_y += y / cell_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let lines_x = self.accumulated_scroll_x as i32;
|
||||||
|
let lines_y = self.accumulated_scroll_y as i32;
|
||||||
|
self.accumulated_scroll_x -= lines_x as f32;
|
||||||
|
self.accumulated_scroll_y -= lines_y as f32;
|
||||||
|
(lines_x, lines_y)
|
||||||
|
}
|
||||||
|
|
||||||
fn button_number(button: Button) -> Option<u8> {
|
fn button_number(button: Button) -> Option<u8> {
|
||||||
match button {
|
match button {
|
||||||
Button::Left => Some(0),
|
Button::Left => Some(0),
|
||||||
|
|
@ -178,24 +198,7 @@ impl MouseReporter {
|
||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
) -> impl Iterator<Item = Vec<u8>> {
|
) -> impl Iterator<Item = Vec<u8>> {
|
||||||
let (lines_x, lines_y) = match delta {
|
let (lines_x, lines_y) = self.accumulate_scroll(delta, term_cell_width, term_cell_height);
|
||||||
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
|
//Resolve modifier flags
|
||||||
let mut modifier_flags = 0;
|
let mut modifier_flags = 0;
|
||||||
|
|
@ -235,26 +238,4 @@ impl MouseReporter {
|
||||||
term_code.as_bytes().to_vec()
|
term_code.as_bytes().to_vec()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//Emulate mouse wheel scroll with up/down arrows. Using mouse spec uses
|
|
||||||
//scroll-back and scroll-forw actions, which moves whole windows like page up/page down.
|
|
||||||
pub fn report_mouse_wheel_as_arrows(
|
|
||||||
terminal: &Terminal,
|
|
||||||
term_cell_width: f32,
|
|
||||||
term_cell_height: f32,
|
|
||||||
delta: ScrollDelta,
|
|
||||||
) {
|
|
||||||
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),
|
|
||||||
};
|
|
||||||
//Send delta_y * SCROLL_SPEED number of Up/Down arrows
|
|
||||||
for _ in 0..(delta_y.abs() as u32 * SCROLL_SPEED) {
|
|
||||||
if delta_y > 0.0 {
|
|
||||||
terminal.input_no_scroll(b"\x1B[A".as_slice())
|
|
||||||
} else if delta_y < 0.0 {
|
|
||||||
terminal.input_no_scroll(b"\x1B[B".as_slice())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1025,10 +1025,9 @@ impl Terminal {
|
||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
) {
|
) {
|
||||||
let term_lock = self.term.lock();
|
let is_sgr = self.term.lock().mode().contains(TermMode::SGR_MOUSE);
|
||||||
let mode = term_lock.mode();
|
|
||||||
|
|
||||||
if mode.contains(TermMode::SGR_MOUSE) {
|
if is_sgr {
|
||||||
let codes = self.mouse_reporter.sgr_mouse_wheel_scroll(
|
let codes = self.mouse_reporter.sgr_mouse_wheel_scroll(
|
||||||
self.size().cell_width,
|
self.size().cell_width,
|
||||||
self.size().cell_height,
|
self.size().cell_height,
|
||||||
|
|
@ -1042,12 +1041,23 @@ impl Terminal {
|
||||||
self.notifier.notify(code);
|
self.notifier.notify(code);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
MouseReporter::report_mouse_wheel_as_arrows(
|
self.scroll_as_arrows(delta);
|
||||||
self,
|
}
|
||||||
self.size().cell_width,
|
}
|
||||||
self.size().cell_height,
|
|
||||||
delta,
|
pub fn scroll_as_arrows(&mut self, delta: ScrollDelta) {
|
||||||
);
|
let cell_width = self.size().cell_width;
|
||||||
|
let cell_height = self.size().cell_height;
|
||||||
|
let (_, lines_y) = self
|
||||||
|
.mouse_reporter
|
||||||
|
.accumulate_scroll(delta, cell_width, cell_height);
|
||||||
|
const SCROLL_SPEED: u32 = 3;
|
||||||
|
for _ in 0..(lines_y.unsigned_abs() * SCROLL_SPEED) {
|
||||||
|
if lines_y > 0 {
|
||||||
|
self.input_no_scroll(b"\x1B[A".as_slice())
|
||||||
|
} else if lines_y < 0 {
|
||||||
|
self.input_no_scroll(b"\x1B[B".as_slice())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,10 +45,7 @@ use std::{
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{Action, Terminal, TerminalScroll, menu::MenuState, terminal::Metadata};
|
||||||
Action, Terminal, TerminalScroll, menu::MenuState, mouse_reporter::MouseReporter,
|
|
||||||
terminal::Metadata,
|
|
||||||
};
|
|
||||||
|
|
||||||
const AUTOSCROLL_INTERVAL: Duration = Duration::from_millis(100);
|
const AUTOSCROLL_INTERVAL: Duration = Duration::from_millis(100);
|
||||||
|
|
||||||
|
|
@ -1551,12 +1548,7 @@ where
|
||||||
let row = y / terminal.size().cell_height;
|
let row = y / terminal.size().cell_height;
|
||||||
terminal.scroll_mouse(*delta, &state.modifiers, col as u32, row as u32);
|
terminal.scroll_mouse(*delta, &state.modifiers, col as u32, row as u32);
|
||||||
} else if terminal.term.lock().mode().contains(TermMode::ALT_SCREEN) {
|
} else if terminal.term.lock().mode().contains(TermMode::ALT_SCREEN) {
|
||||||
MouseReporter::report_mouse_wheel_as_arrows(
|
terminal.scroll_as_arrows(*delta);
|
||||||
&terminal,
|
|
||||||
terminal.size().cell_width,
|
|
||||||
terminal.size().cell_height,
|
|
||||||
*delta,
|
|
||||||
);
|
|
||||||
shell.capture_event();
|
shell.capture_event();
|
||||||
} else {
|
} else {
|
||||||
match delta {
|
match delta {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue