mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-08-31 06:18:17 +00:00
Prevent mouse cursor from showing on short, unintentional flicks
This commit is contained in:
parent
f56c3edd72
commit
464446e388
7 changed files with 118 additions and 9 deletions
42
kitty/glfw.c
42
kitty/glfw.c
|
|
@ -217,6 +217,30 @@ show_mouse_cursor(GLFWwindow *w) {
|
|||
glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
|
||||
}
|
||||
|
||||
void
|
||||
cursor_active_callback(GLFWwindow *w, monotonic_t now) {
|
||||
if (OPT(mouse_show_wait) == 0) {
|
||||
show_mouse_cursor(w);
|
||||
} else if (OPT(mouse_show_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));
|
||||
} 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--;
|
||||
}
|
||||
} else {
|
||||
if (
|
||||
now < global_state.callback_os_window->mouse_activate_deadline + s_double_to_monotonic_t(0.5) &&
|
||||
global_state.callback_os_window->mouse_show_threshold == 0
|
||||
) {
|
||||
show_mouse_cursor(w);
|
||||
}
|
||||
global_state.callback_os_window->mouse_activate_deadline = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
blank_os_window(OSWindow *osw) {
|
||||
color_type color = OPT(background);
|
||||
|
|
@ -451,8 +475,8 @@ cursor_enter_callback(GLFWwindow *w, int entered) {
|
|||
double x, y;
|
||||
glfwGetCursorPos(w, &x, &y);
|
||||
debug_input("Mouse cursor entered window: %llu at %fx%f\n", global_state.callback_os_window->id, x, y);
|
||||
show_mouse_cursor(w);
|
||||
monotonic_t now = monotonic();
|
||||
cursor_active_callback(w, now);
|
||||
global_state.callback_os_window->last_mouse_activity_at = now;
|
||||
global_state.callback_os_window->mouse_x = x * global_state.callback_os_window->viewport_x_ratio;
|
||||
global_state.callback_os_window->mouse_y = y * global_state.callback_os_window->viewport_y_ratio;
|
||||
|
|
@ -465,9 +489,9 @@ cursor_enter_callback(GLFWwindow *w, int entered) {
|
|||
static void
|
||||
mouse_button_callback(GLFWwindow *w, int button, int action, int mods) {
|
||||
if (!set_callback_window(w)) return;
|
||||
show_mouse_cursor(w);
|
||||
mods_at_last_key_or_button_event = mods;
|
||||
monotonic_t now = monotonic();
|
||||
cursor_active_callback(w, now);
|
||||
mods_at_last_key_or_button_event = mods;
|
||||
OSWindow *window = global_state.callback_os_window;
|
||||
window->last_mouse_activity_at = now;
|
||||
if (button >= 0 && (unsigned int)button < arraysz(global_state.callback_os_window->mouse_button_pressed)) {
|
||||
|
|
@ -489,8 +513,8 @@ mouse_button_callback(GLFWwindow *w, int button, int action, int mods) {
|
|||
static void
|
||||
cursor_pos_callback(GLFWwindow *w, double x, double y) {
|
||||
if (!set_callback_window(w)) return;
|
||||
show_mouse_cursor(w);
|
||||
monotonic_t now = monotonic();
|
||||
cursor_active_callback(w, now);
|
||||
global_state.callback_os_window->last_mouse_activity_at = now;
|
||||
global_state.callback_os_window->cursor_blink_zero_time = now;
|
||||
global_state.callback_os_window->mouse_x = x * global_state.callback_os_window->viewport_x_ratio;
|
||||
|
|
@ -504,8 +528,10 @@ cursor_pos_callback(GLFWwindow *w, double x, double y) {
|
|||
static void
|
||||
scroll_callback(GLFWwindow *w, double xoffset, double yoffset, int flags, int mods) {
|
||||
if (!set_callback_window(w)) return;
|
||||
show_mouse_cursor(w);
|
||||
monotonic_t now = monotonic();
|
||||
if (OPT(mouse_scroll_show)) {
|
||||
cursor_active_callback(w, now);
|
||||
}
|
||||
global_state.callback_os_window->last_mouse_activity_at = now;
|
||||
if (is_window_ready_for_callbacks()) scroll_event(xoffset, yoffset, flags, mods);
|
||||
request_tick_callback();
|
||||
|
|
@ -519,13 +545,13 @@ window_focus_callback(GLFWwindow *w, int focused) {
|
|||
if (!set_callback_window(w)) return;
|
||||
debug_input("\x1b[35mon_focus_change\x1b[m: window id: 0x%llu focused: %d\n", global_state.callback_os_window->id, focused);
|
||||
global_state.callback_os_window->is_focused = focused ? true : false;
|
||||
monotonic_t now = monotonic();
|
||||
if (focused) {
|
||||
show_mouse_cursor(w);
|
||||
cursor_active_callback(w, now);
|
||||
focus_in_event();
|
||||
global_state.callback_os_window->last_focused_counter = ++focus_counter;
|
||||
global_state.check_for_active_animated_images = true;
|
||||
}
|
||||
monotonic_t now = monotonic();
|
||||
global_state.callback_os_window->last_mouse_activity_at = now;
|
||||
global_state.callback_os_window->cursor_blink_zero_time = now;
|
||||
if (is_window_ready_for_callbacks()) {
|
||||
|
|
@ -1371,6 +1397,8 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) {
|
|||
w->is_focused = true;
|
||||
w->cursor_blink_zero_time = now;
|
||||
w->last_mouse_activity_at = now;
|
||||
w->mouse_activate_deadline = -1;
|
||||
w->mouse_show_threshold = 0;
|
||||
w->is_semi_transparent = is_semi_transparent;
|
||||
if (want_semi_transparent && !w->is_semi_transparent) {
|
||||
static bool warned = false;
|
||||
|
|
|
|||
|
|
@ -518,6 +518,36 @@ 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='''
|
||||
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='''
|
||||
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.
|
||||
'''
|
||||
)
|
||||
|
||||
|
|
|
|||
9
kitty/options/parse.py
generated
9
kitty/options/parse.py
generated
|
|
@ -1139,6 +1139,15 @@ class Parser:
|
|||
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)
|
||||
|
||||
def narrow_symbols(self, val: str, ans: dict[str, typing.Any]) -> None:
|
||||
for k, v in narrow_symbols(val):
|
||||
ans["narrow_symbols"][k] = v
|
||||
|
|
|
|||
30
kitty/options/to-c-generated.h
generated
30
kitty/options/to-c-generated.h
generated
|
|
@ -330,6 +330,32 @@ 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);
|
||||
|
|
@ -1227,6 +1253,10 @@ 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);
|
||||
|
|
|
|||
6
kitty/options/types.py
generated
6
kitty/options/types.py
generated
|
|
@ -396,6 +396,9 @@ 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',
|
||||
|
|
@ -569,6 +572,9 @@ class Options:
|
|||
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
|
||||
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'})
|
||||
|
|
|
|||
|
|
@ -39,7 +39,9 @@ struct MenuItem {
|
|||
};
|
||||
|
||||
typedef struct {
|
||||
monotonic_t visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, click_interval;
|
||||
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;
|
||||
double wheel_scroll_multiplier, touch_scroll_multiplier;
|
||||
int wheel_scroll_min_lines;
|
||||
bool enable_audio_bell;
|
||||
|
|
@ -286,7 +288,8 @@ typedef struct {
|
|||
} tab_bar_edge_color;
|
||||
bool tab_bar_data_updated;
|
||||
bool is_focused;
|
||||
monotonic_t cursor_blink_zero_time, last_mouse_activity_at;
|
||||
monotonic_t cursor_blink_zero_time, last_mouse_activity_at, mouse_activate_deadline;
|
||||
int mouse_show_threshold;
|
||||
bool has_received_cursor_pos_event;
|
||||
double mouse_x, mouse_y;
|
||||
bool mouse_button_pressed[32];
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ 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.color23, Color(255, 0, 0))
|
||||
self.assertFalse(opts.keyboard_modes[''].keymap)
|
||||
opts = p('clear_all_shortcuts y', 'map f1 next_window')
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue