aboutsummaryrefslogtreecommitdiff
path: root/src/app/input/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/input/mod.rs')
-rw-r--r--src/app/input/mod.rs74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/app/input/mod.rs b/src/app/input/mod.rs
index 421b3738..21e9a49b 100644
--- a/src/app/input/mod.rs
+++ b/src/app/input/mod.rs
@@ -1,6 +1,8 @@
//! Input handling — translates crossterm key/mouse events into state mutations.
+use bytes::Bytes;
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind};
+use tracing::warn;
use crate::app::PaneClickState;
use crate::input::TerminalKey;
@@ -70,6 +72,10 @@ use super::App;
impl App {
pub(super) async fn handle_key(&mut self, key: TerminalKey) {
+ if self.state.popup_pane.is_some() {
+ self.handle_terminal_key(key).await;
+ return;
+ }
let key_event = key.as_key_event();
if modal_paste_target_active(&self.state) && is_modal_paste_shortcut(&key_event) {
if let Some(text) = crate::platform::read_clipboard_text() {
@@ -111,6 +117,14 @@ impl App {
}
pub(super) async fn handle_paste(&mut self, text: String) {
+ if self.state.popup_pane.is_some() {
+ if let Some(runtime) = self.popup_runtime() {
+ let _ = runtime.send_paste(text).await;
+ } else {
+ self.close_popup_pane();
+ }
+ return;
+ }
if self.state.mode != Mode::Terminal {
self.paste_into_active_text_input(&text);
return;
@@ -239,6 +253,10 @@ impl App {
}
pub(super) fn handle_mouse(&mut self, mouse: MouseEvent) {
+ if self.state.popup_pane.is_some() {
+ self.handle_popup_mouse(mouse);
+ return;
+ }
if self.handle_overlay_mouse(mouse) {
return;
}
@@ -373,6 +391,62 @@ impl App {
}
}
+ fn handle_popup_mouse(&mut self, mouse: MouseEvent) {
+ let Some((_outer, inner)) =
+ crate::ui::popup_pane_rects(&self.state, self.state.view.terminal_area)
+ else {
+ return;
+ };
+ if mouse.column < inner.x
+ || mouse.column >= inner.x.saturating_add(inner.width)
+ || mouse.row < inner.y
+ || mouse.row >= inner.y.saturating_add(inner.height)
+ {
+ return;
+ }
+ let Some(rt) = self.popup_runtime() else {
+ self.close_popup_pane();
+ return;
+ };
+ let column = mouse.column.saturating_sub(inner.x);
+ let row = mouse.row.saturating_sub(inner.y);
+ let bytes = match mouse.kind {
+ MouseEventKind::ScrollUp
+ | MouseEventKind::ScrollDown
+ | MouseEventKind::ScrollLeft
+ | MouseEventKind::ScrollRight => match rt.wheel_routing() {
+ Some(crate::pane::WheelRouting::MouseReport) => {
+ rt.encode_mouse_wheel(mouse.kind, column, row, mouse.modifiers)
+ }
+ Some(crate::pane::WheelRouting::AlternateScroll) => {
+ rt.encode_alternate_scroll(mouse.kind)
+ }
+ Some(crate::pane::WheelRouting::HostScroll) | None => {
+ let lines_per_notch = self.state.mouse_scroll_lines;
+ match mouse.kind {
+ MouseEventKind::ScrollUp => rt.scroll_up(lines_per_notch),
+ MouseEventKind::ScrollDown => rt.scroll_down(lines_per_notch),
+ _ => {}
+ }
+ return;
+ }
+ },
+ MouseEventKind::Down(_) | MouseEventKind::Up(_) | MouseEventKind::Drag(_) => {
+ rt.encode_mouse_button(mouse.kind, column, row, mouse.modifiers)
+ }
+ MouseEventKind::Moved => {
+ rt.encode_mouse_motion(mouse.kind, column, row, mouse.modifiers)
+ }
+ };
+ let Some(bytes) = bytes else {
+ return;
+ };
+ rt.scroll_reset();
+ if let Err(err) = rt.try_send_bytes(Bytes::from(bytes)) {
+ warn!(err = %err, kind = ?mouse.kind, "failed to forward popup mouse event");
+ }
+ }
+
fn handle_modified_url_click(&mut self, mouse: MouseEvent) -> bool {
if self.state.mode != Mode::Terminal
|| !matches!(mouse.kind, MouseEventKind::Down(MouseButton::Left))