mirror of
https://github.com/alacritty/alacritty.git
synced 2024-11-11 13:51:01 -05:00
Add support for horizontal scrolling
This adds support for horizontal mouse scrolling in mouse mode and alternative scrolling modes. Fixes #2185.
This commit is contained in:
parent
5a3280e8e0
commit
ed67aa3c08
3 changed files with 60 additions and 19 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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<EventProxy, ActionContext<'_, Notifier, EventProxy>> {
|
||||
/// Handle events from winit.
|
||||
pub fn handle_event(&mut self, event: WinitEvent<'_, Event>) {
|
||||
|
|
|
@ -631,18 +631,19 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
|
|||
|
||||
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<T: EventListener, A: ActionContext<T>> Processor<T, A> {
|
|||
}
|
||||
}
|
||||
|
||||
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<T: EventListener, A: ActionContext<T>> Processor<T, A> {
|
|||
&& !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) {
|
||||
|
|
Loading…
Reference in a new issue