mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-13 04:03:16 +02:00
Implement high precision scrolling with the trackpad on platforms such as macOS and Wayland that implement it.
Fixes #819. Note that I have no idea whether the code works well on retina screens, might have to multiple the pixel count by the scale factor on those screens?
This commit is contained in:
@@ -302,8 +302,9 @@ INPUT_LINE_NUMBER in the command line above will be replaced by an integer
|
||||
representing which line should be at the top of the screen.'''))
|
||||
|
||||
o('wheel_scroll_multiplier', 5.0, long_text=_('''
|
||||
Modify the amount scrolled by the mouse wheel or touchpad. Use
|
||||
negative numbers to change scroll direction.'''))
|
||||
Modify the amount scrolled by the mouse wheel. Note this is only used for low
|
||||
precision scrolling devices, not for high precision scrolling on platforms such
|
||||
as macOS and Wayland. Use negative numbers to change scroll direction.'''))
|
||||
# }}}
|
||||
|
||||
g('mouse') # {{{
|
||||
|
||||
@@ -284,7 +284,7 @@ void enter_event();
|
||||
void mouse_event(int, int);
|
||||
void focus_in_event();
|
||||
void wakeup_io_loop(bool);
|
||||
void scroll_event(double, double);
|
||||
void scroll_event(double, double, int);
|
||||
void fake_scroll(int, bool);
|
||||
void set_special_key_combo(int glfw_key, int mods, bool is_native);
|
||||
void on_key_input(int key, int scancode, int action, int mods, const char*, int);
|
||||
|
||||
2
kitty/glfw-wrapper.h
generated
2
kitty/glfw-wrapper.h
generated
@@ -1141,7 +1141,7 @@ typedef void (* GLFWcursorenterfun)(GLFWwindow*,int);
|
||||
*
|
||||
* @ingroup input
|
||||
*/
|
||||
typedef void (* GLFWscrollfun)(GLFWwindow*,double,double);
|
||||
typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
|
||||
|
||||
/*! @brief The function signature for key callbacks.
|
||||
*
|
||||
|
||||
@@ -178,12 +178,12 @@ cursor_pos_callback(GLFWwindow *w, double x, double y) {
|
||||
}
|
||||
|
||||
static void
|
||||
scroll_callback(GLFWwindow *w, double xoffset, double yoffset) {
|
||||
scroll_callback(GLFWwindow *w, double xoffset, double yoffset, int flags) {
|
||||
if (!set_callback_window(w)) return;
|
||||
show_mouse_cursor(w);
|
||||
double now = monotonic();
|
||||
global_state.callback_os_window->last_mouse_activity_at = now;
|
||||
if (is_window_ready_for_callbacks()) scroll_event(xoffset, yoffset);
|
||||
if (is_window_ready_for_callbacks()) scroll_event(xoffset, yoffset, flags);
|
||||
global_state.callback_os_window = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -527,13 +527,7 @@ mouse_event(int button, int modifiers) {
|
||||
}
|
||||
|
||||
void
|
||||
scroll_event(double UNUSED xoffset, double yoffset) {
|
||||
// glfw inverts the y-axis when reporting scroll events under wayland
|
||||
// Until this is fixed in upstream, invert y ourselves.
|
||||
if (global_state.is_wayland) yoffset *= -1;
|
||||
int s = (int) round(yoffset * OPT(wheel_scroll_multiplier));
|
||||
if (s == 0) return;
|
||||
bool upwards = s > 0;
|
||||
scroll_event(double UNUSED xoffset, double yoffset, int flags) {
|
||||
bool in_tab_bar;
|
||||
unsigned int window_idx = 0;
|
||||
Window *w = window_for_event(&window_idx, &in_tab_bar);
|
||||
@@ -544,17 +538,36 @@ scroll_event(double UNUSED xoffset, double yoffset) {
|
||||
Tab *t = global_state.callback_os_window->tabs + global_state.callback_os_window->active_tab;
|
||||
if (t) w = t->windows + t->active_window;
|
||||
}
|
||||
if (w) {
|
||||
Screen *screen = w->render_data.screen;
|
||||
if (screen->linebuf == screen->main_linebuf) {
|
||||
screen_history_scroll(screen, abs(s), upwards);
|
||||
if (!w) return;
|
||||
|
||||
int s;
|
||||
if (flags & 1) {
|
||||
if (yoffset * global_state.callback_os_window->pending_scroll_pixels < 0) {
|
||||
global_state.callback_os_window->pending_scroll_pixels = 0; // change of direction
|
||||
}
|
||||
double pixels = global_state.callback_os_window->pending_scroll_pixels + yoffset;
|
||||
if (fabs(pixels) < global_state.callback_os_window->fonts_data->cell_height) {
|
||||
global_state.callback_os_window->pending_scroll_pixels = pixels;
|
||||
return;
|
||||
}
|
||||
s = abs(((int)round(pixels))) / global_state.callback_os_window->fonts_data->cell_height;
|
||||
if (pixels < 0) s *= -1;
|
||||
global_state.callback_os_window->pending_scroll_pixels = pixels - s;
|
||||
} else {
|
||||
s = (int) round(yoffset * OPT(wheel_scroll_multiplier));
|
||||
global_state.callback_os_window->pending_scroll_pixels = 0;
|
||||
}
|
||||
if (s == 0) return;
|
||||
bool upwards = s > 0;
|
||||
Screen *screen = w->render_data.screen;
|
||||
if (screen->linebuf == screen->main_linebuf) {
|
||||
screen_history_scroll(screen, abs(s), upwards);
|
||||
} else {
|
||||
if (screen->modes.mouse_tracking_mode) {
|
||||
int sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : GLFW_MOUSE_BUTTON_5, PRESS, 0);
|
||||
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
|
||||
} else {
|
||||
if (screen->modes.mouse_tracking_mode) {
|
||||
int sz = encode_mouse_event(w, upwards ? GLFW_MOUSE_BUTTON_4 : GLFW_MOUSE_BUTTON_5, PRESS, 0);
|
||||
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, CSI, mouse_event_buf); }
|
||||
} else {
|
||||
fake_scroll(abs(s), upwards);
|
||||
}
|
||||
fake_scroll(abs(s), upwards);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ typedef struct {
|
||||
float background_opacity;
|
||||
FONTS_DATA_HANDLE fonts_data;
|
||||
id_type temp_font_group_id;
|
||||
double pending_scroll_pixels;
|
||||
} OSWindow;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user