aboutsummaryrefslogtreecommitdiff
path: root/src/app/mod.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-05-14 02:50:00 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-05-14 02:50:00 +0300
commited4253d6031c9a3b12ddd6dfc7d7bf39480ae761 (patch)
tree315cea3ee7b5ad3a7c3f9fb31272064a0eed5dd2 /src/app/mod.rs
parent287bf51640f8e1bed227cb27d93377d962851196 (diff)
feat: add tmux-style mouse capture config
Diffstat (limited to 'src/app/mod.rs')
-rw-r--r--src/app/mod.rs29
1 files changed, 27 insertions, 2 deletions
diff --git a/src/app/mod.rs b/src/app/mod.rs
index 8ef9d8f6..b56e8fc9 100644
--- a/src/app/mod.rs
+++ b/src/app/mod.rs
@@ -33,7 +33,10 @@ const AUTO_UPDATE_CHECK_INTERVAL: Duration = Duration::from_secs(30 * 60);
const SESSION_SAVE_DEBOUNCE: Duration = Duration::from_secs(5);
const SIDEBAR_DOUBLE_CLICK_WINDOW: Duration = Duration::from_millis(350);
-use crossterm::terminal;
+use crossterm::{
+ event::{DisableMouseCapture, EnableMouseCapture},
+ execute, terminal,
+};
use ratatui::layout::Rect;
use ratatui::DefaultTerminal;
use tokio::sync::{mpsc, Notify};
@@ -364,6 +367,7 @@ impl App {
sidebar_collapsed: false,
sidebar_section_split,
agent_panel_scope,
+ mouse_capture: config.ui.mouse_capture,
confirm_close: config.ui.confirm_close,
show_agent_labels_on_pane_borders: config.ui.show_agent_labels_on_pane_borders,
kitty_graphics_enabled: config.advanced.kitty_graphics,
@@ -449,6 +453,7 @@ impl App {
self.query_host_terminal_theme();
let mut needs_render = true;
+ let mut host_mouse_capture_active = self.state.mouse_capture;
while !self.state.should_quit {
if self.render_dirty.load(Ordering::Acquire) {
@@ -497,6 +502,7 @@ impl App {
let now = Instant::now();
self.sync_animation_timer(now);
+ self.sync_host_mouse_capture(&mut host_mouse_capture_active)?;
if needs_render && self.can_render_now(now) {
self.render_dirty.swap(false, Ordering::AcqRel);
@@ -577,6 +583,20 @@ impl App {
Ok(())
}
+ fn sync_host_mouse_capture(&self, active: &mut bool) -> io::Result<()> {
+ let desired = self.state.should_capture_host_mouse();
+ if desired == *active {
+ return Ok(());
+ }
+ if desired {
+ execute!(io::stdout(), EnableMouseCapture)?;
+ } else {
+ execute!(io::stdout(), DisableMouseCapture)?;
+ }
+ *active = desired;
+ Ok(())
+ }
+
pub(crate) fn dismiss_release_notes(&mut self) {
let preview = self
.state
@@ -683,6 +703,7 @@ impl App {
if self.state.sidebar_width_source == state::SidebarWidthSource::ConfigDefault {
self.state.sidebar_width = config.ui.sidebar_width;
}
+ self.state.mouse_capture = config.ui.mouse_capture;
self.state.confirm_close = config.ui.confirm_close;
self.state.show_agent_labels_on_pane_borders =
config.ui.show_agent_labels_on_pane_borders;
@@ -805,7 +826,11 @@ impl App {
}
}
crate::raw_input::RawInputEvent::Mouse(mouse) => {
- self.handle_mouse_event_headless(mouse);
+ if self.state.mouse_capture {
+ self.handle_mouse_event_headless(mouse);
+ } else {
+ self.state.handle_pane_mouse_only(mouse);
+ }
}
crate::raw_input::RawInputEvent::Paste(text) => {
if self.state.mode == Mode::Terminal {