fix(mouse): improve mouse event reporting (#1329)

* fix: do not rebroadcast mouse press events
* fix: do not send generated mouse hold events to applications
* begin selecting only if click is on terminal pane
This commit is contained in:
Thomas Linford 2022-04-30 18:46:17 +02:00 committed by GitHub
parent 1f4e3d88c8
commit 03ffd08ebb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 30 additions and 23 deletions

View file

@ -1,9 +1,7 @@
use crate::os_input_output::ClientOsApi; use crate::os_input_output::ClientOsApi;
use crate::InputInstruction; use crate::InputInstruction;
use zellij_utils::channels::SenderWithContext; use zellij_utils::channels::SenderWithContext;
use zellij_utils::input::mouse::{MouseButton, MouseEvent}; use zellij_utils::termwiz::input::{InputEvent, InputParser, MouseButtons};
use zellij_utils::termwiz::input::{InputEvent, InputParser};
pub(crate) fn stdin_loop( pub(crate) fn stdin_loop(
os_input: Box<dyn ClientOsApi>, os_input: Box<dyn ClientOsApi>,
@ -17,8 +15,7 @@ pub(crate) fn stdin_loop(
current_buffer.append(&mut buf.to_vec()); current_buffer.append(&mut buf.to_vec());
let maybe_more = false; // read_from_stdin should (hopefully) always empty the STDIN buffer completely let maybe_more = false; // read_from_stdin should (hopefully) always empty the STDIN buffer completely
let parse_input_event = |input_event: InputEvent| { let parse_input_event = |input_event: InputEvent| {
holding_mouse = should_hold_mouse(input_event.clone()); if holding_mouse && is_mouse_press_or_hold(&input_event) {
if holding_mouse {
let mut poller = os_input.stdin_poller(); let mut poller = os_input.stdin_poller();
loop { loop {
let ready = poller.ready(); let ready = poller.ready();
@ -32,30 +29,28 @@ pub(crate) fn stdin_loop(
)) ))
.unwrap(); .unwrap();
} }
} else { }
holding_mouse = is_mouse_press_or_hold(&input_event);
send_input_instructions send_input_instructions
.send(InputInstruction::KeyEvent( .send(InputInstruction::KeyEvent(
input_event, input_event,
current_buffer.drain(..).collect(), current_buffer.drain(..).collect(),
)) ))
.unwrap(); .unwrap();
}
}; };
input_parser.parse(&buf, parse_input_event, maybe_more); input_parser.parse(&buf, parse_input_event, maybe_more);
} }
} }
fn should_hold_mouse(input_event: InputEvent) -> bool { fn is_mouse_press_or_hold(input_event: &InputEvent) -> bool {
if let InputEvent::Mouse(mouse_event) = input_event { if let InputEvent::Mouse(mouse_event) = input_event {
let mouse_event = zellij_utils::input::mouse::MouseEvent::from(mouse_event); if mouse_event.mouse_buttons.contains(MouseButtons::LEFT)
if let MouseEvent::Press(button, _point) = mouse_event { || mouse_event.mouse_buttons.contains(MouseButtons::RIGHT)
match button { {
MouseButton::Left | MouseButton::Right => {
return true; return true;
} }
_ => {}
}
}
} }
false false
} }

View file

@ -90,6 +90,7 @@ pub(crate) struct Tab {
// it seems that optimization is possible using `active_panes` // it seems that optimization is possible using `active_panes`
focus_pane_id: Option<PaneId>, focus_pane_id: Option<PaneId>,
copy_on_select: bool, copy_on_select: bool,
last_mouse_hold_position: Option<Position>,
terminal_emulator_colors: Rc<RefCell<Palette>>, terminal_emulator_colors: Rc<RefCell<Palette>>,
} }
@ -354,6 +355,7 @@ impl Tab {
clipboard_provider, clipboard_provider,
focus_pane_id: None, focus_pane_id: None,
copy_on_select: copy_options.copy_on_select, copy_on_select: copy_options.copy_on_select,
last_mouse_hold_position: None,
terminal_emulator_colors, terminal_emulator_colors,
} }
} }
@ -1547,7 +1549,7 @@ impl Tab {
relative_position.line.0 + 1 relative_position.line.0 + 1
); );
self.write_to_active_terminal(mouse_event.into_bytes(), client_id); self.write_to_active_terminal(mouse_event.into_bytes(), client_id);
} else { } else if let PaneId::Terminal(_) = pane.pid() {
pane.start_selection(&relative_position, client_id); pane.start_selection(&relative_position, client_id);
self.selecting_with_mouse = true; self.selecting_with_mouse = true;
} }
@ -1588,6 +1590,8 @@ impl Tab {
} }
} }
pub fn handle_mouse_release(&mut self, position: &Position, client_id: ClientId) { pub fn handle_mouse_release(&mut self, position: &Position, client_id: ClientId) {
self.last_mouse_hold_position = None;
if self.floating_panes.panes_are_visible() if self.floating_panes.panes_are_visible()
&& self.floating_panes.pane_is_being_moved_with_mouse() && self.floating_panes.pane_is_being_moved_with_mouse()
{ {
@ -1629,6 +1633,14 @@ impl Tab {
} }
} }
pub fn handle_mouse_hold(&mut self, position_on_screen: &Position, client_id: ClientId) { pub fn handle_mouse_hold(&mut self, position_on_screen: &Position, client_id: ClientId) {
// determine if event is repeated to enable smooth scrolling
let is_repeated = if let Some(last_position) = self.last_mouse_hold_position {
position_on_screen == &last_position
} else {
false
};
self.last_mouse_hold_position = Some(*position_on_screen);
let search_selectable = true; let search_selectable = true;
if self.floating_panes.panes_are_visible() if self.floating_panes.panes_are_visible()
@ -1646,7 +1658,7 @@ impl Tab {
if let Some(active_pane) = active_pane { if let Some(active_pane) = active_pane {
let relative_position = active_pane.relative_position(position_on_screen); let relative_position = active_pane.relative_position(position_on_screen);
if active_pane.mouse_mode() { if active_pane.mouse_mode() && !is_repeated {
// ensure that coordinates are valid // ensure that coordinates are valid
let col = (relative_position.column.0 + 1) let col = (relative_position.column.0 + 1)
.max(1) .max(1)