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

Merged
merged 185 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
185 commits
Select commit Hold shift + click to select a range
00bf961
Switch to multi-valued mouse buttons and stub for remembering old mou…
Aug 3, 2024
067d458
Stubs for passing all mouse events from user-facing terminal to server
Aug 6, 2024
774241a
'cargo xtask build' working using refactored functions.
AutumnMeowMeow Aug 29, 2024
7f3b521
fix(plugins): various cwd fixes (#3545)
imsnif Aug 7, 2024
56c6366
docs(changelog): floating_panes cwd fix
imsnif Aug 7, 2024
d8875b1
feat(plugins): rerun_command_pane API (#3546)
imsnif Aug 7, 2024
afd2645
docs(changelog): rerun command pane plugin API
imsnif Aug 7, 2024
8c1c485
feat(plugins): command pane re-run event (#3553)
imsnif Aug 14, 2024
6bdf0e4
docs(changelog): CommandPaneReRun plugin event
imsnif Aug 14, 2024
79679de
feat(ux): first run setup-wizard (#3556)
imsnif Aug 16, 2024
bbc750a
docs(changelog): first run setup wizard
imsnif Aug 16, 2024
fe5134f
feat(ux): reload config at runtime (#3558)
imsnif Aug 19, 2024
d1cc817
docs(changelog): reload config at runtime
imsnif Aug 19, 2024
fe2d46c
feat(ux): change themes at runtime (#3559)
imsnif Aug 20, 2024
8e175d3
docs(changelog): change themes at runtime
imsnif Aug 20, 2024
d63d302
feat(plugins): API to temporarily bind keys to send a message to a sp…
imsnif Aug 21, 2024
4c7d0a5
docs(changelog): message to specific plugins API
imsnif Aug 21, 2024
65fa396
feat(ux): reload config options at runtime (#3564)
imsnif Aug 23, 2024
95c9deb
docs(changelog): reload config options at runtime
imsnif Aug 23, 2024
e11a204
feat(plugins): add plugin APIs to affect other panes (#3576)
imsnif Aug 29, 2024
189ac2e
docs(changelog): new plugin apis
imsnif Aug 29, 2024
aa1c630
docs(readme): update sponsors
imsnif Sep 16, 2024
85981f2
feat(plugins): APIs to break multiple panes into a new tab or an exis…
imsnif Sep 16, 2024
d4d5203
docs(changelog): break multiple panes APIs
imsnif Sep 16, 2024
3d2947a
feat(config): allow loading background plugins on startup (#3616)
imsnif Sep 20, 2024
e25b1eb
docs(changelog): background plugins
imsnif Sep 20, 2024
0e56366
feat(ui): built-in plugin manager (#3633)
imsnif Sep 30, 2024
e2a4e7d
docs(changelog): plugin-manager
imsnif Sep 30, 2024
ea00e7d
fix(resurrection): various serialization issues (#3636)
imsnif Oct 2, 2024
6690b16
docs(changelog): resurrection fixes
imsnif Oct 2, 2024
c7baaf5
fix(http): web requests (#3643)
imsnif Oct 4, 2024
f457bb4
docs(changelog): http fix
imsnif Oct 4, 2024
eceb54a
feat(cli): make --layout idempotent(-ish) (#3650)
imsnif Oct 8, 2024
da596b3
docs(changelog): improve --layout flag
imsnif Oct 8, 2024
77acdb8
fix(plugins): handle race when setting plugin selectable (#3651)
imsnif Oct 9, 2024
8707e84
docs(changelog): plugin selectable race
imsnif Oct 9, 2024
2f9b9b0
feat(cli): show CACHE_DIR in `zellij setup --check` (#3652)
imsnif Oct 9, 2024
3775f70
docs(changelog): add cache dir to setup
imsnif Oct 9, 2024
c65eb3a
fix(ui): various pane name fixes (#3653)
imsnif Oct 9, 2024
d894436
docs(changelog): pane name fixes
imsnif Oct 9, 2024
d7b2074
fix(ux): only damage the relevant swap layout layer when resizing pan…
imsnif Oct 9, 2024
5348539
docs(changelog): swap layout damage fix
imsnif Oct 9, 2024
a0f647a
fix(ui): set background color for UI components according to theme (#…
imsnif Oct 10, 2024
953a8e7
docs(changelog): ui component fix
imsnif Oct 10, 2024
913e279
fix(tab): recover from crash when resizing panes (#3659)
imsnif Oct 10, 2024
77e91ce
chore(git): Add plugin’s issue templates (#3621)
Zykino Oct 10, 2024
3b55a47
fix(ux): make sure esc works as expected in unlock-first (#3660)
imsnif Oct 10, 2024
4e060a8
fix(plugins): handle concurrent http downloads (#3664)
imsnif Oct 11, 2024
71b77c9
docs(changelog): concurrent http plugin downloads
imsnif Oct 11, 2024
8de2fd9
fix(plugins): various plugin api and other fixes (#3665)
imsnif Oct 11, 2024
d3722f1
docs(changelog): plugin fixes
imsnif Oct 11, 2024
cd3f297
fix(plugins): force use curl system lib on macOS (#3668)
dj95 Oct 13, 2024
f75f97f
docs(changelog): fix http requests for macos
imsnif Oct 13, 2024
69cb49d
fix(resurrection): plugin alias resurrection (#3673)
imsnif Oct 14, 2024
ff7e45e
docs(changelog): resurrection alias fix
imsnif Oct 14, 2024
82df3c8
fix(plugins): do not allow attaching to the same session (#3674)
imsnif Oct 14, 2024
f612a27
docs(changelog): fix plugins attaching to same session
imsnif Oct 14, 2024
d18fa97
fix(plugins): allow switching to a new session with cwd without speci…
imsnif Oct 14, 2024
9739cde
docs(changelog): switch_session_with_cwd plugin api
imsnif Oct 14, 2024
b435a82
fix(config): watch/update config given with --config when appropriate…
imsnif Oct 14, 2024
c4b5d34
docs(changelog): reload config flag fix
imsnif Oct 14, 2024
7088d36
feat(plugins): rebind keys api (#3680)
imsnif Oct 15, 2024
d419e8a
docs(changelog): rebind keys plugin api
imsnif Oct 15, 2024
56258e6
fix(client): repeat retry screen instruction (#3570)
manueldeprada Oct 16, 2024
3c21afa
docs(changelog): sixel fix
imsnif Oct 16, 2024
e90a63a
feat(ui): rebind keys UI (#3686)
imsnif Oct 21, 2024
9d191bd
chore(deps): update to Wasmtime 21.0.2 (#3685)
bjorn3 Oct 21, 2024
d7d2cd1
docs(changelog): wasmtime patch upgrade
imsnif Oct 21, 2024
710b366
feat(plugins): add API to list clients, their focused panes and runni…
imsnif Oct 22, 2024
10c3daa
docs(changelog): list-clients plugin api
imsnif Oct 22, 2024
2159e96
docs(changelog): rebind keys UI
imsnif Oct 22, 2024
ad08615
feat(ui): bring back fullscreen indication (#3688)
imsnif Oct 22, 2024
cf9f6ba
docs(changelog): bring back fullscreen indication
imsnif Oct 22, 2024
b80b647
fix(ux): new interface/configuration touch-ups (#3691)
imsnif Oct 23, 2024
15fe4a7
docs(changelog): ui touch-ups
imsnif Oct 23, 2024
009a1c4
fix(plugins): rebind insert (#3692)
imsnif Oct 23, 2024
5393d77
docs(changelog): insert rebind
imsnif Oct 23, 2024
44cd865
fix(plugins): make sure to always render on first resize (#3693)
imsnif Oct 24, 2024
902676a
docs(changelog): plugins first-render fix
imsnif Oct 24, 2024
e9e3c8a
fix(terminal): recover from partial line drop (#3695)
imsnif Oct 24, 2024
a6d8ded
docs(changelog): grid fix
imsnif Oct 24, 2024
6597321
fix(configuration): leave notification up when base mode changes (#3696)
imsnif Oct 24, 2024
3021f16
fix(layouts): suspend commands in remote layouts (#3697)
imsnif Oct 24, 2024
2faf8ec
docs(changelog): suspend commands in remote layouts
imsnif Oct 24, 2024
0a501b0
feat(plugins): add configurable black background for ui components (#…
dj95 Oct 24, 2024
37561a1
style(fmt): various cleanups (#3698)
imsnif Oct 24, 2024
9240550
docs(changelog): ui components bg fix
imsnif Oct 24, 2024
1f9f8f8
feat(theme): add theme ao (#3478)
YardQuit Oct 25, 2024
e930105
feat(themes): add atelier sulphurpool theme (#3596)
achristmascarl Oct 25, 2024
4b30875
feat(themes): added ayu mirage, light, and dark themes (#3567)
Evthestrike Oct 25, 2024
42ef2bb
feat(themes): add Vesper theme (#3443)
rbardini Oct 25, 2024
e997757
feat(themes): add night-owl theme (#3393)
brunocmesquita Oct 25, 2024
9c06692
feat: add iceberg dark/light themes (#3323)
ufUNnxagpM Oct 25, 2024
14a8513
theme: add onedark theme to the available themes (#3313)
shonebinu Oct 25, 2024
f4b7c2c
feat(themes): add basic ANSI theme (#3308)
mikegreiling Oct 25, 2024
98eb4f6
fix(theme): fix for gruvbox light and dark (#3255)
uncomfyhalomacro Oct 25, 2024
da59279
feat(themes): create lucario.kdl (#3030)
ericraio Oct 25, 2024
f7051d7
docs(changelog): new themes
imsnif Oct 25, 2024
afdff1c
style(fmt): remove warnings (#3701)
imsnif Oct 25, 2024
879788a
fix: (tabs) move to next tab if moving to next pane from fullscreen p…
VasilisManol Oct 25, 2024
1a1aa31
docs(changelog): MoveFocusOrTab fullscreen awareness
imsnif Oct 25, 2024
dc0795f
docs(readme): add https to curl download
imsnif Oct 25, 2024
45eae2e
fix(ux): configuration fixes (#3713)
imsnif Oct 31, 2024
6b0bc68
docs(changelog): configuration fixes
imsnif Oct 31, 2024
83d7a4b
fix(ux): forward keys to pane in locked mode and base mode rather tha…
imsnif Oct 31, 2024
4bb36ec
docs(changelog): base mode keybindings fix
imsnif Oct 31, 2024
78a67cb
chore(release): v0.41.0
imsnif Nov 4, 2024
a0a7df2
HOTFIX: default plugins generic compilation issue
imsnif Nov 4, 2024
a2ee446
HOTFIX: patch version
imsnif Nov 4, 2024
5813651
chore(release): v0.41.1
imsnif Nov 4, 2024
11396eb
chore(repo): bump development version
imsnif Nov 5, 2024
41b75db
fix(input): remove support for extra modifiers (#3725)
imsnif Nov 5, 2024
a679857
docs(changelog): kitty input fix
imsnif Nov 5, 2024
98922dc
fix(input): refix ctrl-j (#3746)
imsnif Nov 8, 2024
f064c53
docs(changelog): refix ctrl-j
imsnif Nov 8, 2024
43dc486
fix(plugins): cwd and usability fixes (#3749)
imsnif Nov 8, 2024
8e77a4d
docs(changelog): plugin fixes
imsnif Nov 8, 2024
03ab277
fix(output-buffer): truncate grid height when not rendering it fully …
imsnif Nov 8, 2024
6eeef19
docs(changelog): output-buffer fix
imsnif Nov 8, 2024
ac3e113
fix(tabs): maintain event order for MoveTab (#3758)
imsnif Nov 11, 2024
5d9dddc
docs(changelog): event ordering fix
imsnif Nov 11, 2024
a6fffea
fix(plugins): do not open extra instances of aliases (#3759)
imsnif Nov 11, 2024
fe4fd6b
docs(changelog): do not duplicate built-in plugins
imsnif Nov 11, 2024
f02b731
fix(terminal): reset kitty keyboard support when resetting terminal s…
imsnif Nov 11, 2024
f0a391e
docs(changelog): kitty reset fix
imsnif Nov 11, 2024
2edce39
fix(config): crash if unable to watch config folder (#3761)
imsnif Nov 11, 2024
4bba5db
docs(changelog): config dir crash fix
imsnif Nov 11, 2024
c1d0a68
fix(statup): slow startup on some occasions (#3767)
imsnif Nov 13, 2024
d81a12c
docs(changelog): occasional slow startup fix
imsnif Nov 13, 2024
41802b6
fix(panes): handle various invalid state situations (#3776)
imsnif Nov 15, 2024
6c0e0bc
docs(changelog): invalid state handling
imsnif Nov 15, 2024
b25f48d
chore: add vendored_curl feature (#3766)
tranzystorekk Nov 15, 2024
5bfaecf
docs(changelog): vendored curl option
imsnif Nov 15, 2024
8431fe0
fix(ux): change plugin manager shortcut (#3779)
imsnif Nov 15, 2024
b491cd7
docs(changelog): shortcut change
imsnif Nov 15, 2024
a6d0845
fix(screen): send PaneClosed event to plugins also when closing the w…
imsnif Nov 15, 2024
8bb81af
docs(changelog): pane-closed event
imsnif Nov 15, 2024
c46830e
feat(plugins): add /cache folder (#3787)
imsnif Nov 18, 2024
4c8cc1b
docs(changelog): plugin cache folder
imsnif Nov 18, 2024
40415d4
docs(changelog): plugin cache folder url
imsnif Nov 18, 2024
77eb5aa
chore(package): vendor common_path (#3780)
s1syph0s Nov 19, 2024
6c2b52a
docs(changelog): vendor common_path
imsnif Nov 19, 2024
3981852
fix(plugins): derive hash and ord for PaneId (#3790)
imsnif Nov 19, 2024
0bc254c
docs(changelog): derive hash and ord for paneid
imsnif Nov 19, 2024
131f9c5
style(fmt): remove warnings
imsnif Nov 19, 2024
0491b70
chore(version): set patch version
imsnif Nov 19, 2024
8148ddb
chore(release): v0.41.2
imsnif Nov 19, 2024
0fbe208
chore(repo): bump development version
imsnif Nov 19, 2024
c23758e
chore(repo): fix typo in lock file
imsnif Nov 19, 2024
f5ec873
fix(plugins): properly focus pane after tab was closed (#3797)
imsnif Nov 21, 2024
320819b
docs(changelog): focus_pane_with_id fix
imsnif Nov 21, 2024
813dbbb
fix(plugins): properly pad UI elements when they have a background (#…
imsnif Nov 24, 2024
f6f54e4
docs(changelog): ui component padding
imsnif Nov 24, 2024
c95f125
feat(plugins): allow changing the plugin's `/host` folder (under a ne…
imsnif Dec 1, 2024
d843ef9
docs(changelog): allow plugins to change host folder
imsnif Dec 1, 2024
138627f
chore(repo): add funding.json (#3838)
imsnif Dec 5, 2024
6ffc960
fix(plugins): do not detach if using a slash in a session name (#3839)
imsnif Dec 6, 2024
4588558
docs(changelog): slash detach fix
imsnif Dec 6, 2024
7440461
fix(plugins): properly focus plugin after it was hidden (#3841)
imsnif Dec 6, 2024
6d3df8d
docs(changelog): plugin hidden focus fix
imsnif Dec 6, 2024
c481fc3
fix(screen): off by 1 error when focusing layout tab (#3844)
imsnif Dec 6, 2024
07155a5
docs(changelog): layout tab focus fix
imsnif Dec 6, 2024
09df95b
fix(multiuser): properly clear fake cursors (#3845)
imsnif Dec 6, 2024
b13b358
docs(changelog): multiplayer cursor fix
imsnif Dec 6, 2024
d49b12f
feat(ux): pin floating panes (#3876)
imsnif Dec 16, 2024
851cef8
docs(changelog): pin floating panes
imsnif Dec 16, 2024
e6f2eb5
fix(layout-applier): logical index pane sorting (#3893)
imsnif Dec 25, 2024
ccf7f11
docs(changelog): logical index pane sorting
imsnif Dec 25, 2024
c67d909
fix(terminal): mode 2026 feature detection response (#3884)
darrenburns Dec 26, 2024
7ea8d02
docs(changelog): synchronized rendering query response
imsnif Dec 26, 2024
4210196
fix(terminal): cursor overflow (#3894)
imsnif Dec 26, 2024
008749e
docs(changelog): cursor overflow fix
imsnif Dec 26, 2024
0d5c8ce
Merge branch 'main' into AutumnMeowMeow-mouse-anyevent
imsnif Dec 31, 2024
f7a5115
fix(ux): make the Zellij mouse interaction work
imsnif Jan 9, 2025
3432226
fix(rendering): only render if selection/floating-pane position was c…
imsnif Jan 11, 2025
a90e9a9
do not clear copied to clipboard message on mouse motion
imsnif Jan 13, 2025
3eb026d
various functionality fixes
imsnif Jan 13, 2025
e6f7a24
fix tests
imsnif Jan 13, 2025
b43e7c7
fixes and cleanups
imsnif Jan 13, 2025
549dd03
style(fmt): rustfmt
imsnif Jan 13, 2025
e32e4da
fix(mouse): only report state to plugins when it changed
imsnif Jan 14, 2025
f8ee0f3
fix(plugins): send mouse clicks to inactive panes
imsnif Jan 14, 2025
c192cba
tests: any event tracking in panes
imsnif Jan 14, 2025
bf83a51
style(fmt): rustfmt
imsnif Jan 14, 2025
6d2b8eb
style: remove unused stuff
imsnif Jan 14, 2025
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
108 changes: 33 additions & 75 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::{MouseButtons, MouseEvent},
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_buttons: MouseButtons,
mouse_mode_active: bool,
}

Expand All @@ -67,7 +54,13 @@ impl InputHandler {
send_client_instructions,
should_exit: false,
receive_input_instructions,
holding_mouse: None,
mouse_buttons: MouseButtons {
left: false,
right: false,
middle: false,
wheel_up: false,
wheel_down: false,
},
mouse_mode_active: false,
}
}
Expand Down Expand Up @@ -99,8 +92,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(
self.mouse_buttons,
mouse_event,
);
self.handle_mouse_event(&mouse_event);
},
InputEvent::Paste(pasted_text) => {
Expand Down Expand Up @@ -216,67 +211,30 @@ impl InputHandler {
}
fn handle_mouse_event(&mut self, mouse_event: &MouseEvent) {
match *mouse_event {
MouseEvent::Press(button, point) => match button {
MouseButton::WheelUp => {
MouseEvent::Press(buttons, point) => {
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;
MouseEvent::Release(buttons, point) => {
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);
MouseEvent::Motion(buttons, point) => {
// AZL TODO
},
}
}
Expand Down
167 changes: 100 additions & 67 deletions zellij-utils/src/input/mouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,102 +2,135 @@ use serde::{Deserialize, Serialize};

use crate::position::Position;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Deserialize, Serialize)]
/// A mouse event can have any number of buttons (including no
/// buttons) pressed or released.
pub struct MouseButtons {
pub left: bool,
pub right: bool,
pub middle: bool,
pub wheel_up: bool,
pub wheel_down: bool,
}

/// 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),
Press(MouseButtons, Position),
/// A mouse button was released.
///
/// The coordinates are zero-based.
Release(Position),
Release(MouseButtons, Position),
/// A mouse button is held over the given coordinates.
///
/// The coordinates are zero-based.
Hold(Position),
Motion(MouseButtons, Position),
}

impl From<termwiz::input::MouseEvent> for MouseEvent {
fn from(event: termwiz::input::MouseEvent) -> Self {
#[allow(clippy::if_same_then_else)]
if event
.mouse_buttons
.contains(termwiz::input::MouseButtons::LEFT)
impl MouseButtons {
fn termwiz_mouse_buttons(mut self, button_bits: &termwiz::input::MouseButtons) -> MouseButtons {
self.left = button_bits.contains(termwiz::input::MouseButtons::LEFT);
self.right = button_bits.contains(termwiz::input::MouseButtons::RIGHT);
self.middle = button_bits.contains(termwiz::input::MouseButtons::MIDDLE);
self.wheel_up = button_bits.contains(termwiz::input::MouseButtons::VERT_WHEEL)
&& button_bits.contains(termwiz::input::MouseButtons::WHEEL_POSITIVE);
self.wheel_down = button_bits.contains(termwiz::input::MouseButtons::VERT_WHEEL)
&& !button_bits.contains(termwiz::input::MouseButtons::WHEEL_POSITIVE);

self
}
}

impl MouseEvent {
#[allow(unused)]
pub fn from_termwiz(mut old_buttons: MouseButtons, event: termwiz::input::MouseEvent) -> Self {
// We use the state of old_buttons vs new_buttons to determine
// if this event is a Press, Release, or Motion. This is an
// unfortunate side effect of the pre-SGR-encoded X10 mouse
// protocol design in which release events don't carry
// information about WHICH button(s) were released, so we have
// to maintain a wee bit of state in between events.
Copy link
Member

Choose a reason for hiding this comment

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

Honestly, even this is much better than what we've been doing up until now with the HeldMouse stuff.

//
// Note that only Left, Right, and Middle are saved in between
// calls. WheelUp/WheelDown typically do not generate Release
// events.
let mut new_buttons = MouseButtons::termwiz_mouse_buttons(
MouseButtons {
left: false,
right: false,
middle: false,
wheel_up: false,
wheel_down: false,
},
&event.mouse_buttons,
);

if (new_buttons.left && !old_buttons.left)
|| (new_buttons.right && !old_buttons.right)
|| (new_buttons.middle && !old_buttons.middle)
|| new_buttons.wheel_up
|| new_buttons.wheel_down
{
// This is a mouse Press event. Hang onto the button state.
old_buttons = new_buttons;
MouseEvent::Press(
MouseButton::Left,
new_buttons,
Position::new(event.y.saturating_sub(1) as i32, event.x.saturating_sub(1)),
)
} else if event
.mouse_buttons
.contains(termwiz::input::MouseButtons::RIGHT)
.contains(termwiz::input::MouseButtons::NONE)
&& !old_buttons.left
&& !old_buttons.right
&& !old_buttons.middle
{
MouseEvent::Press(
MouseButton::Right,
// This is a mouse Motion event (no buttons are down).
old_buttons = new_buttons;
MouseEvent::Motion(
new_buttons,
Position::new(event.y.saturating_sub(1) as i32, event.x.saturating_sub(1)),
)
} else if event
.mouse_buttons
.contains(termwiz::input::MouseButtons::MIDDLE)
.contains(termwiz::input::MouseButtons::NONE)
&& (old_buttons.left || old_buttons.right || old_buttons.middle)
{
MouseEvent::Press(
MouseButton::Middle,
// This is a mouse Release event. Note that we set
// old_buttons to false (to release), but set ONLY the
// new_buttons that were released to true before sending
// the event up.
if old_buttons.left {
old_buttons.left = false;
new_buttons.left = true;
}
if old_buttons.right {
old_buttons.right = false;
new_buttons.right = true;
}
if old_buttons.middle {
old_buttons.middle = false;
new_buttons.middle = true;
}

MouseEvent::Release(
new_buttons,
Position::new(event.y.saturating_sub(1) as i32, event.x.saturating_sub(1)),
)
} else if event
.mouse_buttons
.contains(termwiz::input::MouseButtons::VERT_WHEEL)
{
if event
.mouse_buttons
.contains(termwiz::input::MouseButtons::WHEEL_POSITIVE)
{
MouseEvent::Press(
MouseButton::WheelUp,
Position::new(event.y.saturating_sub(1) as i32, event.x.saturating_sub(1)),
)
} else {
MouseEvent::Press(
MouseButton::WheelDown,
Position::new(event.y.saturating_sub(1) as i32, event.x.saturating_sub(1)),
)
}
} else if event
.mouse_buttons
.contains(termwiz::input::MouseButtons::NONE)
{
// release
MouseEvent::Release(Position::new(
event.y.saturating_sub(1) as i32,
event.x.saturating_sub(1),
))
} else {
// this is an unsupported event, we just do this in order to send "something", but if
// something happens here, we might want to add more specific support
MouseEvent::Release(Position::new(
event.y.saturating_sub(1) as i32,
event.x.saturating_sub(1),
))
// Unrecognized mouse state. Return it as a blank Motion event.
MouseEvent::Motion(
MouseButtons {
left: false,
right: false,
middle: false,
wheel_up: false,
wheel_down: false,
},
Position::new(event.y.saturating_sub(1) as i32, event.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,
}
Loading