From 80367cdb7b37970b18a8676acf33ecb3f1370f8d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 22 Feb 2026 06:39:57 +0530 Subject: [PATCH] Add option to control tab bar drag threshold --- kitty/options/definition.py | 15 +++++++++++---- kitty/options/parse.py | 6 ++++++ kitty/options/to-c-generated.h | 15 +++++++++++++++ kitty/options/types.py | 2 ++ kitty/tabs.py | 3 ++- 5 files changed, 36 insertions(+), 5 deletions(-) diff --git a/kitty/options/definition.py b/kitty/options/definition.py index 4e5639088..f8521bcfe 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -1688,8 +1688,7 @@ long_text=''' Background color for the tab bar. Defaults to using the terminal background color. -''' - ) +''') opt('tab_bar_margin_color', 'none', option_type='to_color_or_none', ctype='color_or_none_as_int', @@ -1697,8 +1696,16 @@ Color for the tab bar margin area. Defaults to using the terminal background color for margins above and below the tab bar. For side margins the default color is chosen to match the background color of the neighboring tab. -''' - ) +''') + +opt('tab_bar_drag_threshold', '5', option_type='positive_int', + long_text=''' +Control when dragging of tabs to re-order them happens. +The value is the drag threshold in pixels, the distance the mouse must move +before a drag begins. A value of zero disables tab dragging entirely. +Dragging a tab to another kitty window moves it there, while dragging +outside any kitty window detaches it into a new OS window. +''') egr() # }}} diff --git a/kitty/options/parse.py b/kitty/options/parse.py index e5e339fc0..2fff89848 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -1085,6 +1085,9 @@ def macos_colorspace(self, val: str, ans: dict[str, typing.Any]) -> None: def macos_custom_beam_cursor(self, val: str, ans: dict[str, typing.Any]) -> None: ans['macos_custom_beam_cursor'] = to_bool(val) + def macos_dock_badge_on_bell(self, val: str, ans: dict[str, typing.Any]) -> None: + ans['macos_dock_badge_on_bell'] = to_bool(val) + def macos_hide_from_tasks(self, val: str, ans: dict[str, typing.Any]) -> None: ans['macos_hide_from_tasks'] = to_bool(val) @@ -1321,6 +1324,9 @@ def tab_bar_align(self, val: str, ans: dict[str, typing.Any]) -> None: def tab_bar_background(self, val: str, ans: dict[str, typing.Any]) -> None: ans['tab_bar_background'] = to_color_or_none(val) + def tab_bar_drag_threshold(self, val: str, ans: dict[str, typing.Any]) -> None: + ans['tab_bar_drag_threshold'] = positive_int(val) + def tab_bar_edge(self, val: str, ans: dict[str, typing.Any]) -> None: ans['tab_bar_edge'] = tab_bar_edge(val) diff --git a/kitty/options/to-c-generated.h b/kitty/options/to-c-generated.h index f23c3a359..0a9d7b2b0 100644 --- a/kitty/options/to-c-generated.h +++ b/kitty/options/to-c-generated.h @@ -798,6 +798,19 @@ convert_from_opts_window_alert_on_bell(PyObject *py_opts, Options *opts) { Py_DECREF(ret); } +static void +convert_from_python_macos_dock_badge_on_bell(PyObject *val, Options *opts) { + opts->macos_dock_badge_on_bell = PyObject_IsTrue(val); +} + +static void +convert_from_opts_macos_dock_badge_on_bell(PyObject *py_opts, Options *opts) { + PyObject *ret = PyObject_GetAttrString(py_opts, "macos_dock_badge_on_bell"); + if (ret == NULL) return; + convert_from_python_macos_dock_badge_on_bell(ret, opts); + Py_DECREF(ret); +} + static void convert_from_python_bell_path(PyObject *val, Options *opts) { bell_path(val, opts); @@ -1494,6 +1507,8 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) { if (PyErr_Occurred()) return false; convert_from_opts_window_alert_on_bell(py_opts, opts); if (PyErr_Occurred()) return false; + convert_from_opts_macos_dock_badge_on_bell(py_opts, opts); + if (PyErr_Occurred()) return false; convert_from_opts_bell_path(py_opts, opts); if (PyErr_Occurred()) return false; convert_from_opts_linux_bell_theme(py_opts, opts); diff --git a/kitty/options/types.py b/kitty/options/types.py index f4ab3cce6..c8c192d80 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -449,6 +449,7 @@ 'tab_activity_symbol', 'tab_bar_align', 'tab_bar_background', + 'tab_bar_drag_threshold', 'tab_bar_edge', 'tab_bar_filter', 'tab_bar_margin_color', @@ -639,6 +640,7 @@ class Options: tab_activity_symbol: str = '' tab_bar_align: choices_for_tab_bar_align = 'left' tab_bar_background: kitty.fast_data_types.Color | None = None + tab_bar_drag_threshold: int = 5 tab_bar_edge: int = 8 tab_bar_filter: str = '' tab_bar_margin_color: kitty.fast_data_types.Color | None = None diff --git a/kitty/tabs.py b/kitty/tabs.py index 4dd3ea93e..0f369daf5 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -1662,7 +1662,8 @@ def handle_tab_bar_mouse(self, x: float, y: float, button: int, modifiers: int, if button == -1: # motion dragged_tab_id, drag_started, start_x, start_y = get_tab_being_dragged() if dragged_tab_id and self.tab_for_id(dragged_tab_id) is not None and not drag_started: - if math.sqrt((x-start_x)**2 + (y-start_y)**2) > 5: + threshold = get_options().tab_bar_drag_threshold + if threshold and math.sqrt((x-start_x)**2 + (y-start_y)**2) > threshold: set_tab_being_dragged(dragged_tab_id, True, start_x, start_y) request_callback_with_thumbnail("start_tab_drag", self.os_window_id) return