diff --git a/doc_src/terminal-compatibility.rst b/doc_src/terminal-compatibility.rst index b01da63da..f1e7a9f62 100644 --- a/doc_src/terminal-compatibility.rst +++ b/doc_src/terminal-compatibility.rst @@ -210,7 +210,7 @@ Optional Commands and the second parameter is the column number. Both start at 1. - This is required for terminals that either + This is used inside terminals that either - implement the OSC 133 :ref:`click_events ` feature. - advertise the :ref:`indn ` capability via :ref:`XTGETTCAP ` @@ -284,8 +284,8 @@ Optional Commands ``\e]133;A; click_events=1\x07`` - - Mark prompt start (OSC 133), with kitty's ``click_events`` extension. - If ``click_events`` is implemented, - the :ref:`cursor position reporting ` feature is required. + The ``click_events`` extension enables mouse clicks to move the cursor or select pager items, + assuming that :ref:`cursor position reporting ` is available. - FinalTerm, kitty * - ``\e]133;C; cmdline_url= Pt \x07`` - diff --git a/src/input_common.rs b/src/input_common.rs index 439462ecc..c16aac5bf 100644 --- a/src/input_common.rs +++ b/src/input_common.rs @@ -756,14 +756,26 @@ pub fn function_set_status(&mut self, status: bool) { } #[derive(Clone, Eq, PartialEq)] -pub enum CursorPositionQuery { +pub enum CursorPositionQueryKind { MouseLeft(ViewportPosition), ScrollbackPush, } +#[derive(Clone, Eq, PartialEq)] +pub struct CursorPositionQuery { + pub kind: CursorPositionQueryKind, + pub result: Option, +} + +impl CursorPositionQuery { + pub fn new(kind: CursorPositionQueryKind) -> Self { + Self { kind, result: None } + } +} + #[derive(Eq, PartialEq)] pub enum TerminalQuery { - PrimaryDeviceAttribute, + Initial, CursorPosition(CursorPositionQuery), } diff --git a/src/reader.rs b/src/reader.rs index 49136a782..66d36a4fb 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -87,8 +87,8 @@ }; use crate::input::init_input; use crate::input_common::{ - stop_query, CharEvent, CharInputStyle, CursorPositionQuery, ImplicitEvent, InputData, - QueryResponseEvent, ReadlineCmd, TerminalQuery, + stop_query, CharEvent, CharInputStyle, CursorPositionQuery, CursorPositionQueryKind, + ImplicitEvent, InputData, QueryResponseEvent, ReadlineCmd, TerminalQuery, }; use crate::io::IoChain; use crate::key::ViewportPosition; @@ -276,7 +276,7 @@ pub(crate) fn initial_query( query_capabilities_via_dcs(out.by_ref(), vars); } out.write_command(QueryPrimaryDeviceAttribute); - Some(TerminalQuery::PrimaryDeviceAttribute) + Some(TerminalQuery::Initial) }; RefCell::new(query) }); @@ -1548,7 +1548,12 @@ pub fn request_cursor_position(&mut self, out: &mut Outputter, q: CursorPosition let mut query = self.blocking_query(); assert!(query.is_none()); *query = Some(TerminalQuery::CursorPosition(q)); - out.write_command(QueryCursorPosition); + { + out.begin_buffering(); + out.write_command(QueryCursorPosition); + out.write_command(QueryPrimaryDeviceAttribute); + out.end_buffering(); + } drop(query); self.save_screen_state(); } @@ -2560,19 +2565,16 @@ fn handle_char_event(&mut self, injected_event: Option) -> ControlFlo FLOG!(reader, "Mouse left click", position); self.request_cursor_position( &mut Outputter::stdoutput().borrow_mut(), - CursorPositionQuery::MouseLeft(position), + CursorPositionQuery::new(CursorPositionQueryKind::MouseLeft(position)), ); } }, CharEvent::QueryResponse(query_result) => { - let maybe_query = self.blocking_query(); - let query = &maybe_query; + let mut maybe_query = self.blocking_query(); + let query = &mut maybe_query; use QueryResponseEvent::*; - let query = match (&**query, query_result) { - ( - Some(TerminalQuery::PrimaryDeviceAttribute), - PrimaryDeviceAttributeResponse, - ) => { + let query = match (&mut **query, query_result) { + (Some(TerminalQuery::Initial), PrimaryDeviceAttributeResponse) => { if get_kitty_keyboard_capability() == Capability::Unknown { set_kitty_keyboard_capability( reader_save_screen_state, @@ -2584,15 +2586,28 @@ fn handle_char_event(&mut self, injected_event: Option) -> ControlFlo ( Some(TerminalQuery::CursorPosition(cursor_pos_query)), CursorPositionResponse(cursor_pos), + ) => { + cursor_pos_query.result = Some(cursor_pos); + maybe_query + } + ( + Some(TerminalQuery::CursorPosition(cursor_pos_query)), + PrimaryDeviceAttributeResponse, ) => { let cursor_pos_query = cursor_pos_query.clone(); drop(maybe_query); - match cursor_pos_query { - CursorPositionQuery::MouseLeft(click_position) => { - self.mouse_left_click(cursor_pos, click_position); + use CursorPositionQueryKind::*; + let cursor_pos = cursor_pos_query.result; + match cursor_pos_query.kind { + MouseLeft(click_position) => { + if let Some(cursor_pos) = cursor_pos { + self.mouse_left_click(cursor_pos, click_position); + } } - CursorPositionQuery::ScrollbackPush => { - self.screen.push_to_scrollback(cursor_pos.y); + ScrollbackPush => { + if let Some(cursor_pos) = cursor_pos { + self.screen.push_to_scrollback(cursor_pos.y); + } } }; self.blocking_query() @@ -3908,12 +3923,12 @@ fn handle_readline_command(&mut self, c: ReadlineCmd) { drop(query); self.request_cursor_position( &mut Outputter::stdoutput().borrow_mut(), - CursorPositionQuery::ScrollbackPush, + CursorPositionQuery::new(CursorPositionQueryKind::ScrollbackPush), ); return; }; match query { - TerminalQuery::PrimaryDeviceAttribute => panic!(), + TerminalQuery::Initial => panic!(), TerminalQuery::CursorPosition(_) => { // TODO: re-queue it I guess. FLOG!(