Merge branch 'copilot/fix-cursor-trail-start-threshold' of https://github.com/kovidgoyal/kitty

Fix #10248
This commit is contained in:
Kovid Goyal
2026-07-10 07:55:51 +05:30
9 changed files with 48 additions and 27 deletions

View File

@@ -222,7 +222,7 @@ Detailed list of changes
- quick-access-terminal kitten: Allow configuring the layer on which to display the terminal (:pull:`10242`)
- :opt:`cursor_trail_start_threshold` now optionally accepts two values to set x (horizontal) and y (vertical) thresholds independently (:iss:`10246`)
0.47.4 [2026-06-15]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -55,10 +55,10 @@ should_skip_cursor_trail_update(CursorTrail *ct, ndc_coords g, OSWindow *os_wind
return true;
}
if (OPT(cursor_trail_start_threshold) > 0 && !ct->needs_render) {
if ((OPT(cursor_trail_start_threshold_x) > 0 || OPT(cursor_trail_start_threshold_y) > 0) && !ct->needs_render) {
int dx = (int)round((ct->corner_x[0] - EDGE(x, 1)) / g.dx);
int dy = (int)round((ct->corner_y[0] - EDGE(y, 0)) / g.dy);
if (abs(dx) + abs(dy) <= OPT(cursor_trail_start_threshold)) {
if (abs(dx) <= OPT(cursor_trail_start_threshold_x) && abs(dy) <= OPT(cursor_trail_start_threshold_y)) {
return true;
}
}

View File

@@ -406,13 +406,17 @@ Adjust these values to control how quickly the cursor trail fades away.
''')
opt('cursor_trail_start_threshold', '2',
option_type='positive_int', ctype='int',
option_type='cursor_trail_start_threshold',
ctype='!cursor_trail_start_threshold',
long_text='''
Set the distance threshold for starting the cursor trail. This option accepts a
positive integer value that represents the minimum number of cells the
cursor must move before the trail is started. When the cursor moves less than
this threshold, the trail is skipped, reducing unnecessary cursor trail
animation.
Set the distance threshold for starting the cursor trail. This option accepts
one or two positive integer values. When a single value is specified, it sets
the threshold for both horizontal (x) and vertical (y) movement. When two
values are specified, the first sets the x (horizontal) threshold and the
second sets the y (vertical) threshold. The values represent the minimum
number of cells the cursor must move in each dimension before the trail is
started. When the cursor moves less than the threshold in both dimensions,
the trail is skipped, reducing unnecessary cursor trail animation.
''')
opt('cursor_trail_color', 'none',

30
kitty/options/parse.py generated
View File

@@ -11,20 +11,20 @@ from kitty.options.utils import (
action_alias, active_tab_title_template, allow_hyperlinks, background_images, bell_on_tab,
box_drawing_scale, clear_all_mouse_actions, clear_all_shortcuts, clipboard_control,
clone_source_strategies, config_or_absolute_path, confirm_close, copy_on_select,
cursor_blink_interval, cursor_text_color, cursor_trail_decay, deprecated_adjust_line_height,
deprecated_hide_window_decorations_aliases, deprecated_macos_show_window_title_in_menubar_alias,
deprecated_scrollback_indicator_opacity, deprecated_send_text, disable_ligatures, edge_width, env,
filter_notification, font_features, hide_window_decorations, macos_option_as_alt,
macos_titlebar_color, menu_map, modify_font, mouse_hide_wait, narrow_symbols, notify_on_cmd_finish,
optional_edge_width, parse_font_spec, parse_map, parse_mouse_map, paste_actions,
pointer_shape_when_dragging, remote_control_password, resize_debounce_time, scrollback_lines,
scrollback_pager_history_size, scrollbar_color, shell_integration, show_hyperlink_targets,
store_multiple, symbol_map, tab_activity_symbol, tab_bar_edge, tab_bar_margin_height,
tab_bar_min_tabs, tab_fade, tab_font_style, tab_separator, tab_title_template,
text_fg_override_threshold, titlebar_color, to_cursor_shape, to_cursor_unfocused_shape,
to_font_size, to_layout_names, to_modifiers, transparent_background_colors, underline_exclusion,
url_prefixes, url_style, visual_bell_duration, visual_window_select_characters, window_border_width,
window_logo_scale, window_size
cursor_blink_interval, cursor_text_color, cursor_trail_decay, cursor_trail_start_threshold,
deprecated_adjust_line_height, deprecated_hide_window_decorations_aliases,
deprecated_macos_show_window_title_in_menubar_alias, deprecated_scrollback_indicator_opacity,
deprecated_send_text, disable_ligatures, edge_width, env, filter_notification, font_features,
hide_window_decorations, macos_option_as_alt, macos_titlebar_color, menu_map, modify_font,
mouse_hide_wait, narrow_symbols, notify_on_cmd_finish, optional_edge_width, parse_font_spec,
parse_map, parse_mouse_map, paste_actions, pointer_shape_when_dragging, remote_control_password,
resize_debounce_time, scrollback_lines, scrollback_pager_history_size, scrollbar_color,
shell_integration, show_hyperlink_targets, store_multiple, symbol_map, tab_activity_symbol,
tab_bar_edge, tab_bar_margin_height, tab_bar_min_tabs, tab_fade, tab_font_style, tab_separator,
tab_title_template, text_fg_override_threshold, titlebar_color, to_cursor_shape,
to_cursor_unfocused_shape, to_font_size, to_layout_names, to_modifiers,
transparent_background_colors, underline_exclusion, url_prefixes, url_style, visual_bell_duration,
visual_window_select_characters, window_border_width, window_logo_scale, window_size
)
@@ -953,7 +953,7 @@ class Parser:
ans['cursor_trail_decay'] = cursor_trail_decay(val)
def cursor_trail_start_threshold(self, val: str, ans: dict[str, typing.Any]) -> None:
ans['cursor_trail_start_threshold'] = positive_int(val)
ans['cursor_trail_start_threshold'] = cursor_trail_start_threshold(val)
def cursor_underline_thickness(self, val: str, ans: dict[str, typing.Any]) -> None:
ans['cursor_underline_thickness'] = positive_float(val)

View File

@@ -228,7 +228,7 @@ convert_from_opts_cursor_trail_decay(PyObject *py_opts, Options *opts) {
static void
convert_from_python_cursor_trail_start_threshold(PyObject *val, Options *opts) {
opts->cursor_trail_start_threshold = PyLong_AsLong(val);
cursor_trail_start_threshold(val, opts);
}
static void

View File

@@ -289,6 +289,12 @@ cursor_trail_decay(PyObject *src, Options *opts) {
opts->cursor_trail_decay_slow = PyFloat_AsFloat(PyTuple_GET_ITEM(src, 1));
}
static inline void
cursor_trail_start_threshold(PyObject *src, Options *opts) {
opts->cursor_trail_start_threshold_x = (int)PyLong_AsLong(PyTuple_GET_ITEM(src, 0));
opts->cursor_trail_start_threshold_y = (int)PyLong_AsLong(PyTuple_GET_ITEM(src, 1));
}
static inline void
cursor_trail_color(PyObject *src, Options *opts) {
opts->cursor_trail_color = color_or_none_as_int(src);

View File

@@ -567,7 +567,7 @@ class Options:
cursor_trail: int = 0
cursor_trail_color: kitty.fast_data_types.Color | None = None
cursor_trail_decay: tuple[float, float] = (0.1, 0.4)
cursor_trail_start_threshold: int = 2
cursor_trail_start_threshold: tuple[int, int] = (2, 2)
cursor_underline_thickness: float = 2.0
default_pointer_shape: choices_for_default_pointer_shape = 'beam'
detect_urls: bool = True

View File

@@ -585,6 +585,16 @@ def cursor_trail_decay(x: str) -> tuple[float, float]:
slow = max(slow, fast)
return fast, slow
def cursor_trail_start_threshold(x: str) -> tuple[int, int]:
parts = x.split()
if len(parts) == 1:
val = positive_int(parts[0])
return val, val
if len(parts) == 2:
return positive_int(parts[0]), positive_int(parts[1])
raise ValueError(f'cursor_trail_start_threshold must have 1 or 2 values, got: {x!r}')
def scrollback_lines(x: str) -> int:
ans = int(x)
if ans < 0:

View File

@@ -65,7 +65,8 @@ typedef struct Options {
float cursor_trail_decay_fast;
float cursor_trail_decay_slow;
color_type cursor_trail_color;
float cursor_trail_start_threshold;
int cursor_trail_start_threshold_x;
int cursor_trail_start_threshold_y;
unsigned int url_style;
unsigned int scrollback_pager_history_size;
bool scrollback_fill_enlarged_window;