aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app/input/terminal.rs38
-rw-r--r--src/pane/terminal.rs22
-rw-r--r--src/server/headless.rs16
3 files changed, 75 insertions, 1 deletions
diff --git a/src/app/input/terminal.rs b/src/app/input/terminal.rs
index 36d60e41..1ba2789c 100644
--- a/src/app/input/terminal.rs
+++ b/src/app/input/terminal.rs
@@ -1971,4 +1971,42 @@ mod tests {
.expect("scroll metrics after PageUp");
assert_eq!(end_metrics.offset_from_bottom, 0);
}
+
+ #[tokio::test]
+ async fn page_up_scrolls_shell_like_decckm_with_bracketed_paste() {
+ let mut app = app_for_mouse_test();
+ let mut ws = Workspace::test_new("test");
+ let pane_id = ws.tabs[0].root_pane;
+ let pane_infos = ws.tabs[0].layout.panes(Rect::new(26, 2, 80, 18));
+ let info = pane_infos[0].clone();
+ // zsh enables DECCKM via smkx and bracketed paste together; bash/fish do not.
+ let mut bytes = b"\x1b[?1h\x1b[?2004h".to_vec();
+ bytes.extend_from_slice(&numbered_lines_bytes(64));
+ let (runtime, mut input_rx) =
+ crate::terminal::TerminalRuntime::test_with_channel_and_scrollback_bytes(
+ info.inner_rect.width,
+ info.inner_rect.height,
+ 16 * 1024,
+ &bytes,
+ 4,
+ );
+ ws.tabs[0].runtimes.insert(pane_id, runtime);
+
+ app.state.workspaces = vec![ws];
+ app.state.active = Some(0);
+ app.state.selected = 0;
+ app.state.mode = Mode::Terminal;
+ app.state.view.pane_infos = pane_infos;
+
+ app.handle_terminal_key_headless(TerminalKey::new(KeyCode::PageUp, KeyModifiers::empty()));
+
+ assert!(
+ input_rx.try_recv().is_err(),
+ "PageUp should not reach the shell"
+ );
+ assert_eq!(
+ pane_scroll_offset(&app, pane_id),
+ info.inner_rect.height as usize
+ );
+ }
}
diff --git a/src/pane/terminal.rs b/src/pane/terminal.rs
index 438c3037..b90c63f1 100644
--- a/src/pane/terminal.rs
+++ b/src/pane/terminal.rs
@@ -130,7 +130,11 @@ impl InputState {
}
pub fn plain_page_keys_use_host_scrollback(self) -> bool {
- !self.alternate_screen && !self.mouse_reporting_enabled() && !self.application_cursor
+ !self.alternate_screen
+ && !self.mouse_reporting_enabled()
+ // Bracketed paste distinguishes zsh's line editor (where it's on)
+ // from e.g. less -X (where it's off).
+ && (!self.application_cursor || self.bracketed_paste)
}
}
@@ -3073,6 +3077,22 @@ mod tests {
use ratatui::{layout::Rect, style::Color};
use tokio::sync::mpsc;
+ #[test]
+ fn plain_page_keys_host_scroll_for_shell_like_decckm_with_bracketed_paste() {
+ assert!(InputState {
+ alternate_screen: false,
+ application_cursor: true,
+ bracketed_paste: true,
+ focus_reporting: false,
+ mouse_protocol_mode: crate::input::MouseProtocolMode::None,
+ mouse_protocol_encoding: crate::input::MouseProtocolEncoding::Default,
+ mouse_alternate_scroll: false,
+ modify_other_keys: false,
+ color_scheme_reporting: false,
+ }
+ .plain_page_keys_use_host_scrollback());
+ }
+
fn text_cell(text: &str) -> crate::ghostty::ScreenTextCell {
crate::ghostty::ScreenTextCell {
wide: crate::ghostty::CellWide::Narrow,
diff --git a/src/server/headless.rs b/src/server/headless.rs
index ff85f253..f72d1a94 100644
--- a/src/server/headless.rs
+++ b/src/server/headless.rs
@@ -6469,6 +6469,22 @@ next_tab = ""
}
#[test]
+ fn terminal_attach_page_key_host_scrolls_shell_like_decckm_with_bracketed_paste() {
+ with_terminal_attach_page_key_runtime(b"\x1b[?1h\x1b[?2004h", 0, |runtime, input_rx| {
+ apply_terminal_attach_page_up(runtime);
+
+ assert_eq!(
+ runtime
+ .scroll_metrics()
+ .expect("scroll metrics")
+ .offset_from_bottom,
+ 4
+ );
+ assert!(input_rx.try_recv().is_err());
+ });
+ }
+
+ #[test]
fn terminal_attach_page_key_forwards_in_alternate_screen_without_mouse_reporting() {
with_terminal_attach_page_key_runtime(b"\x1b[?1049h", 3, |runtime, input_rx| {
apply_terminal_attach_page_up(runtime);