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:
Kovid Goyal
2018-08-24 11:00:58 +05:30
parent 0e0e25f986
commit 009ef54de7
13 changed files with 56 additions and 46 deletions

View File

@@ -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') # {{{

View File

@@ -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
View File

@@ -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.
*

View File

@@ -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;
}

View File

@@ -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);
}
}
}

View File

@@ -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;