diff --git a/docs/changelog.rst b/docs/changelog.rst index 499a8f42e..852bf8a5a 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -135,6 +135,8 @@ Detailed list of changes - Wayland: Fix touchpads and high resolution wheels not scrolling at the same speed on monitors with different scales (:iss:`4703`) +- Add an option :opt:`wheel_scroll_min_lines` to set the minimum number of lines for mouse wheel scrolling (:pull:`4710`) + 0.24.2 [2022-02-03] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/kitty/mouse.c b/kitty/mouse.c index 5f34fcb31..91fe06389 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -888,9 +888,13 @@ scroll_event(double UNUSED xoffset, double yoffset, int flags, int modifiers) { } else { SCALE_SCROLL(wheel_scroll_multiplier); s = (int) round(yoffset); + int min_lines = OPT(wheel_scroll_min_lines); + if (min_lines > 0 && abs(s) < min_lines) s = yoffset > 0 ? min_lines : -min_lines; + // Add the minimum number of lines when it is negative and the scrolling acceleration takes effect + else if (min_lines < 0) s = yoffset > 0 ? s - min_lines : s + min_lines; // apparently on cocoa some mice generate really small yoffset values // when scrolling slowly https://github.com/kovidgoyal/kitty/issues/1238 - if (s == 0 && yoffset != 0) s = yoffset > 0 ? 1 : -1; + if (s == 0) s = yoffset > 0 ? 1 : -1; screen->pending_scroll_pixels = 0; } #undef SCALE_SCROLL diff --git a/kitty/options/definition.py b/kitty/options/definition.py index cb537a942..81c5582b8 100644 --- a/kitty/options/definition.py +++ b/kitty/options/definition.py @@ -347,6 +347,16 @@ as macOS and Wayland. Use negative numbers to change scroll direction. ''' ) +opt('wheel_scroll_min_lines', '1', + option_type='int', ctype='int', + long_text=''' +The minimum number of lines scrolled by the mouse wheel. The scrolling +acceleration only takes effect after it reaches the number. Note that this is +only used for low precision scrolling devices. With a negative number, the +minimum number of lines will always be added. +''' + ) + opt('touch_scroll_multiplier', '1.0', option_type='float', ctype='double', long_text=''' diff --git a/kitty/options/parse.py b/kitty/options/parse.py index effa9b7cf..3237b7e79 100644 --- a/kitty/options/parse.py +++ b/kitty/options/parse.py @@ -1272,6 +1272,9 @@ class Parser: def wayland_titlebar_color(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: ans['wayland_titlebar_color'] = titlebar_color(val) + def wheel_scroll_min_lines(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: + ans['wheel_scroll_min_lines'] = int(val) + def wheel_scroll_multiplier(self, val: str, ans: typing.Dict[str, typing.Any]) -> None: ans['wheel_scroll_multiplier'] = float(val) diff --git a/kitty/options/to-c-generated.h b/kitty/options/to-c-generated.h index 3a4c24401..3706010c5 100644 --- a/kitty/options/to-c-generated.h +++ b/kitty/options/to-c-generated.h @@ -187,6 +187,19 @@ convert_from_opts_wheel_scroll_multiplier(PyObject *py_opts, Options *opts) { Py_DECREF(ret); } +static void +convert_from_python_wheel_scroll_min_lines(PyObject *val, Options *opts) { + opts->wheel_scroll_min_lines = PyLong_AsLong(val); +} + +static void +convert_from_opts_wheel_scroll_min_lines(PyObject *py_opts, Options *opts) { + PyObject *ret = PyObject_GetAttrString(py_opts, "wheel_scroll_min_lines"); + if (ret == NULL) return; + convert_from_python_wheel_scroll_min_lines(ret, opts); + Py_DECREF(ret); +} + static void convert_from_python_touch_scroll_multiplier(PyObject *val, Options *opts) { opts->touch_scroll_multiplier = PyFloat_AsDouble(val); @@ -1023,6 +1036,8 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) { if (PyErr_Occurred()) return false; convert_from_opts_wheel_scroll_multiplier(py_opts, opts); if (PyErr_Occurred()) return false; + convert_from_opts_wheel_scroll_min_lines(py_opts, opts); + if (PyErr_Occurred()) return false; convert_from_opts_touch_scroll_multiplier(py_opts, opts); if (PyErr_Occurred()) return false; convert_from_opts_mouse_hide_wait(py_opts, opts); diff --git a/kitty/options/types.py b/kitty/options/types.py index 3cbf5c7c7..9919eae0f 100644 --- a/kitty/options/types.py +++ b/kitty/options/types.py @@ -437,6 +437,7 @@ option_names = ( # {{{ 'visual_window_select_characters', 'watcher', 'wayland_titlebar_color', + 'wheel_scroll_min_lines', 'wheel_scroll_multiplier', 'window_alert_on_bell', 'window_border_width', @@ -580,6 +581,7 @@ class Options: visual_bell_duration: float = 0 visual_window_select_characters: str = '1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ' wayland_titlebar_color: int = 0 + wheel_scroll_min_lines: int = 1 wheel_scroll_multiplier: float = 5.0 window_alert_on_bell: bool = True window_border_width: typing.Tuple[float, str] = (0.5, 'pt') diff --git a/kitty/state.h b/kitty/state.h index cbb17fdf0..7ff75af0c 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -24,6 +24,7 @@ typedef struct { typedef struct { monotonic_t visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, click_interval; double wheel_scroll_multiplier, touch_scroll_multiplier; + int wheel_scroll_min_lines; bool enable_audio_bell; CursorShape cursor_shape; float cursor_beam_thickness;