From ed67aa3c081950a55a8dc7fa1bd9c626f6e7a187 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Mon, 16 Jan 2023 20:22:01 +0300 Subject: Add support for horizontal scrolling This adds support for horizontal mouse scrolling in mouse mode and alternative scrolling modes. Fixes #2185. --- CHANGELOG.md | 1 + alacritty/src/event.rs | 14 +++++++++-- alacritty/src/input.rs | 64 ++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 60 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2c8ce41..40855955 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Uppercase `-T` short form for `--title` +- Support for horizontal scrolling in mouse mode and alternative scrolling modes ### Changed diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 2fb60b2a..9388b8a9 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1033,7 +1033,7 @@ pub struct Mouse { pub last_click_timestamp: Instant, pub last_click_button: MouseButton, pub click_state: ClickState, - pub scroll_px: f64, + pub accumulated_scroll: AccumulatedScroll, pub cell_side: Side, pub lines_scrolled: f32, pub block_hint_launcher: bool, @@ -1057,7 +1057,7 @@ impl Default for Mouse { block_hint_launcher: Default::default(), inside_text_area: Default::default(), lines_scrolled: Default::default(), - scroll_px: Default::default(), + accumulated_scroll: Default::default(), x: Default::default(), y: Default::default(), } @@ -1081,6 +1081,16 @@ impl Mouse { } } +/// The amount of scroll accumulated from the pointer events. +#[derive(Default, Debug)] +pub struct AccumulatedScroll { + /// Scroll we should perform along `x` axis. + pub x: f64, + + /// Scroll we should perform along `y` axis. + pub y: f64, +} + impl input::Processor> { /// Handle events from winit. pub fn handle_event(&mut self, event: WinitEvent<'_, Event>) { diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs index c8d948ff..33be1bf3 100644 --- a/alacritty/src/input.rs +++ b/alacritty/src/input.rs @@ -631,18 +631,19 @@ impl> Processor { pub fn mouse_wheel_input(&mut self, delta: MouseScrollDelta, phase: TouchPhase) { match delta { - MouseScrollDelta::LineDelta(_columns, lines) => { - let new_scroll_px = lines * self.ctx.size_info().cell_height(); - self.scroll_terminal(f64::from(new_scroll_px)); + MouseScrollDelta::LineDelta(columns, lines) => { + let new_scroll_px_x = columns * self.ctx.size_info().cell_width(); + let new_scroll_px_y = lines * self.ctx.size_info().cell_height(); + self.scroll_terminal(new_scroll_px_x as f64, new_scroll_px_y as f64); }, MouseScrollDelta::PixelDelta(lpos) => { match phase { TouchPhase::Started => { // Reset offset to zero. - self.ctx.mouse_mut().scroll_px = 0.; + self.ctx.mouse_mut().accumulated_scroll = Default::default(); }, TouchPhase::Moved => { - self.scroll_terminal(lpos.y); + self.scroll_terminal(lpos.x, lpos.y); }, _ => (), } @@ -650,18 +651,32 @@ impl> Processor { } } - fn scroll_terminal(&mut self, new_scroll_px: f64) { + fn scroll_terminal(&mut self, new_scroll_x_px: f64, new_scroll_y_px: f64) { + const MOUSE_WHEEL_UP: u8 = 64; + const MOUSE_WHEEL_DOWN: u8 = 65; + const MOUSE_WHEEL_LEFT: u8 = 66; + const MOUSE_WHEEL_RIGHT: u8 = 67; + + let width = f64::from(self.ctx.size_info().cell_width()); let height = f64::from(self.ctx.size_info().cell_height()); if self.ctx.mouse_mode() { - self.ctx.mouse_mut().scroll_px += new_scroll_px; + self.ctx.mouse_mut().accumulated_scroll.x += new_scroll_x_px; + self.ctx.mouse_mut().accumulated_scroll.y += new_scroll_y_px; - let code = if new_scroll_px > 0. { 64 } else { 65 }; - let lines = (self.ctx.mouse().scroll_px / height).abs() as i32; + let code = if new_scroll_y_px > 0. { MOUSE_WHEEL_UP } else { MOUSE_WHEEL_DOWN }; + let lines = (self.ctx.mouse().accumulated_scroll.y / height).abs() as i32; for _ in 0..lines { self.mouse_report(code, ElementState::Pressed); } + + let code = if new_scroll_x_px > 0. { MOUSE_WHEEL_LEFT } else { MOUSE_WHEEL_RIGHT }; + let columns = (self.ctx.mouse().accumulated_scroll.x / width).abs() as i32; + + for _ in 0..columns { + self.mouse_report(code, ElementState::Pressed); + } } else if self .ctx .terminal() @@ -670,30 +685,45 @@ impl> Processor { && !self.ctx.modifiers().shift() { let multiplier = f64::from(self.ctx.config().terminal_config.scrolling.multiplier); - self.ctx.mouse_mut().scroll_px += new_scroll_px * multiplier; - let cmd = if new_scroll_px > 0. { b'A' } else { b'B' }; - let lines = (self.ctx.mouse().scroll_px / height).abs() as i32; + self.ctx.mouse_mut().accumulated_scroll.x += new_scroll_x_px * multiplier; + self.ctx.mouse_mut().accumulated_scroll.y += new_scroll_y_px * multiplier; + + // The chars here are the same as for the respective arrow keys. + let line_cmd = if new_scroll_y_px > 0. { b'A' } else { b'B' }; + let column_cmd = if new_scroll_x_px > 0. { b'D' } else { b'C' }; + + let lines = (self.ctx.mouse().accumulated_scroll.y / height).abs() as usize; + let columns = (self.ctx.mouse().accumulated_scroll.x / width).abs() as usize; + + let mut content = Vec::with_capacity(3 * (lines + columns)); - let mut content = Vec::with_capacity(lines as usize * 3); for _ in 0..lines { content.push(0x1b); content.push(b'O'); - content.push(cmd); + content.push(line_cmd); + } + + for _ in 0..columns { + content.push(0x1b); + content.push(b'O'); + content.push(column_cmd); } + self.ctx.write_to_pty(content); } else { let multiplier = f64::from(self.ctx.config().terminal_config.scrolling.multiplier); - self.ctx.mouse_mut().scroll_px += new_scroll_px * multiplier; + self.ctx.mouse_mut().accumulated_scroll.y += new_scroll_y_px * multiplier; - let lines = (self.ctx.mouse().scroll_px / height) as i32; + let lines = (self.ctx.mouse().accumulated_scroll.y / height) as i32; if lines != 0 { self.ctx.scroll(Scroll::Delta(lines)); } } - self.ctx.mouse_mut().scroll_px %= height; + self.ctx.mouse_mut().accumulated_scroll.x %= width; + self.ctx.mouse_mut().accumulated_scroll.y %= height; } pub fn on_focus_change(&mut self, is_focused: bool) { -- cgit v1.2.3