diff --git a/docs/changelog.rst b/docs/changelog.rst index c3aab6811..56a850321 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -222,6 +222,9 @@ Detailed list of changes - :ac:`goto_session`: Add a ``--active-only`` option to select from only active sessions (:pull:`9503`) +- Shell integration: Allow sending click events to shells using y co-ordinates + relative to prompts (:iss:`9500`) + 0.45.0 [2025-12-24] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/shell-integration.rst b/docs/shell-integration.rst index 04a96ec47..355bc77d1 100644 --- a/docs/shell-integration.rst +++ b/docs/shell-integration.rst @@ -468,13 +468,21 @@ to control its behavior, separated by semi-colons. They are: this tells kitty that the secondary (PS2) prompt is starting at the current line. -``click_events=1`` +``click_events=1|2`` this tells kitty that the shell is capable of handling mouse click events. kitty will thus send a click event to the shell when the user clicks somewhere in the prompt. The shell can then move the cursor to that position or perform some other appropriate action. Without this, kitty will instead generate a number of fake key events to move the cursor - to the clicked location, which is not fully robust. + to the clicked location, which is not fully robust. A value of ``1`` will + cause the click events to have absolute y co-ordinates, a value of ``2`` + will cause them to have y-coordinates relative to the top line of the + current prompt. In relative mode, y is zero for cells on the top line of + the current prompt. The current prompt here is either the secondary (PS2) or + primary prompt. If the secondary prompt is on the same line or above the + mouse position, then the reported y will be with respect to that, otherwise + with respect to the primary prompt. The click event is encoded in the SGR + encoding from xterm. kitty also optionally supports sending the cmdline going to be executed with ``133;C`` as: diff --git a/kitty/mouse.c b/kitty/mouse.c index 05575a568..592e58290 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -740,14 +740,16 @@ move_cursor_to_mouse_if_at_shell_prompt(Window *w) { int y = screen_cursor_at_a_shell_prompt(screen); if (y < 0 || (unsigned)y > w->mouse_pos.cell_y) return false; - if (screen_prompt_supports_click_events(screen)) { - int sz = encode_mouse_event_impl(&w->mouse_pos, SGR_PROTOCOL, 1, PRESS, 0); + bool is_relative; + if (screen_prompt_supports_click_events(screen, &is_relative)) { + MousePosition mpos = w->mouse_pos; + if (is_relative) mpos.cell_y -= y; + int sz = encode_mouse_event_impl(&mpos, SGR_PROTOCOL, 1, PRESS, 0); if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, ESC_CSI, mouse_event_buf); return true; } - return false; } else { return screen_fake_move_cursor_to_position(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y); diff --git a/kitty/screen.c b/kitty/screen.c index 140fb5736..68c667ccc 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -2318,7 +2318,8 @@ screen_cursor_at_a_shell_prompt(const Screen *self) { } bool -screen_prompt_supports_click_events(const Screen *self) { +screen_prompt_supports_click_events(const Screen *self, bool *is_relative) { + *is_relative = (bool) self->prompt_settings.relative_click_events; return (bool) self->prompt_settings.supports_click_events; } @@ -3065,7 +3066,13 @@ parse_prompt_mark(Screen *self, char *buf, PromptKind *pk) { if (strcmp(token, "k=s") == 0) *pk = SECONDARY_PROMPT; else if (strcmp(token, "redraw=0") == 0) self->prompt_settings.redraws_prompts_at_all = 0; else if (strcmp(token, "special_key=1") == 0) self->prompt_settings.uses_special_keys_for_cursor_movement = 1; - else if (strcmp(token, "click_events=1") == 0) self->prompt_settings.supports_click_events = 1; + else if (strcmp(token, "click_events=1") == 0) { + self->prompt_settings.supports_click_events = 1; + self->prompt_settings.relative_click_events = 0; + } else if (strcmp(token, "click_events=2") == 0) { + self->prompt_settings.supports_click_events = 1; + self->prompt_settings.relative_click_events = 1; + } } } diff --git a/kitty/screen.h b/kitty/screen.h index 56abafc9a..fbc915585 100644 --- a/kitty/screen.h +++ b/kitty/screen.h @@ -154,6 +154,7 @@ typedef struct { unsigned int redraws_prompts_at_all: 1; unsigned int uses_special_keys_for_cursor_movement: 1; unsigned int supports_click_events: 1; + unsigned int relative_click_events: 1; }; unsigned int val; } prompt_settings; @@ -307,7 +308,7 @@ void screen_modify_other_keys(Screen *self, unsigned, unsigned); void screen_report_key_encoding_flags(Screen *self); int screen_detect_url(Screen *screen, unsigned int x, unsigned int y); int screen_cursor_at_a_shell_prompt(const Screen *); -bool screen_prompt_supports_click_events(const Screen *); +bool screen_prompt_supports_click_events(const Screen *, bool *is_relative); bool screen_fake_move_cursor_to_position(Screen *, index_type x, index_type y); bool screen_send_signal_for_key(Screen *, char key); bool get_line_edge_colors(Screen *self, color_type *left, color_type *right);