diff options
| author | Thomas Linford <tlinford@users.noreply.github.com> | 2021-07-02 16:40:50 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-07-02 16:40:50 +0200 |
| commit | f93308f211565fae527f9b1e5788e12d0ea887c4 (patch) | |
| tree | edb915be32a81c1caae2c7218398c96344a29bd0 /src/tests/e2e | |
| parent | chore(changelog): Add run-command option #596 (diff) | |
| download | sl0ppij-f93308f211565fae527f9b1e5788e12d0ea887c4.tar.gz sl0ppij-f93308f211565fae527f9b1e5788e12d0ea887c4.tar.xz sl0ppij-f93308f211565fae527f9b1e5788e12d0ea887c4.zip | |
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
Diffstat (limited to 'src/tests/e2e')
3 files changed, 211 insertions, 1 deletions
diff --git a/src/tests/e2e/cases.rs b/src/tests/e2e/cases.rs index 69233f25..8d41d44f 100644 --- a/src/tests/e2e/cases.rs +++ b/src/tests/e2e/cases.rs @@ -1,7 +1,7 @@ #![allow(unused)] use ::insta::assert_snapshot; -use zellij_utils::pane_size::PositionAndSize; +use zellij_utils::{pane_size::PositionAndSize, position::Position}; use rand::Rng; @@ -54,6 +54,17 @@ pub const BRACKETED_PASTE_START: [u8; 6] = [27, 91, 50, 48, 48, 126]; // \u{1b}[ pub const BRACKETED_PASTE_END: [u8; 6] = [27, 91, 50, 48, 49, 126]; // \u{1b}[201 pub const SLEEP: [u8; 0] = []; +// simplified, slighty adapted version of alacritty mouse reporting code +pub fn normal_mouse_report(position: Position, button: u8) -> Vec<u8> { + let Position { line, column } = position; + + let mut command = vec![b'\x1b', b'[', b'M', 32 + button]; + command.push(32 + 1 + column.0 as u8); + command.push(32 + 1 + line.0 as u8); + + command +} + // All the E2E tests are marked as "ignored" so that they can be run separately from the normal // tests @@ -785,3 +796,144 @@ pub fn accepts_basic_layout() { .run_all_steps(); assert_snapshot!(last_snapshot); } + +#[test] +#[ignore] +fn focus_pane_with_mouse() { + let fake_win_size = PositionAndSize { + cols: 120, + rows: 24, + x: 0, + y: 0, + ..Default::default() + }; + + let last_snapshot = RemoteRunner::new("split_terminals_vertically", fake_win_size, None) + .add_step(Step { + name: "Split pane to the right", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.status_bar_appears() && remote_terminal.cursor_position_is(2, 2) + { + remote_terminal.send_key(&PANE_MODE); + remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); + // back to normal mode after split + remote_terminal.send_key(&ENTER); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Click left pane", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { + remote_terminal.send_key(&normal_mouse_report(Position::new(5, 2), 0)); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Wait for left pane to be focused", + instruction: |remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(2, 2) && remote_terminal.tip_appears() { + // cursor is in the newly opened second pane + step_is_complete = true; + } + step_is_complete + }, + }) + .run_all_steps(); + assert_snapshot!(last_snapshot); +} + +#[test] +#[ignore] +pub fn scrolling_inside_a_pane_with_mouse() { + let fake_win_size = PositionAndSize { + cols: 120, + rows: 24, + x: 0, + y: 0, + ..Default::default() + }; + let last_snapshot = + RemoteRunner::new("scrolling_inside_a_pane_with_mouse", fake_win_size, None) + .add_step(Step { + name: "Split pane to the right", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.status_bar_appears() + && remote_terminal.cursor_position_is(2, 2) + { + remote_terminal.send_key(&PANE_MODE); + remote_terminal.send_key(&SPLIT_RIGHT_IN_PANE_MODE); + // back to normal mode after split + remote_terminal.send_key(&ENTER); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Fill terminal with text", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(63, 2) && remote_terminal.tip_appears() { + // cursor is in the newly opened second pane + remote_terminal.send_key(&format!("{:0<57}", "line1 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line2 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line3 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line4 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line5 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line6 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line7 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line8 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line9 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line10 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line11 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line12 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line13 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line14 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line15 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line16 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line17 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line18 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<59}", "line19 ").as_bytes()); + remote_terminal.send_key(&format!("{:0<58}", "line20 ").as_bytes()); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Scroll up inside pane", + instruction: |mut remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(119, 20) { + // all lines have been written to the pane + remote_terminal.send_key(&normal_mouse_report(Position::new(2, 64), 64)); + step_is_complete = true; + } + step_is_complete + }, + }) + .add_step(Step { + name: "Wait for scroll to finish", + instruction: |remote_terminal: RemoteTerminal| -> bool { + let mut step_is_complete = false; + if remote_terminal.cursor_position_is(119, 20) + && remote_terminal.snapshot_contains("line1 ") + { + // scrolled up one line + step_is_complete = true; + } + step_is_complete + }, + }) + .run_all_steps(); + assert_snapshot!(last_snapshot); +} diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__focus_pane_with_mouse.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__focus_pane_with_mouse.snap new file mode 100644 index 00000000..79e84810 --- /dev/null +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__focus_pane_with_mouse.snap @@ -0,0 +1,29 @@ +--- +source: src/tests/e2e/cases.rs +expression: last_snapshot + +--- + Zellij Tab #1 + +$ █ │$ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + │ + + Ctrl + <g> LOCK <p> PANE <t> TAB <r> RESIZE <s> SCROLL <o> SESSION <q> QUIT + Tip: Alt + n => open new pane. Alt + [] or hjkl => navigate between panes. diff --git a/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane_with_mouse.snap b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane_with_mouse.snap new file mode 100644 index 00000000..bff40376 --- /dev/null +++ b/src/tests/e2e/snapshots/zellij__tests__e2e__cases__scrolling_inside_a_pane_with_mouse.snap @@ -0,0 +1,29 @@ +--- +source: src/tests/e2e/cases.rs +expression: last_snapshot + +--- + Zellij Tab #1 + +$ │$ line1 000000000000000000000000000000000000000000000000000 + │line2 00000000000000000000000000000000000000000000000000000 + │line3 00000000000000000000000000000000000000000000000000000 + │line4 00000000000000000000000000000000000000000000000000000 + │line5 00000000000000000000000000000000000000000000000000000 + │line6 00000000000000000000000000000000000000000000000000000 + │line7 00000000000000000000000000000000000000000000000000000 + │line8 00000000000000000000000000000000000000000000000000000 + │line9 00000000000000000000000000000000000000000000000000000 + │line10 0000000000000000000000000000000000000000000000000000 + │line11 0000000000000000000000000000000000000000000000000000 + │line12 0000000000000000000000000000000000000000000000000000 + │line13 0000000000000000000000000000000000000000000000000000 + │line14 0000000000000000000000000000000000000000000000000000 + │line15 0000000000000000000000000000000000000000000000000000 + │line16 0000000000000000000000000000000000000000000000000000 + │line17 0000000000000000000000000000000000000000000000000000 + │line18 0000000000000000000000000000000000000000000000000000 + │line19 000000000000000000000000000000000000000000000000000█ + + Ctrl + <g> LOCK <p> PANE <t> TAB <r> RESIZE <s> SCROLL <o> SESSION <q> QUIT + Tip: Alt + n => open new pane. Alt + [] or hjkl => navigate between panes. |
