zellij/zellij-utils/src/input/mouse.rs
Thomas Linford f93308f211
feat(ui): initial mouse support (#448)
* Initial mouse support

* enable mouse support (termion MouseTerminal)
* handle scroll up and down events

* Allow enabling/disabling of mouse reporting

Store the mouse terminal on OsInputOutput

* WIP: switch pane focus with mouse

* testing to get mouse character selection

* wip mouse selection

* wip: mouse selection

- initial handling of mouse events for
  text selection within a pane
- wide characters currently problematic
- selection is not highlighted

* highlight currently selected text

* improve get currently selected text from TerminalPane

* copy selection to clipboard (wayland only for now)

* Add missing set_should_render on selection update

* Improve text selection

- Strip whitespace from end of lines
- Insert newlines when selection spans multiple lines

* Simplify selection logic

- Remove Range struct
- Selection is not an Option anymore, it's empty when start == end

* copy selection to clipboard with OSC-52 sequence

* Improve text selection with multiple panes

- Constrain mouse hold and release events to currently active pane
- Fix calculation of columns with side by side panes

* fix for PositionAndSize changes

* Fix mouse selection with full screen pane.

- Transform mouse event positions to relative when passing to pane.

* Move selection to grid, rework highlighting.

- Mark selected lines for update in grid output buffer, for now in the
  simplest way possible, but can be made more efficient by calculating
  changed lines only.
- Clear selection on pane resize.
- Re-add logic to forward mouse hold and release events only to
  currently active pane.

* Tidy up selection

- add method to get selection line range
- add method to sort the current selection

* Grid: move current selection up/down when scrolling

- Make the selection work with lines in lines_above and lines_below
- Todo: update selection end when scrolling with mouse button being held
- Todo: figure out how to move selection when new characters are added.

* Grid: move selection when new lines are added

* Keep track of selection being active

- Handle the selection growing/shrinking when scrolling with mouse
  button held down but not yet released.

* Improve selection end with multiple panes

* Tidying up

- remove logging statements, unused code

* Add some unit tests for selection, move position to zellij-utils

* Change Position::new to take i32 for line

* Grid: add unit tests for copy from selection

* add basic integration test for mouse pane focus

* Add basic integration test for mouse scroll

* Use color from palette for selection rendering

* Improve performance of selection render

- Try to minimize lines to update on selection start/update/end

* fixes for updated start method

* fix lines not in viewport being marked for rendering

- the previous optimization to grid selection rendering was always
adding the lines at the extremes of previous selection, causing problems
when scrolling up or down
- make sure to only add lines in viewport

* Disable mouse mode on exit

* use saturating_sub for usize subtractions

* copy selection to clipboard on mouse release

* disable mouse on exit after error

* remove left-over comments

* remove copy keybinding

* add default impl for selection methods in Pane

- remove the useless methods from Impl Pane in PluginPane

* move line diff between selections to selection

* add option to disable mouse mode

* Allow scrolling with mouse while selecting.

* move action repeater to os_input_output, change timeout to 10ms

- change repeater to take an action instead of a position with hardcoded
action

* replace mouse mode integration tests with e2e tests

* cleanup

* cleanup

* check if mouse mode is disabled from merged options

* fix missing changes in tests, cleanup
2021-07-02 16:40:50 +02:00

69 lines
2.2 KiB
Rust

use serde::{Deserialize, Serialize};
use crate::position::Position;
/// A mouse related event
#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize, Serialize)]
pub enum MouseEvent {
/// A mouse button was pressed.
///
/// The coordinates are zero-based.
Press(MouseButton, Position),
/// A mouse button was released.
///
/// The coordinates are zero-based.
Release(Position),
/// A mouse button is held over the given coordinates.
///
/// The coordinates are zero-based.
Hold(Position),
}
impl From<termion::event::MouseEvent> for MouseEvent {
fn from(event: termion::event::MouseEvent) -> Self {
match event {
termion::event::MouseEvent::Press(button, x, y) => Self::Press(
MouseButton::from(button),
Position::new((y.saturating_sub(1)) as i32, x.saturating_sub(1)),
),
termion::event::MouseEvent::Release(x, y) => Self::Release(Position::new(
(y.saturating_sub(1)) as i32,
x.saturating_sub(1),
)),
termion::event::MouseEvent::Hold(x, y) => Self::Hold(Position::new(
(y.saturating_sub(1)) as i32,
x.saturating_sub(1),
)),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub enum MouseButton {
/// The left mouse button.
Left,
/// The right mouse button.
Right,
/// The middle mouse button.
Middle,
/// Mouse wheel is going up.
///
/// This event is typically only used with Mouse::Press.
WheelUp,
/// Mouse wheel is going down.
///
/// This event is typically only used with Mouse::Press.
WheelDown,
}
impl From<termion::event::MouseButton> for MouseButton {
fn from(button: termion::event::MouseButton) -> Self {
match button {
termion::event::MouseButton::Left => Self::Left,
termion::event::MouseButton::Right => Self::Right,
termion::event::MouseButton::Middle => Self::Middle,
termion::event::MouseButton::WheelUp => Self::WheelUp,
termion::event::MouseButton::WheelDown => Self::WheelDown,
}
}
}