Change mouse_hide_wait to struct, and change mouse_show_* options to optional parameters for struct. mouse_show_* renamed to mouse_unhide_*

This commit is contained in:
Your Name 2025-04-04 09:09:29 +00:00
parent 464446e388
commit 33167f2057
11 changed files with 85 additions and 89 deletions

View file

@ -717,9 +717,9 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int *
}
if (send_cell_data_to_gpu(TD.vao_idx, TD.xstart, TD.ystart, TD.dx, TD.dy, TD.screen, os_window)) needs_render = true;
}
if (OPT(mouse_hide_wait) > 0 && !is_mouse_hidden(os_window)) {
if (now - os_window->last_mouse_activity_at >= OPT(mouse_hide_wait)) hide_mouse(os_window);
else set_maximum_wait(OPT(mouse_hide_wait) - now + os_window->last_mouse_activity_at);
if (OPT(mouse_hide.hide_wait) > 0 && !is_mouse_hidden(os_window)) {
if (now - os_window->last_mouse_activity_at >= OPT(mouse_hide.hide_wait)) hide_mouse(os_window);
else set_maximum_wait(OPT(mouse_hide.hide_wait) - now + os_window->last_mouse_activity_at);
}
Tab *tab = os_window->tabs + os_window->active_tab;
*active_window_bg = OPT(background);

View file

@ -219,12 +219,12 @@ show_mouse_cursor(GLFWwindow *w) {
void
cursor_active_callback(GLFWwindow *w, monotonic_t now) {
if (OPT(mouse_show_wait) == 0) {
if (OPT(mouse_hide.unhide_wait) == 0) {
show_mouse_cursor(w);
} else if (OPT(mouse_show_wait) > 0) {
} else if (OPT(mouse_hide.unhide_wait) > 0) {
if (global_state.callback_os_window->mouse_activate_deadline == -1) {
global_state.callback_os_window->mouse_activate_deadline = OPT(mouse_show_wait) + now;
global_state.callback_os_window->mouse_show_threshold = (int) (OPT(mouse_show_wait) * OPT(mouse_show_threshold));
global_state.callback_os_window->mouse_activate_deadline = OPT(mouse_hide.unhide_wait) + now;
global_state.callback_os_window->mouse_show_threshold = (int) (OPT(mouse_hide.unhide_wait) / 1e9 * OPT(mouse_hide.unhide_threshold));
} else if (now < global_state.callback_os_window->mouse_activate_deadline) {
if (global_state.callback_os_window->mouse_show_threshold > 0) {
global_state.callback_os_window->mouse_show_threshold--;
@ -529,7 +529,7 @@ static void
scroll_callback(GLFWwindow *w, double xoffset, double yoffset, int flags, int mods) {
if (!set_callback_window(w)) return;
monotonic_t now = monotonic();
if (OPT(mouse_scroll_show)) {
if (OPT(mouse_hide.scroll_unhide)) {
cursor_active_callback(w, now);
}
global_state.callback_os_window->last_mouse_activity_at = now;

View file

@ -235,7 +235,7 @@ on_key_input(const GLFWkeyevent *ev) {
}
if (!w) { debug("no active window, ignoring\n"); return; }
send_pending_click_to_window(w, -1);
if (OPT(mouse_hide_wait) < 0 && !is_no_action_key(key, native_key)) hide_mouse(global_state.callback_os_window);
if (OPT(mouse_hide.hide_wait) < 0 && !is_no_action_key(key, native_key)) hide_mouse(global_state.callback_os_window);
Screen *screen = w->render_data.screen;
id_type active_window_id = w->id;

View file

@ -511,43 +511,51 @@ agr('mouse', 'Mouse')
opt('mouse_hide_wait', '3.0',
macos_default='0.0',
option_type='float', ctype='time',
option_type='mouse_hide_wait', ctype='!mouse_hide_wait',
long_text='''
Hide mouse cursor after the specified number of seconds of the mouse not being
used. Set to zero to disable mouse cursor hiding. Set to a negative value to
hide the mouse cursor immediately when typing text. Disabled by default on macOS
as getting it to work robustly with the ever-changing sea of bugs that is Cocoa
is too much effort.
'''
)
opt('mouse_show_wait', '0.0',
option_type='float', ctype='time',
long_text='''
By default, once the cursor is hidden, it is immediately unhidden on any
further mouse events.
Two formats are supported:
- "<hide-wait>"
- "<hide-wait> <unhide-wait> <unhide-threshold> <scroll-unhide>"
To change the unhide behavior, the optional parameters <unhide-wait>,
<unhide-threshold>, and <scroll-unhide> may be set.
<unhide-wait>:
Waits for the specified number of seconds after mouse events before unhiding the
mouse cursor. Set to zero to unhide mouse cursor immediately on mouse activity.
This is useful to prevent the mouse cursor from unhiding on accidental swipes on
the trackpad.
'''
)
opt('mouse_show_threshold', '40',
option_type='positive_int',
long_text='''
Sets the threshold of mouse activity required to unhide the mouse cursor, when
the mouse_show_wait option is non-zero. When mouse_show_wait is zero, this has
no effect.
For example, if mouse_show_threshold is 40 and mouse_show_wait is 2.5, when
kitty detects a mouse event, it records the number of mouse events in the next
2.5 seconds, and checks if that exceeds 40 * 2.5 = 100. If it does, then the
mouse cursor is unhidden, otherwise nothing happens.
'''
)
opt('mouse_scroll_show', 'yes',
option_type='to_bool', ctype='bool',
long_text='''
<unhide-threshold>:
Sets the threshold of mouse activity required to unhide the mouse cursor, when
the <unhide-wait> option is non-zero. When <unhide-wait> is zero, this has no
effect.
For example, if <unhide-threshold> is 40 and <unhide-wait> is 2.5, when kitty
detects a mouse event, it records the number of mouse events in the next 2.5
seconds, and checks if that exceeds 40 * 2.5 = 100. If it does, then the mouse
cursor is unhidden, otherwise nothing happens.
<scroll-unhide>:
Controls what mouse events may unhide the mouse cursor. If enabled, both scroll
and movement events may unhide the cursor. If disabled, only mouse movements can
unhide the cursor.
Examples of valid values:
- 0.0
- 1.0
- -1.0
- 0.1 3.0 40 yes
'''
)

13
kitty/options/parse.py generated
View file

@ -14,7 +14,7 @@ from kitty.options.utils import (
cursor_trail_decay, deprecated_adjust_line_height, deprecated_hide_window_decorations_aliases,
deprecated_macos_show_window_title_in_menubar_alias, 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, narrow_symbols, notify_on_cmd_finish,
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, shell_integration, store_multiple, symbol_map, tab_activity_symbol,
@ -1137,16 +1137,7 @@ class Parser:
ans["modify_font"][k] = v
def mouse_hide_wait(self, val: str, ans: dict[str, typing.Any]) -> None:
ans['mouse_hide_wait'] = float(val)
def mouse_scroll_show(self, val: str, ans: dict[str, typing.Any]) -> None:
ans['mouse_scroll_show'] = to_bool(val)
def mouse_show_threshold(self, val: str, ans: dict[str, typing.Any]) -> None:
ans['mouse_show_threshold'] = positive_int(val)
def mouse_show_wait(self, val: str, ans: dict[str, typing.Any]) -> None:
ans['mouse_show_wait'] = float(val)
ans['mouse_hide_wait'] = mouse_hide_wait(val)
def narrow_symbols(self, val: str, ans: dict[str, typing.Any]) -> None:
for k, v in narrow_symbols(val):

View file

@ -319,7 +319,7 @@ convert_from_opts_touch_scroll_multiplier(PyObject *py_opts, Options *opts) {
static void
convert_from_python_mouse_hide_wait(PyObject *val, Options *opts) {
opts->mouse_hide_wait = parse_s_double_to_monotonic_t(val);
mouse_hide_wait(val, opts);
}
static void
@ -330,32 +330,6 @@ convert_from_opts_mouse_hide_wait(PyObject *py_opts, Options *opts) {
Py_DECREF(ret);
}
static void
convert_from_python_mouse_show_wait(PyObject *val, Options *opts) {
opts->mouse_show_wait = parse_s_double_to_monotonic_t(val);
}
static void
convert_from_opts_mouse_show_wait(PyObject *py_opts, Options *opts) {
PyObject *ret = PyObject_GetAttrString(py_opts, "mouse_show_wait");
if (ret == NULL) return;
convert_from_python_mouse_show_wait(ret, opts);
Py_DECREF(ret);
}
static void
convert_from_python_mouse_scroll_show(PyObject *val, Options *opts) {
opts->mouse_scroll_show = PyObject_IsTrue(val);
}
static void
convert_from_opts_mouse_scroll_show(PyObject *py_opts, Options *opts) {
PyObject *ret = PyObject_GetAttrString(py_opts, "mouse_scroll_show");
if (ret == NULL) return;
convert_from_python_mouse_scroll_show(ret, opts);
Py_DECREF(ret);
}
static void
convert_from_python_url_color(PyObject *val, Options *opts) {
opts->url_color = color_as_int(val);
@ -1253,10 +1227,6 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) {
if (PyErr_Occurred()) return false;
convert_from_opts_mouse_hide_wait(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_mouse_show_wait(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_mouse_scroll_show(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_url_color(py_opts, opts);
if (PyErr_Occurred()) return false;
convert_from_opts_url_style(py_opts, opts);

View file

@ -197,6 +197,18 @@ visual_bell_duration(PyObject *src, Options *opts) {
#undef parse_animation
static inline void
mouse_hide_wait(PyObject *val, Options *opts) {
if (!PyTuple_Check(val) || PyTuple_GET_SIZE(val) != 4) {
PyErr_SetString(PyExc_TypeError, "mouse_hide_wait is not a 4-item tuple");
return;
}
opts->mouse_hide.hide_wait = parse_s_double_to_monotonic_t(PyTuple_GET_ITEM(val, 0));
opts->mouse_hide.unhide_wait = parse_s_double_to_monotonic_t(PyTuple_GET_ITEM(val, 1));
opts->mouse_hide.unhide_threshold = PyLong_AsLong(PyTuple_GET_ITEM(val, 2));
opts->mouse_hide.scroll_unhide = PyObject_IsTrue(PyTuple_GET_ITEM(val, 3));
}
static inline void
cursor_trail_decay(PyObject *src, Options *opts) {
opts->cursor_trail_decay_fast = PyFloat_AsFloat(PyTuple_GET_ITEM(src, 0));

10
kitty/options/types.py generated
View file

@ -11,7 +11,7 @@ import kitty.fast_data_types
from kitty.fonts import FontSpec
import kitty.fonts
from kitty.options.utils import (
AliasMap, KeyDefinition, KeyboardModeMap, MouseMap, MouseMapping, NotifyOnCmdFinish,
AliasMap, KeyDefinition, KeyboardModeMap, MouseHideWait, MouseMap, MouseMapping, NotifyOnCmdFinish,
TabBarMarginHeight
)
import kitty.options.utils
@ -396,9 +396,6 @@ option_names = (
'modify_font',
'mouse_hide_wait',
'mouse_map',
'mouse_scroll_show',
'mouse_show_threshold',
'mouse_show_wait',
'narrow_symbols',
'notify_on_cmd_finish',
'open_url_with',
@ -571,10 +568,7 @@ class Options:
mark2_foreground: Color = Color(0, 0, 0)
mark3_background: Color = Color(242, 116, 188)
mark3_foreground: Color = Color(0, 0, 0)
mouse_hide_wait: float = 0.0 if is_macos else 3.0
mouse_scroll_show: bool = True
mouse_show_threshold: int = 40
mouse_show_wait: float = 0.0
mouse_hide_wait: MouseHideWait = MouseHideWait(hide_wait=0.0, show_wait=0.0, show_threshold=40, scroll_show=True) if is_macos else MouseHideWait(hide_wait=3.0, show_wait=0.0, show_threshold=40, scroll_show=True)
notify_on_cmd_finish: NotifyOnCmdFinish = NotifyOnCmdFinish(when='never', duration=5.0, action='notify', cmdline=(), clear_on=('focus', 'next'))
open_url_with: list[str] = ['default']
paste_actions: frozenset[str] = frozenset({'confirm', 'quote-urls-at-prompt'})

View file

@ -1590,6 +1590,24 @@ def cursor_blink_interval(spec: str) -> tuple[float, EasingFunction, EasingFunct
return parse_animation(spec)
class MouseHideWait(NamedTuple):
hide_wait: float
show_wait: float
show_threshold: int
scroll_show: bool
def mouse_hide_wait(x: str) -> MouseHideWait:
parts = x.split(maxsplit=3)
if len(parts) != 1 and len(parts) != 4:
log_error(f'Invalid mouse_hide_wait: {x}, ignoring')
return MouseHideWait(3.0, 0.0, 40, True)
if len(parts) == 1:
return MouseHideWait(float(parts[0]), 0.0, 40, True)
else:
return MouseHideWait(float(parts[0]), float(parts[1]), int(parts[2]), to_bool(parts[3]))
def visual_bell_duration(spec: str) -> tuple[float, EasingFunction, EasingFunction]:
return parse_animation(spec, interval=0.)

View file

@ -39,9 +39,12 @@ struct MenuItem {
};
typedef struct {
monotonic_t visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, mouse_show_wait, click_interval;
int mouse_show_threshold;
bool mouse_scroll_show;
monotonic_t visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, click_interval;
struct {
monotonic_t hide_wait, unhide_wait;
int unhide_threshold;
bool scroll_unhide;
} mouse_hide;
double wheel_scroll_multiplier, touch_scroll_multiplier;
int wheel_scroll_min_lines;
bool enable_audio_bell;

View file

@ -56,10 +56,10 @@ def conf_parsing(self):
opts = p('font_size 11.37', 'clear_all_shortcuts y', 'color23 red')
self.ae(opts.font_size, 11.37)
self.ae(opts.mouse_hide_wait, 0 if is_macos else 3)
self.ae(opts.mouse_show_wait, 0)
self.ae(opts.mouse_show_threshold, 40)
self.ae(opts.mouse_scroll_show, True)
self.ae(opts.mouse_hide_wait[0], 0 if is_macos else 3)
self.ae(opts.mouse_hide_wait[1], 0)
self.ae(opts.mouse_hide_wait[2], 40)
self.ae(opts.mouse_hide_wait[3], True)
self.ae(opts.color23, Color(255, 0, 0))
self.assertFalse(opts.keyboard_modes[''].keymap)
opts = p('clear_all_shortcuts y', 'map f1 next_window')