mirror of
https://github.com/zellij-org/zellij.git
synced 2024-11-23 08:57:14 +03:00
fix(mouse): avoid forwarding click events on pane border (#1584)
* if left click is on pane border do not forward to application * properly handle frames * fix comment * fix another comment * add tests, fix edge case
This commit is contained in:
parent
d1fa067713
commit
e2a3438c86
@ -8,7 +8,8 @@ use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use zellij_utils::{
|
||||
data::{Palette, Style},
|
||||
pane_size::{PaneGeom, SizeInPixels},
|
||||
pane_size::{Offset, PaneGeom, SizeInPixels},
|
||||
position::Position,
|
||||
};
|
||||
|
||||
use std::fmt::Write;
|
||||
@ -391,3 +392,255 @@ pub fn keep_working_after_corrupted_sixel_image() {
|
||||
terminal_pane.handle_pty_bytes(text_to_fill_pane.into_bytes());
|
||||
assert_snapshot!(format!("{:?}", terminal_pane.grid));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn pane_with_frame_position_is_on_frame() {
|
||||
let mut fake_win_size = PaneGeom {
|
||||
x: 10,
|
||||
y: 10,
|
||||
..PaneGeom::default()
|
||||
};
|
||||
fake_win_size.cols.set_inner(121);
|
||||
fake_win_size.rows.set_inner(20);
|
||||
|
||||
let pid = 1;
|
||||
let style = Style::default();
|
||||
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
|
||||
let terminal_emulator_colors = Rc::new(RefCell::new(Palette::default()));
|
||||
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
|
||||
let character_cell_size = Rc::new(RefCell::new(Some(SizeInPixels {
|
||||
width: 8,
|
||||
height: 21,
|
||||
})));
|
||||
let mut terminal_pane = TerminalPane::new(
|
||||
pid,
|
||||
fake_win_size,
|
||||
style,
|
||||
0,
|
||||
String::new(),
|
||||
Rc::new(RefCell::new(LinkHandler::new())),
|
||||
character_cell_size,
|
||||
sixel_image_store,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
); // 0 is the pane index
|
||||
|
||||
terminal_pane.set_content_offset(Offset::frame(1));
|
||||
|
||||
// row above pane: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 129)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 131)));
|
||||
|
||||
// first row: border for 10 <= col <= 130
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 9)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(10, 10)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(10, 11)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(10, 70)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(10, 129)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(10, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 131)));
|
||||
|
||||
// second row: border only at col=10,130
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 9)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(11, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 70)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(11, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 131)));
|
||||
|
||||
// row in the middle: border only at col=10,130
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 9)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(15, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 70)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(15, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 131)));
|
||||
|
||||
// last row: border for 10 <= col <= 130
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 9)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(29, 10)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(29, 11)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(29, 70)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(29, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 131)));
|
||||
|
||||
// row below pane: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 131)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn pane_with_bottom_and_right_borders_position_is_on_frame() {
|
||||
let mut fake_win_size = PaneGeom {
|
||||
x: 10,
|
||||
y: 10,
|
||||
..PaneGeom::default()
|
||||
};
|
||||
fake_win_size.cols.set_inner(121);
|
||||
fake_win_size.rows.set_inner(20);
|
||||
|
||||
let pid = 1;
|
||||
let style = Style::default();
|
||||
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
|
||||
let terminal_emulator_colors = Rc::new(RefCell::new(Palette::default()));
|
||||
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
|
||||
let character_cell_size = Rc::new(RefCell::new(Some(SizeInPixels {
|
||||
width: 8,
|
||||
height: 21,
|
||||
})));
|
||||
let mut terminal_pane = TerminalPane::new(
|
||||
pid,
|
||||
fake_win_size,
|
||||
style,
|
||||
0,
|
||||
String::new(),
|
||||
Rc::new(RefCell::new(LinkHandler::new())),
|
||||
character_cell_size,
|
||||
sixel_image_store,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
); // 0 is the pane index
|
||||
|
||||
terminal_pane.set_content_offset(Offset::shift(1, 1));
|
||||
|
||||
// row above pane: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 129)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 131)));
|
||||
|
||||
// first row: border only at col=130
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 129)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(10, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 131)));
|
||||
|
||||
// second row: border only at col=130
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 70)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(11, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 131)));
|
||||
|
||||
// row in the middle: border only at col=130
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 70)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(15, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 131)));
|
||||
|
||||
// last row: border for 10 <= col <= 130
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 9)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(29, 10)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(29, 11)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(29, 70)));
|
||||
assert!(terminal_pane.position_is_on_frame(&Position::new(29, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 131)));
|
||||
|
||||
// row below pane: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 131)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn frameless_pane_position_is_on_frame() {
|
||||
let mut fake_win_size = PaneGeom {
|
||||
x: 10,
|
||||
y: 10,
|
||||
..PaneGeom::default()
|
||||
};
|
||||
fake_win_size.cols.set_inner(121);
|
||||
fake_win_size.rows.set_inner(20);
|
||||
|
||||
let pid = 1;
|
||||
let style = Style::default();
|
||||
let sixel_image_store = Rc::new(RefCell::new(SixelImageStore::default()));
|
||||
let terminal_emulator_colors = Rc::new(RefCell::new(Palette::default()));
|
||||
let terminal_emulator_color_codes = Rc::new(RefCell::new(HashMap::new()));
|
||||
let character_cell_size = Rc::new(RefCell::new(Some(SizeInPixels {
|
||||
width: 8,
|
||||
height: 21,
|
||||
})));
|
||||
let mut terminal_pane = TerminalPane::new(
|
||||
pid,
|
||||
fake_win_size,
|
||||
style,
|
||||
0,
|
||||
String::new(),
|
||||
Rc::new(RefCell::new(LinkHandler::new())),
|
||||
character_cell_size,
|
||||
sixel_image_store,
|
||||
terminal_emulator_colors,
|
||||
terminal_emulator_color_codes,
|
||||
); // 0 is the pane index
|
||||
|
||||
terminal_pane.set_content_offset(Offset::default());
|
||||
|
||||
// row above pane: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 129)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(9, 131)));
|
||||
|
||||
// first row: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 129)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(10, 131)));
|
||||
|
||||
// second row: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(11, 131)));
|
||||
|
||||
// random row in the middle: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(15, 131)));
|
||||
|
||||
// last row: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 9)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(29, 131)));
|
||||
|
||||
// row below pane: no border
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 10)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 11)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 70)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 130)));
|
||||
assert!(!terminal_pane.position_is_on_frame(&Position::new(30, 131)));
|
||||
}
|
||||
|
@ -262,13 +262,32 @@ pub trait Pane {
|
||||
fn relative_position(&self, position_on_screen: &Position) -> Position {
|
||||
position_on_screen.relative_to(self.get_content_y(), self.get_content_x())
|
||||
}
|
||||
fn position_is_on_frame(&self, position_on_screen: &Position) -> bool {
|
||||
// TODO: handle cases where we have no frame
|
||||
position_on_screen.line() == self.y() as isize
|
||||
|| position_on_screen.line()
|
||||
== (self.y() as isize + self.rows() as isize).saturating_sub(1)
|
||||
|| position_on_screen.column() == self.x()
|
||||
|| position_on_screen.column() == (self.x() + self.cols()).saturating_sub(1)
|
||||
fn position_is_on_frame(&self, position: &Position) -> bool {
|
||||
if !self.contains(position) {
|
||||
return false;
|
||||
}
|
||||
if (self.x()..self.get_content_x()).contains(&position.column()) {
|
||||
// position is on left border
|
||||
return true;
|
||||
}
|
||||
if (self.get_content_x() + self.get_content_columns()..(self.x() + self.cols()))
|
||||
.contains(&position.column())
|
||||
{
|
||||
// position is on right border
|
||||
return true;
|
||||
}
|
||||
if (self.y() as isize..self.get_content_y() as isize).contains(&position.line()) {
|
||||
// position is on top border
|
||||
return true;
|
||||
}
|
||||
if ((self.get_content_y() + self.get_content_rows()) as isize
|
||||
..(self.y() + self.rows()) as isize)
|
||||
.contains(&position.line())
|
||||
{
|
||||
// position is on bottom border
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
fn store_pane_name(&mut self);
|
||||
fn load_pane_name(&mut self);
|
||||
@ -1709,12 +1728,14 @@ impl Tab {
|
||||
let relative_position = pane.relative_position(position);
|
||||
|
||||
if pane.mouse_mode() {
|
||||
let mouse_event = format!(
|
||||
"\u{1b}[<0;{:?};{:?}M",
|
||||
relative_position.column.0 + 1,
|
||||
relative_position.line.0 + 1
|
||||
);
|
||||
self.write_to_active_terminal(mouse_event.into_bytes(), client_id);
|
||||
if !pane.position_is_on_frame(position) {
|
||||
let mouse_event = format!(
|
||||
"\u{1b}[<0;{:?};{:?}M",
|
||||
relative_position.column() + 1,
|
||||
relative_position.line() + 1
|
||||
);
|
||||
self.write_to_active_terminal(mouse_event.into_bytes(), client_id);
|
||||
}
|
||||
} else {
|
||||
// TODO: rename this method, it is used to forward click events to plugin panes
|
||||
pane.start_selection(&relative_position, client_id);
|
||||
@ -1730,12 +1751,14 @@ impl Tab {
|
||||
if let Some(pane) = self.get_pane_at(position, false) {
|
||||
let relative_position = pane.relative_position(position);
|
||||
if pane.mouse_mode() {
|
||||
let mouse_event = format!(
|
||||
"\u{1b}[<2;{:?};{:?}M",
|
||||
relative_position.column.0 + 1,
|
||||
relative_position.line.0 + 1
|
||||
);
|
||||
self.write_to_active_terminal(mouse_event.into_bytes(), client_id);
|
||||
if !pane.position_is_on_frame(position) {
|
||||
let mouse_event = format!(
|
||||
"\u{1b}[<2;{:?};{:?}M",
|
||||
relative_position.column() + 1,
|
||||
relative_position.line() + 1
|
||||
);
|
||||
self.write_to_active_terminal(mouse_event.into_bytes(), client_id);
|
||||
}
|
||||
} else {
|
||||
pane.handle_right_click(&relative_position, client_id);
|
||||
}
|
||||
@ -1777,11 +1800,11 @@ impl Tab {
|
||||
let relative_position = active_pane.relative_position(position);
|
||||
if active_pane.mouse_mode() {
|
||||
// ensure that coordinates are valid
|
||||
let col = (relative_position.column.0 + 1)
|
||||
let col = (relative_position.column() + 1)
|
||||
.max(1)
|
||||
.min(active_pane.get_content_columns());
|
||||
|
||||
let line = (relative_position.line.0 + 1)
|
||||
let line = (relative_position.line() + 1)
|
||||
.max(1)
|
||||
.min(active_pane.get_content_rows() as isize);
|
||||
let mouse_event = format!("\u{1b}[<0;{:?};{:?}m", col, line);
|
||||
@ -1840,11 +1863,11 @@ impl Tab {
|
||||
let relative_position = active_pane.relative_position(position_on_screen);
|
||||
if active_pane.mouse_mode() && !is_repeated {
|
||||
// ensure that coordinates are valid
|
||||
let col = (relative_position.column.0 + 1)
|
||||
let col = (relative_position.column() + 1)
|
||||
.max(1)
|
||||
.min(active_pane.get_content_columns());
|
||||
|
||||
let line = (relative_position.line.0 + 1)
|
||||
let line = (relative_position.line() + 1)
|
||||
.max(1)
|
||||
.min(active_pane.get_content_rows() as isize);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user