diff options
Diffstat (limited to 'zellij-server/src/tab/mod.rs')
-rw-r--r-- | zellij-server/src/tab/mod.rs | 256 |
1 files changed, 201 insertions, 55 deletions
diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index 44c2a480f..750f49447 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -296,8 +296,32 @@ pub trait Pane { fn load_pane_name(&mut self); fn set_borderless(&mut self, borderless: bool); fn borderless(&self) -> bool; + // TODO: this should probably be merged with the mouse_right_click fn handle_right_click(&mut self, _to: &Position, _client_id: ClientId) {} - fn mouse_mode(&self) -> bool; + fn mouse_left_click(&self, _position: &Position, _is_held: bool) -> Option<String> { + None + } + fn mouse_left_click_release(&self, _position: &Position) -> Option<String> { + None + } + fn mouse_right_click(&self, _position: &Position, _is_held: bool) -> Option<String> { + None + } + fn mouse_right_click_release(&self, _position: &Position) -> Option<String> { + None + } + fn mouse_middle_click(&self, _position: &Position, _is_held: bool) -> Option<String> { + None + } + fn mouse_middle_click_release(&self, _position: &Position) -> Option<String> { + None + } + fn mouse_scroll_up(&self, _position: &Position) -> Option<String> { + None + } + fn mouse_scroll_down(&self, _position: &Position) -> Option<String> { + None + } fn get_line_number(&self) -> Option<usize> { None } @@ -1668,13 +1692,8 @@ impl Tab { } pub fn scroll_terminal_up(&mut self, point: &Position, lines: usize, client_id: ClientId) { if let Some(pane) = self.get_pane_at(point, false) { - if pane.mouse_mode() { - let relative_position = pane.relative_position(point); - let mouse_event = format!( - "\u{1b}[<64;{:?};{:?}M", - relative_position.column.0 + 1, - relative_position.line.0 + 1 - ); + let relative_position = pane.relative_position(point); + if let Some(mouse_event) = pane.mouse_scroll_up(&relative_position) { self.write_to_terminal_at(mouse_event.into_bytes(), point); } else { pane.scroll_up(lines, client_id); @@ -1683,13 +1702,8 @@ impl Tab { } pub fn scroll_terminal_down(&mut self, point: &Position, lines: usize, client_id: ClientId) { if let Some(pane) = self.get_pane_at(point, false) { - if pane.mouse_mode() { - let relative_position = pane.relative_position(point); - let mouse_event = format!( - "\u{1b}[<65;{:?};{:?}M", - relative_position.column.0 + 1, - relative_position.line.0 + 1 - ); + let relative_position = pane.relative_position(point); + if let Some(mouse_event) = pane.mouse_scroll_down(&relative_position) { self.write_to_terminal_at(mouse_event.into_bytes(), point); } else { pane.scroll_down(lines, client_id); @@ -1755,18 +1769,11 @@ impl Tab { if let Some(pane) = self.get_pane_at(position, false) { let relative_position = pane.relative_position(position); - - if pane.mouse_mode() { + if let Some(mouse_event) = pane.mouse_left_click(&relative_position, false) { 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); if let PaneId::Terminal(_) = pane.pid() { self.selecting_with_mouse = true; @@ -1779,13 +1786,8 @@ impl Tab { if let Some(pane) = self.get_pane_at(position, false) { let relative_position = pane.relative_position(position); - if pane.mouse_mode() { + if let Some(mouse_event) = pane.mouse_right_click(&relative_position, false) { 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 { @@ -1793,6 +1795,18 @@ impl Tab { } }; } + pub fn handle_middle_click(&mut self, position: &Position, client_id: ClientId) { + self.focus_pane_at(position, client_id); + + if let Some(pane) = self.get_pane_at(position, false) { + let relative_position = pane.relative_position(position); + if let Some(mouse_event) = pane.mouse_middle_click(&relative_position, false) { + if !pane.position_is_on_frame(position) { + self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + } + } + }; + } fn focus_pane_at(&mut self, point: &Position, client_id: ClientId) { if self.floating_panes.panes_are_visible() { if let Some(clicked_pane) = self.floating_panes.get_pane_id_at(point, true) { @@ -1810,7 +1824,51 @@ impl Tab { } } } - pub fn handle_mouse_release(&mut self, position: &Position, client_id: ClientId) { + pub fn handle_right_mouse_release(&mut self, position: &Position, client_id: ClientId) { + self.last_mouse_hold_position = None; + let active_pane = self.get_active_pane_or_floating_pane_mut(client_id); + if let Some(active_pane) = active_pane { + let mut relative_position = active_pane.relative_position(position); + relative_position.change_column( + (relative_position.column()) + .max(0) + .min(active_pane.get_content_columns()), + ); + + relative_position.change_line( + (relative_position.line()) + .max(0) + .min(active_pane.get_content_rows() as isize), + ); + + if let Some(mouse_event) = active_pane.mouse_right_click_release(&relative_position) { + self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + } + } + } + pub fn handle_middle_mouse_release(&mut self, position: &Position, client_id: ClientId) { + self.last_mouse_hold_position = None; + let active_pane = self.get_active_pane_or_floating_pane_mut(client_id); + if let Some(active_pane) = active_pane { + let mut relative_position = active_pane.relative_position(position); + relative_position.change_column( + (relative_position.column()) + .max(0) + .min(active_pane.get_content_columns()), + ); + + relative_position.change_line( + (relative_position.line()) + .max(0) + .min(active_pane.get_content_rows() as isize), + ); + + if let Some(mouse_event) = active_pane.mouse_middle_click_release(&relative_position) { + self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + } + } + } + pub fn handle_left_mouse_release(&mut self, position: &Position, client_id: ClientId) { self.last_mouse_hold_position = None; if self.floating_panes.panes_are_visible() @@ -1826,20 +1884,23 @@ impl Tab { let active_pane = self.get_active_pane_or_floating_pane_mut(client_id); if let Some(active_pane) = active_pane { - let relative_position = active_pane.relative_position(position); - if active_pane.mouse_mode() { - // ensure that coordinates are valid - let col = (relative_position.column() + 1) - .max(1) - .min(active_pane.get_content_columns()); - - 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); + let mut relative_position = active_pane.relative_position(position); + relative_position.change_column( + (relative_position.column()) + .max(0) + .min(active_pane.get_content_columns()), + ); + + relative_position.change_line( + (relative_position.line()) + .max(0) + .min(active_pane.get_content_rows() as isize), + ); + + if let Some(mouse_event) = active_pane.mouse_left_click_release(&relative_position) { self.write_to_active_terminal(mouse_event.into_bytes(), client_id); } else { - // TODO: rename this method, it is used to forward release events to plugin panes + let relative_position = active_pane.relative_position(position); if let PaneId::Terminal(_) = active_pane.pid() { if selecting && copy_on_release { active_pane.end_selection(&relative_position, client_id); @@ -1858,7 +1919,7 @@ impl Tab { } } } - pub fn handle_mouse_hold( + pub fn handle_mouse_hold_left( &mut self, position_on_screen: &Position, client_id: ClientId, @@ -1889,20 +1950,24 @@ impl Tab { let active_pane = self.get_active_pane_or_floating_pane_mut(client_id); if let Some(active_pane) = active_pane { - let relative_position = active_pane.relative_position(position_on_screen); - if active_pane.mouse_mode() && !is_repeated { + let mut relative_position = active_pane.relative_position(position_on_screen); + if !is_repeated { // ensure that coordinates are valid - let col = (relative_position.column() + 1) - .max(1) - .min(active_pane.get_content_columns()); - - let line = (relative_position.line() + 1) - .max(1) - .min(active_pane.get_content_rows() as isize); + relative_position.change_column( + (relative_position.column()) + .max(0) + .min(active_pane.get_content_columns()), + ); - let mouse_event = format!("\u{1b}[<32;{:?};{:?}M", col, line); - self.write_to_active_terminal(mouse_event.into_bytes(), client_id); - return true; // we need to re-render in this case so the selection disappears + relative_position.change_line( + (relative_position.line()) + .max(0) + .min(active_pane.get_content_rows() as isize), + ); + if let Some(mouse_event) = active_pane.mouse_left_click(&relative_position, true) { + self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + return true; // we need to re-render in this case so the selection disappears + } } else if selecting { active_pane.update_selection(&relative_position, client_id); return true; // we need to re-render in this case so the selection is updated @@ -1910,6 +1975,87 @@ impl Tab { } false // we shouldn't even get here, but might as well not needlessly render if we do } + pub fn handle_mouse_hold_right( + &mut self, + position_on_screen: &Position, + client_id: ClientId, + ) -> bool { + // return value indicates whether we should trigger a render + // 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 active_pane = self.get_active_pane_or_floating_pane_mut(client_id); + + if let Some(active_pane) = active_pane { + let mut relative_position = active_pane.relative_position(position_on_screen); + if !is_repeated { + relative_position.change_column( + (relative_position.column()) + .max(0) + .min(active_pane.get_content_columns()), + ); + + relative_position.change_line( + (relative_position.line()) + .max(0) + .min(active_pane.get_content_rows() as isize), + ); + if let Some(mouse_event) = active_pane.mouse_right_click(&relative_position, true) { + self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + return true; // we need to re-render in this case so the selection disappears + } + } + } + false // we shouldn't even get here, but might as well not needlessly render if we do + } + pub fn handle_mouse_hold_middle( + &mut self, + position_on_screen: &Position, + client_id: ClientId, + ) -> bool { + println!("mouse hold middle"); + // return value indicates whether we should trigger a render + // 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 + }; + println!("is repeated: {:?}", is_repeated); + self.last_mouse_hold_position = Some(*position_on_screen); + + let active_pane = self.get_active_pane_or_floating_pane_mut(client_id); + + if let Some(active_pane) = active_pane { + println!("can have active pane"); + let mut relative_position = active_pane.relative_position(position_on_screen); + if !is_repeated { + relative_position.change_column( + (relative_position.column()) + .max(0) + .min(active_pane.get_content_columns()), + ); + + relative_position.change_line( + (relative_position.line()) + .max(0) + .min(active_pane.get_content_rows() as isize), + ); + if let Some(mouse_event) = active_pane.mouse_middle_click(&relative_position, true) + { + log::info!("can have mouse event: {:?}", mouse_event); + self.write_to_active_terminal(mouse_event.into_bytes(), client_id); + return true; // we need to re-render in this case so the selection disappears + } + } + } + false // we shouldn't even get here, but might as well not needlessly render if we do + } pub fn copy_selection(&self, client_id: ClientId) { let selected_text = self |