mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-21 11:31:15 -03:00
Degrade gracefully when failing to receive cursor position report
Follow up the cursor position report query with a primary device attribute one. When that one arrives, any cursor position response must have arrived too. This allows us to prevent a hang on terminals that only support primary device attribute.
This commit is contained in:
@@ -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 <term-compat-osc-133>` feature.
|
||||
- advertise the :ref:`indn <term-compat-indn>` capability via :ref:`XTGETTCAP <term-compat-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 <term-compat-cursor-position-report>` feature is required.
|
||||
The ``click_events`` extension enables mouse clicks to move the cursor or select pager items,
|
||||
assuming that :ref:`cursor position reporting <term-compat-cursor-position-report>` is available.
|
||||
- FinalTerm, kitty
|
||||
* - ``\e]133;C; cmdline_url= Pt \x07``
|
||||
-
|
||||
|
||||
@@ -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<ViewportPosition>,
|
||||
}
|
||||
|
||||
impl CursorPositionQuery {
|
||||
pub fn new(kind: CursorPositionQueryKind) -> Self {
|
||||
Self { kind, result: None }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq)]
|
||||
pub enum TerminalQuery {
|
||||
PrimaryDeviceAttribute,
|
||||
Initial,
|
||||
CursorPosition(CursorPositionQuery),
|
||||
}
|
||||
|
||||
|
||||
@@ -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<CharEvent>) -> 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<CharEvent>) -> 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!(
|
||||
|
||||
Reference in New Issue
Block a user