Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mouse AnyEvent tracking (1003) -- work in progress #3538

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 40 additions & 76 deletions zellij-client/src/input_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,13 @@ use zellij_utils::{
actions::Action,
cast_termwiz_key,
config::Config,
mouse::{MouseButton, MouseEvent},
mouse::{MouseEvent, MouseEventType},
options::Options,
},
ipc::{ClientToServerMsg, ExitReason},
termwiz::input::InputEvent,
};

#[derive(Debug, Clone, Copy)]
enum HeldMouseButton {
Left,
Right,
Middle,
}

impl Default for HeldMouseButton {
fn default() -> Self {
HeldMouseButton::Left
}
}

/// Handles the dispatching of [`Action`]s according to the current
/// [`InputMode`], and keep tracks of the current [`InputMode`].
struct InputHandler {
Expand All @@ -43,7 +30,7 @@ struct InputHandler {
send_client_instructions: SenderWithContext<ClientInstruction>,
should_exit: bool,
receive_input_instructions: Receiver<(InputInstruction, ErrorContext)>,
holding_mouse: Option<HeldMouseButton>,
mouse_old_event: MouseEvent,
mouse_mode_active: bool,
}

Expand All @@ -67,7 +54,7 @@ impl InputHandler {
send_client_instructions,
should_exit: false,
receive_input_instructions,
holding_mouse: None,
mouse_old_event: MouseEvent::new(),
mouse_mode_active: false,
}
}
Expand Down Expand Up @@ -99,8 +86,10 @@ impl InputHandler {
self.handle_key(&key, raw_bytes, false);
},
InputEvent::Mouse(mouse_event) => {
let mouse_event =
zellij_utils::input::mouse::MouseEvent::from(mouse_event);
let mouse_event = zellij_utils::input::mouse::MouseEvent::from_termwiz(
&mut self.mouse_old_event,
mouse_event,
);
self.handle_mouse_event(&mouse_event);
},
InputEvent::Paste(pasted_text) => {
Expand Down Expand Up @@ -215,68 +204,43 @@ impl InputHandler {
}
}
fn handle_mouse_event(&mut self, mouse_event: &MouseEvent) {
match *mouse_event {
MouseEvent::Press(button, point) => match button {
MouseButton::WheelUp => {
// This dispatch handles all of the output(s) to terminal
// pane(s).
self.dispatch_action(Action::MouseEvent(*mouse_event), None);

// The rest of this is for the plugin API actions, text
// selection, pane move/resize, etc.
match mouse_event.event_type {
MouseEventType::Press => {
// AZL TODO
/*
if buttons.wheel_up {
self.dispatch_action(Action::ScrollUpAt(point), None);
},
MouseButton::WheelDown => {
} else if buttons.wheel_down {
self.dispatch_action(Action::ScrollDownAt(point), None);
},
MouseButton::Left => {
if self.holding_mouse.is_some() {
self.dispatch_action(Action::MouseHoldLeft(point), None);
} else {
self.dispatch_action(Action::LeftClick(point), None);
}
self.holding_mouse = Some(HeldMouseButton::Left);
},
MouseButton::Right => {
if self.holding_mouse.is_some() {
self.dispatch_action(Action::MouseHoldRight(point), None);
} else {
self.dispatch_action(Action::RightClick(point), None);
}
self.holding_mouse = Some(HeldMouseButton::Right);
},
MouseButton::Middle => {
if self.holding_mouse.is_some() {
self.dispatch_action(Action::MouseHoldMiddle(point), None);
} else {
self.dispatch_action(Action::MiddleClick(point), None);
}
self.holding_mouse = Some(HeldMouseButton::Middle);
},
} else if buttons.left {
self.dispatch_action(Action::LeftClick(point), None);
} else if buttons.right {
self.dispatch_action(Action::RightClick(point), None);
} else if buttons.middle {
self.dispatch_action(Action::MiddleClick(point), None);
}
*/
},
MouseEvent::Release(point) => {
let button_released = self.holding_mouse.unwrap_or_default();
match button_released {
HeldMouseButton::Left => {
self.dispatch_action(Action::LeftMouseRelease(point), None)
},
HeldMouseButton::Right => {
self.dispatch_action(Action::RightMouseRelease(point), None)
},
HeldMouseButton::Middle => {
self.dispatch_action(Action::MiddleMouseRelease(point), None)
},
};
self.holding_mouse = None;
MouseEventType::Release => {
// AZL TODO
/*
if buttons.left {
self.dispatch_action(Action::LeftMouseRelease(point), None);
} else if buttons.right {
self.dispatch_action(Action::RightMouseRelease(point), None);
} else if buttons.middle {
self.dispatch_action(Action::MiddleMouseRelease(point), None);
}
*/
},
MouseEvent::Hold(point) => {
let button_held = self.holding_mouse.unwrap_or_default();
match button_held {
HeldMouseButton::Left => {
self.dispatch_action(Action::MouseHoldLeft(point), None)
},
HeldMouseButton::Right => {
self.dispatch_action(Action::MouseHoldRight(point), None)
},
HeldMouseButton::Middle => {
self.dispatch_action(Action::MouseHoldMiddle(point), None)
},
};
self.holding_mouse = Some(button_held);
MouseEventType::Motion => {
// AZL TODO
},
}
}
Expand Down
85 changes: 85 additions & 0 deletions zellij-server/src/panes/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::{
use zellij_utils::{
consts::{DEFAULT_SCROLL_BUFFER_SIZE, SCROLL_BUFFER_SIZE},
data::{Palette, PaletteColor},
input::mouse::{MouseEvent, MouseEventType},
pane_size::SizeInPixels,
position::Position,
vte,
Expand Down Expand Up @@ -1921,6 +1922,90 @@ impl Grid {
}
}
}
fn mouse_buttons_value_x10(&self, event: &MouseEvent) -> u8 {
let mut value = 35; // Default to no buttons down.
if event.event_type == MouseEventType::Release {
return value;
}
if event.left {
value = 32;
} else if event.right {
value = 33;
} else if event.middle {
value = 34;
} else if event.wheel_up {
value = 68;
} else if event.wheel_down {
value = 69;
}
if event.event_type == MouseEventType::Motion {
value += 32;
}
if event.shift {
value |= 0x04;
}
if event.alt {
value |= 0x08;
}
if event.ctrl {
value |= 0x10;
}
value
}
fn mouse_buttons_value_sgr(&self, event: &MouseEvent) -> u8 {
let mut value = 3; // Default to no buttons down.
if event.left {
value = 0;
} else if event.right {
value = 1;
} else if event.middle {
value = 2;
} else if event.wheel_up {
value = 64;
} else if event.wheel_down {
value = 65;
}
if event.event_type == MouseEventType::Motion {
value += 32;
}
if event.shift {
value |= 0x04;
}
if event.alt {
value |= 0x08;
}
if event.ctrl {
value |= 0x10;
}
value
}
pub fn mouse_event_signal(&self, event: &MouseEvent) -> Option<String> {
match &self.mouse_mode {
MouseMode::NoEncoding | MouseMode::Utf8 => {
let mut msg: Vec<u8> = vec![27, b'[', b'M', self.mouse_buttons_value_x10(event)];
msg.append(&mut utf8_mouse_coordinates(
// AZL: Why is event.position not staying 0-based
// on both axes?
event.position.column(),
event.position.line() - 1,
));
Some(String::from_utf8_lossy(&msg).into())
},
MouseMode::Sgr => Some(format!(
"\u{1b}[<{:?};{:?};{:?}{}",
self.mouse_buttons_value_sgr(event),
// AZL: Why is event.position not staying 0-based on
// both axes?
event.position.column(),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that I missed the relative coordinate conversion in handle_mouse_event(). I'll fix that.

event.position.line() - 1,
match event.event_type {
MouseEventType::Press => 'M',
_ => 'm',
}
)),
_ => None,
}
}
pub fn mouse_left_click_signal(&self, position: &Position, is_held: bool) -> Option<String> {
let utf8_event = || -> Option<String> {
let button_code = if is_held { b'@' } else { b' ' };
Expand Down
5 changes: 5 additions & 0 deletions zellij-server/src/panes/terminal_pane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::fmt::Debug;
use std::rc::Rc;
use std::time::{self, Instant};
use zellij_utils::input::command::RunCommand;
use zellij_utils::input::mouse::MouseEvent;
use zellij_utils::pane_size::Offset;
use zellij_utils::{
data::{
Expand Down Expand Up @@ -629,6 +630,10 @@ impl Pane for TerminalPane {
self.exclude_from_sync
}

fn mouse_event(&self, event: &MouseEvent) -> Option<String> {
self.grid.mouse_event_signal(event)
}

fn mouse_left_click(&self, position: &Position, is_held: bool) -> Option<String> {
self.grid.mouse_left_click_signal(position, is_held)
}
Expand Down
37 changes: 10 additions & 27 deletions zellij-server/src/route.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,14 @@ pub(crate) fn route_action(
let mut should_break = false;
let err_context = || format!("failed to route action for client {client_id}");

// forward the action to plugins unless it is a mousehold
// this is a bit of a hack around the unfortunate architecture we use with plugins
// this will change as soon as we refactor
match action {
Action::MouseHoldLeft(..) | Action::MouseHoldRight(..) => {},
_ => {
senders
.send_to_plugin(PluginInstruction::Update(vec![(
None,
Some(client_id),
Event::InputReceived,
)]))
.with_context(err_context)?;
},
}
// forward the action to plugins
senders
.send_to_plugin(PluginInstruction::Update(vec![(
None,
Some(client_id),
Event::InputReceived,
)]))
.with_context(err_context)?;

match action {
Action::ToggleTab => {
Expand Down Expand Up @@ -635,19 +628,9 @@ pub(crate) fn route_action(
.send_to_screen(ScreenInstruction::MiddleMouseRelease(point, client_id))
.with_context(err_context)?;
},
Action::MouseHoldLeft(point) => {
senders
.send_to_screen(ScreenInstruction::MouseHoldLeft(point, client_id))
.with_context(err_context)?;
},
Action::MouseHoldRight(point) => {
senders
.send_to_screen(ScreenInstruction::MouseHoldRight(point, client_id))
.with_context(err_context)?;
},
Action::MouseHoldMiddle(point) => {
Action::MouseEvent(event) => {
senders
.send_to_screen(ScreenInstruction::MouseHoldMiddle(point, client_id))
.send_to_screen(ScreenInstruction::MouseEvent(event, client_id))
.with_context(err_context)?;
},
Action::Copy => {
Expand Down
23 changes: 5 additions & 18 deletions zellij-server/src/screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use zellij_utils::data::{
use zellij_utils::errors::prelude::*;
use zellij_utils::input::command::RunCommand;
use zellij_utils::input::keybinds::Keybinds;
use zellij_utils::input::mouse::MouseEvent;
use zellij_utils::input::options::Clipboard;
use zellij_utils::pane_size::{Size, SizeInPixels};
use zellij_utils::{
Expand Down Expand Up @@ -258,9 +259,7 @@ pub enum ScreenInstruction {
LeftMouseRelease(Position, ClientId),
RightMouseRelease(Position, ClientId),
MiddleMouseRelease(Position, ClientId),
MouseHoldLeft(Position, ClientId),
MouseHoldRight(Position, ClientId),
MouseHoldMiddle(Position, ClientId),
MouseEvent(MouseEvent, ClientId),
Copy(ClientId),
AddClient(
ClientId,
Expand Down Expand Up @@ -488,9 +487,7 @@ impl From<&ScreenInstruction> for ScreenContext {
ScreenInstruction::LeftMouseRelease(..) => ScreenContext::LeftMouseRelease,
ScreenInstruction::RightMouseRelease(..) => ScreenContext::RightMouseRelease,
ScreenInstruction::MiddleMouseRelease(..) => ScreenContext::MiddleMouseRelease,
ScreenInstruction::MouseHoldLeft(..) => ScreenContext::MouseHoldLeft,
ScreenInstruction::MouseHoldRight(..) => ScreenContext::MouseHoldRight,
ScreenInstruction::MouseHoldMiddle(..) => ScreenContext::MouseHoldMiddle,
ScreenInstruction::MouseEvent(..) => ScreenContext::MouseEvent,
ScreenInstruction::Copy(..) => ScreenContext::Copy,
ScreenInstruction::ToggleTab(..) => ScreenContext::ToggleTab,
ScreenInstruction::AddClient(..) => ScreenContext::AddClient,
Expand Down Expand Up @@ -3329,19 +3326,9 @@ pub(crate) fn screen_thread_main(
.handle_middle_mouse_release(&point, client_id), ?);
screen.render(None)?;
},
ScreenInstruction::MouseHoldLeft(point, client_id) => {
ScreenInstruction::MouseEvent(event, client_id) => {
active_tab!(screen, client_id, |tab: &mut Tab| tab
.handle_mouse_hold_left(&point, client_id), ?);
screen.render(None)?;
},
ScreenInstruction::MouseHoldRight(point, client_id) => {
active_tab!(screen, client_id, |tab: &mut Tab| tab
.handle_mouse_hold_right(&point, client_id), ?);
screen.render(None)?;
},
ScreenInstruction::MouseHoldMiddle(point, client_id) => {
active_tab!(screen, client_id, |tab: &mut Tab| tab
.handle_mouse_hold_middle(&point, client_id), ?);
.handle_mouse_event(&event, client_id), ?);
screen.render(None)?;
},
ScreenInstruction::Copy(client_id) => {
Expand Down
Loading
Loading