diff --git a/src/mouse_reporter.rs b/src/mouse_reporter.rs index 3d32b701..e426a196 100644 --- a/src/mouse_reporter.rs +++ b/src/mouse_reporter.rs @@ -3,10 +3,6 @@ use cosmic::{ iced::{Event, keyboard::Modifiers, mouse::Button}, }; -use crate::terminal::Terminal; - -const SCROLL_SPEED: u32 = 3; - #[derive(Default)] pub struct MouseReporter { last_movment_x: Option, @@ -17,6 +13,30 @@ pub struct 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 { match button { Button::Left => Some(0), @@ -178,24 +198,7 @@ impl MouseReporter { x: u32, y: u32, ) -> impl Iterator> { - 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) - } - }; + let (lines_x, lines_y) = self.accumulate_scroll(delta, term_cell_width, term_cell_height); //Resolve modifier flags let mut modifier_flags = 0; @@ -235,26 +238,4 @@ impl MouseReporter { 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()) - } - } - } } diff --git a/src/terminal.rs b/src/terminal.rs index 81b9f504..6171d6ca 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1025,10 +1025,9 @@ impl Terminal { x: u32, y: u32, ) { - let term_lock = self.term.lock(); - let mode = term_lock.mode(); + let is_sgr = self.term.lock().mode().contains(TermMode::SGR_MOUSE); - if mode.contains(TermMode::SGR_MOUSE) { + if is_sgr { let codes = self.mouse_reporter.sgr_mouse_wheel_scroll( self.size().cell_width, self.size().cell_height, @@ -1042,12 +1041,29 @@ impl Terminal { self.notifier.notify(code); } } else { - MouseReporter::report_mouse_wheel_as_arrows( - self, - self.size().cell_width, - self.size().cell_height, - delta, - ); + self.scroll_as_arrows(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); + let is_app_cursor = self.term.lock().mode().contains(TermMode::APP_CURSOR); + let (up, down) = if is_app_cursor { + (&b"\x1BOA"[..], &b"\x1BOB"[..]) + } else { + (&b"\x1B[A"[..], &b"\x1B[B"[..]) + }; + const SCROLL_SPEED: u32 = 3; + for _ in 0..(lines_y.unsigned_abs() * SCROLL_SPEED) { + if lines_y > 0 { + self.input_no_scroll(up) + } else if lines_y < 0 { + self.input_no_scroll(down) + } } } } diff --git a/src/terminal_box.rs b/src/terminal_box.rs index b5bdabd9..3367e018 100644 --- a/src/terminal_box.rs +++ b/src/terminal_box.rs @@ -45,10 +45,7 @@ use std::{ time::{Duration, Instant}, }; -use crate::{ - Action, Terminal, TerminalScroll, menu::MenuState, mouse_reporter::MouseReporter, - terminal::Metadata, -}; +use crate::{Action, Terminal, TerminalScroll, menu::MenuState, terminal::Metadata}; const AUTOSCROLL_INTERVAL: Duration = Duration::from_millis(100); @@ -1551,12 +1548,7 @@ where let row = y / terminal.size().cell_height; terminal.scroll_mouse(*delta, &state.modifiers, col as u32, row as u32); } else if terminal.term.lock().mode().contains(TermMode::ALT_SCREEN) { - MouseReporter::report_mouse_wheel_as_arrows( - &terminal, - terminal.size().cell_width, - terminal.size().cell_height, - *delta, - ); + terminal.scroll_as_arrows(*delta); shell.capture_event(); } else { match delta {