diff --git a/kitty/glfw.c b/kitty/glfw.c index 52c8b495c..f4dc67843 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -36,7 +36,7 @@ typedef struct { PyObject_HEAD GLFWwindow *window; - PyObject *framebuffer_size_callback, *char_mods_callback, *key_callback, *mouse_button_callback, *scroll_callback, *cursor_pos_callback, *window_focus_callback; + PyObject *framebuffer_size_callback, *char_mods_callback, *key_callback, *window_focus_callback; GLFWcursor *standard_cursor, *click_cursor, *arrow_cursor; } WindowWrapper; @@ -68,6 +68,7 @@ key_callback(GLFWwindow UNUSED *w, int key, int scancode, int action, int mods) } extern void mouse_event(int, int); +extern void scroll_event(double, double); static void mouse_button_callback(GLFWwindow *w, int button, int action, int mods) { @@ -78,7 +79,6 @@ mouse_button_callback(GLFWwindow *w, int button, int action, int mods) { global_state.mouse_button_pressed[button] = action == GLFW_PRESS ? true : false; mouse_event(button, mods); } - /* WINDOW_CALLBACK(mouse_button_callback, "iii", button, action, mods); */ } static void @@ -89,7 +89,6 @@ cursor_pos_callback(GLFWwindow *w, double x, double y) { global_state.cursor_blink_zero_time = now; global_state.mouse_x = x; global_state.mouse_y = y; mouse_event(-1, 0); - /* WINDOW_CALLBACK(cursor_pos_callback, "dd", x, y); */ } static void @@ -97,7 +96,7 @@ scroll_callback(GLFWwindow *w, double xoffset, double yoffset) { if (!global_state.mouse_visible) { glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL); global_state.mouse_visible = true; } double now = monotonic(); global_state.last_mouse_activity_at = now; - WINDOW_CALLBACK(scroll_callback, "dd", xoffset, yoffset); + scroll_event(xoffset, yoffset); } static void @@ -147,10 +146,10 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { set_mouse_cursor(0); glfwSetFramebufferSizeCallback(self->window, framebuffer_size_callback); glfwSetCharModsCallback(self->window, char_mods_callback); - glfwSetKeyCallback(self->window, key_callback); glfwSetMouseButtonCallback(self->window, mouse_button_callback); glfwSetScrollCallback(self->window, scroll_callback); glfwSetCursorPosCallback(self->window, cursor_pos_callback); + glfwSetKeyCallback(self->window, key_callback); glfwSetWindowFocusCallback(self->window, window_focus_callback); } return (PyObject*)self; @@ -263,7 +262,7 @@ glfw_init_hint_string(PyObject UNUSED *self, PyObject *args) { static void dealloc(WindowWrapper* self) { the_window = NULL; - Py_CLEAR(self->framebuffer_size_callback); Py_CLEAR(self->char_mods_callback); Py_CLEAR(self->key_callback); Py_CLEAR(self->mouse_button_callback); Py_CLEAR(self->scroll_callback); Py_CLEAR(self->cursor_pos_callback); Py_CLEAR(self->window_focus_callback); + Py_CLEAR(self->framebuffer_size_callback); Py_CLEAR(self->char_mods_callback); Py_CLEAR(self->key_callback); Py_CLEAR(self->window_focus_callback); if (self->window != NULL) glfwDestroyWindow(self->window); Py_TYPE(self)->tp_free((PyObject*)self); } @@ -452,9 +451,6 @@ static PyMemberDef members[] = { CBE(framebuffer_size_callback), CBE(char_mods_callback), CBE(key_callback), - CBE(mouse_button_callback), - CBE(scroll_callback), - CBE(cursor_pos_callback), CBE(window_focus_callback), {NULL} #undef CBE diff --git a/kitty/mouse.c b/kitty/mouse.c index 0ee5579b0..eaba0cb00 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -8,6 +8,7 @@ #include "state.h" #include "screen.h" #include "lineops.h" +#include #include extern void set_mouse_cursor(MouseShape); @@ -203,23 +204,56 @@ handle_tab_bar_mouse(int button, int UNUSED modifiers) { call_boss(activate_tab_at, "d", global_state.mouse_x); } -void -mouse_event(int button, int modifiers) { - MouseShape old_cursor = mouse_cursor_shape; - bool in_tab_bar = global_state.num_tabs > 1 && global_state.mouse_y >= global_state.viewport_height - global_state.cell_height ? true : false; - if (in_tab_bar) { - mouse_cursor_shape = HAND; - handle_tab_bar_mouse(button, modifiers); - } else { +static inline Window* +window_for_event(unsigned int *window_idx, bool *in_tab_bar) { + *in_tab_bar = global_state.num_tabs > 1 && global_state.mouse_y >= global_state.viewport_height - global_state.cell_height ? true : false; + if (!*in_tab_bar) { Tab *t = global_state.tabs + global_state.active_tab; for (unsigned int i = 0; i < t->num_windows; i++) { if (contains_mouse(t->windows + i) && t->windows[i].render_data.screen) { - handle_event(t->windows + i, button, modifiers, i); - break; + *window_idx = i; return t->windows + i; } } } + return NULL; + +} + +void +mouse_event(int button, int modifiers) { + MouseShape old_cursor = mouse_cursor_shape; + bool in_tab_bar; + unsigned int window_idx; + Window *w = window_for_event(&window_idx, &in_tab_bar); + if (in_tab_bar) { + mouse_cursor_shape = HAND; + handle_tab_bar_mouse(button, modifiers); + } else if(w) { + handle_event(w, button, modifiers, window_idx); + } if (mouse_cursor_shape != old_cursor) { set_mouse_cursor(mouse_cursor_shape); } } + +void +scroll_event(double UNUSED xoffset, double yoffset) { + int s = (int) round(yoffset * OPT(wheel_scroll_multiplier)); + if (s == 0) return; + bool upwards = s > 0 ? true : false; + bool in_tab_bar; + unsigned int window_idx; + Window *w = window_for_event(&window_idx, &in_tab_bar); + if (w) { + 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) { + // TODO: Implement this + } else { + // TODO: Implement this, writing a up arrow or down arrow key event to the child + } + } + } +} diff --git a/kitty/state.c b/kitty/state.c index be216970a..cf9e30e06 100644 --- a/kitty/state.c +++ b/kitty/state.c @@ -127,6 +127,7 @@ PYWRAP1(set_options) { S(cursor_shape, PyLong_AsLong); S(cursor_opacity, PyFloat_AsDouble); S(mouse_hide_wait, PyFloat_AsDouble); + S(wheel_scroll_multiplier, PyFloat_AsDouble); S(open_url_modifiers, PyLong_AsUnsignedLong); S(click_interval, PyFloat_AsDouble); PyObject *chars = PyObject_GetAttrString(args, "select_by_word_characters"); diff --git a/kitty/state.h b/kitty/state.h index a8ae6472f..c3de33b0c 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -10,7 +10,7 @@ #define OPT(name) global_state.opts.name typedef struct { - double visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, click_interval, cursor_opacity; + double visual_bell_duration, cursor_blink_interval, cursor_stop_blinking_after, mouse_hide_wait, click_interval, cursor_opacity, wheel_scroll_multiplier; bool enable_audio_bell; CursorShape cursor_shape; unsigned int open_url_modifiers;