Skip to content

Commit

Permalink
'cargo xtask build' working using refactored functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
AutumnMeowMeow committed Aug 29, 2024
1 parent 067d458 commit 774241a
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 112 deletions.
90 changes: 85 additions & 5 deletions zellij-client/src/input_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ use zellij_utils::{
options::Options,
},
ipc::{ClientToServerMsg, ExitReason},
termwiz::input::InputEvent,
position::Position,
termwiz::input::{InputEvent, Modifiers, MouseButtons, MouseEvent as TermwizMouseEvent},
};

/// Handles the dispatching of [`Action`]s according to the current
Expand All @@ -34,6 +35,88 @@ struct InputHandler {
mouse_mode_active: bool,
}

fn termwiz_mouse_convert(original_event: &mut MouseEvent, event: &TermwizMouseEvent) {
let button_bits = &event.mouse_buttons;
original_event.left = button_bits.contains(MouseButtons::LEFT);
original_event.right = button_bits.contains(MouseButtons::RIGHT);
original_event.middle = button_bits.contains(MouseButtons::MIDDLE);
original_event.wheel_up = button_bits.contains(MouseButtons::VERT_WHEEL)
&& button_bits.contains(MouseButtons::WHEEL_POSITIVE);
original_event.wheel_down = button_bits.contains(MouseButtons::VERT_WHEEL)
&& !button_bits.contains(MouseButtons::WHEEL_POSITIVE);

let mods = &event.modifiers;
original_event.shift = mods.contains(Modifiers::SHIFT);
original_event.alt = mods.contains(Modifiers::ALT);
original_event.ctrl = mods.contains(Modifiers::CTRL);
}

fn from_termwiz(old_event: &mut MouseEvent, event: TermwizMouseEvent) -> MouseEvent {
// We use the state of old_event vs new_event 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.
//
// Note that only Left, Right, and Middle are saved in between
// calls. WheelUp/WheelDown typically do not generate Release
// events.
let mut new_event = MouseEvent::new();
termwiz_mouse_convert(&mut new_event, &event);
new_event.position = Position::new(event.y.saturating_sub(1) as i32, event.x.saturating_sub(1));

if (new_event.left && !old_event.left)
|| (new_event.right && !old_event.right)
|| (new_event.middle && !old_event.middle)
|| new_event.wheel_up
|| new_event.wheel_down
{
// This is a mouse Press event.
new_event.event_type = MouseEventType::Press;

// Hang onto the button state.
*old_event = new_event;
} else if event.mouse_buttons.is_empty()
&& !old_event.left
&& !old_event.right
&& !old_event.middle
{
// This is a mouse Motion event (no buttons are down).
new_event.event_type = MouseEventType::Motion;

// Hang onto the button state.
*old_event = new_event;
} else if event.mouse_buttons.is_empty()
&& (old_event.left || old_event.right || old_event.middle)
{
// This is a mouse Release event. Note that we set
// old_event.{button} to false (to release), but set ONLY the
// new_event that were released to true before sending the
// event up.
if old_event.left {
old_event.left = false;
new_event.left = true;
}
if old_event.right {
old_event.right = false;
new_event.right = true;
}
if old_event.middle {
old_event.middle = false;
new_event.middle = true;
}
new_event.event_type = MouseEventType::Release;
} else {
// Dragging with some button down. Return it as a Motion
// event, and hang on to the button state.
new_event.event_type = MouseEventType::Motion;
*old_event = new_event;
}

new_event
}

impl InputHandler {
/// Returns a new [`InputHandler`] with the attributes specified as arguments.
fn new(
Expand Down Expand Up @@ -86,10 +169,7 @@ impl InputHandler {
self.handle_key(&key, raw_bytes, false);
},
InputEvent::Mouse(mouse_event) => {
let mouse_event = zellij_utils::input::mouse::MouseEvent::from_termwiz(
&mut self.mouse_old_event,
mouse_event,
);
let mouse_event = from_termwiz(&mut self.mouse_old_event, mouse_event);
self.handle_mouse_event(&mouse_event);
},
InputEvent::Paste(pasted_text) => {
Expand Down
6 changes: 4 additions & 2 deletions zellij-client/src/os_input_output.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ use zellij_utils::{

const SIGWINCH_CB_THROTTLE_DURATION: time::Duration = time::Duration::from_millis(50);

const ENABLE_MOUSE_SUPPORT: &str = "\u{1b}[?1000h\u{1b}[?1002h\u{1b}[?1015h\u{1b}[?1006h";
const DISABLE_MOUSE_SUPPORT: &str = "\u{1b}[?1006l\u{1b}[?1015l\u{1b}[?1002l\u{1b}[?1000l";
const ENABLE_MOUSE_SUPPORT: &str =
"\u{1b}[?1000h\u{1b}[?1002h\u{1b}[?1003h\u{1b}[?1015h\u{1b}[?1006h";
const DISABLE_MOUSE_SUPPORT: &str =
"\u{1b}[?1006l\u{1b}[?1015l\u{1b}[?1003l\u{1b}[?1002l\u{1b}[?1000l";

fn into_raw_mode(pid: RawFd) {
let mut tio = termios::tcgetattr(pid).expect("could not get terminal attribute");
Expand Down
35 changes: 21 additions & 14 deletions zellij-server/src/panes/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,7 @@ pub enum MouseTracking {
Off,
Normal,
ButtonEventTracking,
AnyEventTracking,
}

impl Default for MouseTracking {
Expand Down Expand Up @@ -1980,30 +1981,36 @@ impl Grid {
value
}
pub fn mouse_event_signal(&self, event: &MouseEvent) -> Option<String> {
match &self.mouse_mode {
MouseMode::NoEncoding | MouseMode::Utf8 => {
let emit = match (&self.mouse_tracking, event.event_type) {
(MouseTracking::Off, _) => false,
(MouseTracking::AnyEventTracking, _) => true,
(_, MouseEventType::Press | MouseEventType::Release) => true,
(MouseTracking::ButtonEventTracking, MouseEventType::Motion) => {
event.left | event.right | event.middle | event.wheel_up | event.wheel_down
},
(_, _) => false,
};

match (emit, &self.mouse_mode) {
(true, 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,
event.position.column() + 1,
event.position.line() + 1,
));
Some(String::from_utf8_lossy(&msg).into())
},
MouseMode::Sgr => Some(format!(
(true, 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(),
event.position.line() - 1,
event.position.column() + 1,
event.position.line() + 1,
match event.event_type {
MouseEventType::Press => 'M',
_ => 'm',
}
)),
_ => None,
(_, _) => None,
}
}
pub fn mouse_left_click_signal(&self, position: &Position, is_held: bool) -> Option<String> {
Expand Down Expand Up @@ -2675,7 +2682,7 @@ impl Perform for Grid {
self.mouse_tracking = MouseTracking::Off;
},
1003 => {
// TBD: any-even mouse tracking
self.mouse_tracking = MouseTracking::Off;
},
1004 => {
self.focus_event_tracking = false;
Expand Down Expand Up @@ -2778,7 +2785,7 @@ impl Perform for Grid {
self.mouse_tracking = MouseTracking::ButtonEventTracking;
},
1003 => {
// TBD: any-even mouse tracking
self.mouse_tracking = MouseTracking::AnyEventTracking;
},
1004 => {
self.focus_event_tracking = true;
Expand Down
14 changes: 12 additions & 2 deletions zellij-server/src/tab/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3023,9 +3023,19 @@ impl Tab {
|| format!("failed to handle mouse event {event:?} for client {client_id}");
let active_pane = self.get_active_pane_or_floating_pane_mut(client_id);
if let Some(active_pane) = active_pane {
if let Some(mouse_event) = active_pane.mouse_event(&event) {
self.write_to_active_terminal(&None, mouse_event.into_bytes(), false, client_id)
let relative_position = active_pane.relative_position(&event.position);
let mut pass_event = *event;
pass_event.position = relative_position;
if let Some(mouse_event) = active_pane.mouse_event(&pass_event) {
if !active_pane.position_is_on_frame(&event.position) {
self.write_to_active_terminal(
&None,
mouse_event.into_bytes(),
false,
client_id,
)
.with_context(err_context)?;
}
}
}
Ok(())
Expand Down
5 changes: 1 addition & 4 deletions zellij-utils/src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,12 @@ pub mod command;
pub mod config;
pub mod keybinds;
pub mod layout;
pub mod mouse;
pub mod options;
pub mod permission;
pub mod plugins;
pub mod theme;

// Can't use this in wasm due to dependency on the `termwiz` crate.
#[cfg(not(target_family = "wasm"))]
pub mod mouse;

#[cfg(not(target_family = "wasm"))]
pub use not_wasm::*;

Expand Down
85 changes: 0 additions & 85 deletions zellij-utils/src/input/mouse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,89 +59,4 @@ impl MouseEvent {

event
}

fn termwiz_mouse_convert(&mut self, event: &termwiz::input::MouseEvent) {
let button_bits = &event.mouse_buttons;
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);

let mods = &event.modifiers;
self.shift = mods.contains(termwiz::input::Modifiers::SHIFT);
self.alt = mods.contains(termwiz::input::Modifiers::ALT);
self.ctrl = mods.contains(termwiz::input::Modifiers::CTRL);
}

pub fn from_termwiz(old_event: &mut MouseEvent, event: termwiz::input::MouseEvent) -> Self {
// We use the state of old_event vs new_event 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.
//
// Note that only Left, Right, and Middle are saved in between
// calls. WheelUp/WheelDown typically do not generate Release
// events.
let mut new_event = MouseEvent::new();
new_event.termwiz_mouse_convert(&event);
new_event.position =
Position::new(event.y.saturating_sub(1) as i32, event.x.saturating_sub(1));

if (new_event.left && !old_event.left)
|| (new_event.right && !old_event.right)
|| (new_event.middle && !old_event.middle)
|| new_event.wheel_up
|| new_event.wheel_down
{
// This is a mouse Press event.
new_event.event_type = MouseEventType::Press;

// Hang onto the button state.
*old_event = new_event;
} else if event
.mouse_buttons
.contains(termwiz::input::MouseButtons::NONE)
&& !old_event.left
&& !old_event.right
&& !old_event.middle
{
// This is a mouse Motion event (no buttons are down).
new_event.event_type = MouseEventType::Motion;

// Hang onto the button state.
*old_event = new_event;
} else if event
.mouse_buttons
.contains(termwiz::input::MouseButtons::NONE)
&& (old_event.left || old_event.right || old_event.middle)
{
// This is a mouse Release event. Note that we set
// old_event.{button} to false (to release), but set ONLY
// the new_event that were released to true before sending
// the event up.
if old_event.left {
old_event.left = false;
new_event.left = true;
}
if old_event.right {
old_event.right = false;
new_event.right = true;
}
if old_event.middle {
old_event.middle = false;
new_event.middle = true;
}
new_event.event_type = MouseEventType::Release;
} else {
// Unrecognized mouse state. Return it as a blank Motion event.
new_event.event_type = MouseEventType::Motion;
}

new_event
}
}

0 comments on commit 774241a

Please sign in to comment.