aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-09-05 04:39:25 +0300
committerGitHub <noreply@github.com>2026-09-05 03:39:25 +0200
commit3a822e8106b45745f9d463d9167033f977353d9f (patch)
tree5ffbf80074d739c9ac6976e8bfb894b9de16e5f3 /src
parent7916be1656d8ee9c5882b52753cd47f5e58e3e7e (diff)
fix: preserve pixel mouse after sgr reassertion (#3637)
refs #3295 Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Diffstat (limited to 'src')
-rw-r--r--src/ghostty/mod.rs2
-rw-r--r--src/pane/input.rs11
-rw-r--r--src/server/headless/tests/mod.rs42
3 files changed, 51 insertions, 4 deletions
diff --git a/src/ghostty/mod.rs b/src/ghostty/mod.rs
index 691160e6..77ac36da 100644
--- a/src/ghostty/mod.rs
+++ b/src/ghostty/mod.rs
@@ -175,6 +175,8 @@ pub const MOUSE_BUTTON_WHEEL_RIGHT: ffi::GhosttyMouseButton =
ffi::GhosttyMouseButton_GHOSTTY_MOUSE_BUTTON_SEVEN;
pub const MOUSE_FORMAT_SGR: ffi::GhosttyMouseFormat =
ffi::GhosttyMouseFormat_GHOSTTY_MOUSE_FORMAT_SGR;
+pub const MOUSE_FORMAT_SGR_PIXELS: ffi::GhosttyMouseFormat =
+ ffi::GhosttyMouseFormat_GHOSTTY_MOUSE_FORMAT_SGR_PIXELS;
pub const MODE_APPLICATION_CURSOR_KEYS: u16 = 1;
pub const MODE_FOCUS_EVENT: u16 = 1004;
diff --git a/src/pane/input.rs b/src/pane/input.rs
index 2ff299c9..8de216e8 100644
--- a/src/pane/input.rs
+++ b/src/pane/input.rs
@@ -66,17 +66,20 @@ pub(super) fn ghostty_mouse_encoder_for_terminal(
encoder.set_from_terminal(terminal);
let cols = terminal.cols().ok()? as u32;
let rows = terminal.rows().ok()? as u32;
+ let sgr_pixels = terminal
+ .mode_get(crate::ghostty::MODE_MOUSE_SGR_PIXELS)
+ .ok()?;
match position {
crate::input::mouse::Position::Cell { .. } => {
- if terminal
- .mode_get(crate::ghostty::MODE_MOUSE_SGR_PIXELS)
- .ok()?
- {
+ if sgr_pixels {
encoder.set_format(crate::ghostty::MOUSE_FORMAT_SGR);
}
encoder.set_size(cols, rows, 1, 1);
}
crate::input::mouse::Position::Pixels { .. } => {
+ if sgr_pixels {
+ encoder.set_format(crate::ghostty::MOUSE_FORMAT_SGR_PIXELS);
+ }
let width_px = terminal.width_px().ok()?;
let height_px = terminal.height_px().ok()?;
if width_px == 0 || height_px == 0 || cols == 0 || rows == 0 {
diff --git a/src/server/headless/tests/mod.rs b/src/server/headless/tests/mod.rs
index 2951a82d..1e4249b5 100644
--- a/src/server/headless/tests/mod.rs
+++ b/src/server/headless/tests/mod.rs
@@ -3885,6 +3885,48 @@ fn client_pane_pixel_mouse_uses_runtime_pixel_encoding() {
}
#[test]
+fn client_pane_pixel_mouse_stays_pixel_scaled_when_sgr_is_reasserted() {
+ let rt = tokio::runtime::Builder::new_current_thread()
+ .enable_all()
+ .build()
+ .expect("test runtime");
+ let _runtime_guard = rt.enter();
+ let (runtime, mut input_rx) =
+ crate::terminal::TerminalRuntime::test_with_channel_and_scrollback_bytes(
+ 80,
+ 24,
+ 0,
+ b"\x1b[?1003h\x1b[?1006h\x1b[?1016h\x1b[?1006h",
+ 4,
+ );
+ runtime.resize(24, 80, 10, 20);
+
+ apply_client_pane_input_events(
+ &runtime,
+ &[crate::protocol::ClientPaneInputEvent::Mouse {
+ kind: crate::protocol::ClientMouseKind::Down(crate::protocol::ClientMouseButton::Left),
+ position: crate::protocol::ClientMousePosition::Pixels {
+ x: 403,
+ y: 240,
+ column: 40,
+ row: 12,
+ },
+ geometry: None,
+ modifiers: 0,
+ lines: 1,
+ }],
+ )
+ .expect("pixel mouse input");
+ assert_eq!(
+ input_rx.try_recv().expect("encoded pixel mouse"),
+ Bytes::from_static(b"\x1b[<0;403;240M")
+ );
+ drop(runtime);
+ drop(_runtime_guard);
+ rt.shutdown_timeout(Duration::from_millis(100));
+}
+
+#[test]
fn client_pane_pixel_mouse_falls_back_to_canonical_cell_position() {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()