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
|
### Added
|
||||||
|
|
||||||
- Uppercase `-T` short form for `--title`
|
- Uppercase `-T` short form for `--title`
|
||||||
|
- Support for horizontal scrolling in mouse mode and alternative scrolling modes
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|
|
@ -1033,7 +1033,7 @@ pub struct Mouse {
|
||||||
pub last_click_timestamp: Instant,
|
pub last_click_timestamp: Instant,
|
||||||
pub last_click_button: MouseButton,
|
pub last_click_button: MouseButton,
|
||||||
pub click_state: ClickState,
|
pub click_state: ClickState,
|
||||||
pub scroll_px: f64,
|
pub accumulated_scroll: AccumulatedScroll,
|
||||||
pub cell_side: Side,
|
pub cell_side: Side,
|
||||||
pub lines_scrolled: f32,
|
pub lines_scrolled: f32,
|
||||||
pub block_hint_launcher: bool,
|
pub block_hint_launcher: bool,
|
||||||
|
@ -1057,7 +1057,7 @@ impl Default for Mouse {
|
||||||
block_hint_launcher: Default::default(),
|
block_hint_launcher: Default::default(),
|
||||||
inside_text_area: Default::default(),
|
inside_text_area: Default::default(),
|
||||||
lines_scrolled: Default::default(),
|
lines_scrolled: Default::default(),
|
||||||
scroll_px: Default::default(),
|
accumulated_scroll: Default::default(),
|
||||||
x: Default::default(),
|
x: Default::default(),
|
||||||
y: 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>> {
|
impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> {
|
||||||
/// Handle events from winit.
|
/// Handle events from winit.
|
||||||
pub fn handle_event(&mut self, event: WinitEvent<'_, Event>) {
|
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) {
|
pub fn mouse_wheel_input(&mut self, delta: MouseScrollDelta, phase: TouchPhase) {
|
||||||
match delta {
|
match delta {
|
||||||
MouseScrollDelta::LineDelta(_columns, lines) => {
|
MouseScrollDelta::LineDelta(columns, lines) => {
|
||||||
let new_scroll_px = lines * self.ctx.size_info().cell_height();
|
let new_scroll_px_x = columns * self.ctx.size_info().cell_width();
|
||||||
self.scroll_terminal(f64::from(new_scroll_px));
|
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) => {
|
MouseScrollDelta::PixelDelta(lpos) => {
|
||||||
match phase {
|
match phase {
|
||||||
TouchPhase::Started => {
|
TouchPhase::Started => {
|
||||||
// Reset offset to zero.
|
// Reset offset to zero.
|
||||||
self.ctx.mouse_mut().scroll_px = 0.;
|
self.ctx.mouse_mut().accumulated_scroll = Default::default();
|
||||||
},
|
},
|
||||||
TouchPhase::Moved => {
|
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());
|
let height = f64::from(self.ctx.size_info().cell_height());
|
||||||
|
|
||||||
if self.ctx.mouse_mode() {
|
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 code = if new_scroll_y_px > 0. { MOUSE_WHEEL_UP } else { MOUSE_WHEEL_DOWN };
|
||||||
let lines = (self.ctx.mouse().scroll_px / height).abs() as i32;
|
let lines = (self.ctx.mouse().accumulated_scroll.y / height).abs() as i32;
|
||||||
|
|
||||||
for _ in 0..lines {
|
for _ in 0..lines {
|
||||||
self.mouse_report(code, ElementState::Pressed);
|
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
|
} else if self
|
||||||
.ctx
|
.ctx
|
||||||
.terminal()
|
.terminal()
|
||||||
|
@ -670,30 +685,45 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
|
||||||
&& !self.ctx.modifiers().shift()
|
&& !self.ctx.modifiers().shift()
|
||||||
{
|
{
|
||||||
let multiplier = f64::from(self.ctx.config().terminal_config.scrolling.multiplier);
|
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' };
|
self.ctx.mouse_mut().accumulated_scroll.x += new_scroll_x_px * multiplier;
|
||||||
let lines = (self.ctx.mouse().scroll_px / height).abs() as i32;
|
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 {
|
for _ in 0..lines {
|
||||||
content.push(0x1b);
|
content.push(0x1b);
|
||||||
content.push(b'O');
|
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);
|
self.ctx.write_to_pty(content);
|
||||||
} else {
|
} else {
|
||||||
let multiplier = f64::from(self.ctx.config().terminal_config.scrolling.multiplier);
|
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 {
|
if lines != 0 {
|
||||||
self.ctx.scroll(Scroll::Delta(lines));
|
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) {
|
pub fn on_focus_change(&mut self, is_focused: bool) {
|
||||||
|
|
Loading…
Reference in a new issue