Nicer fix for enter event mouse tracking

Send an explicit mouse event to child when pointer enters window instead
of relying on GLFW to send a cursor position update event.
This commit is contained in:
Kovid Goyal 2025-03-04 11:29:29 +05:30
parent bfdc098236
commit 27df509206
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
5 changed files with 28 additions and 15 deletions

4
glfw/input.c vendored
View file

@ -728,10 +728,8 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
window->cursorMode = value;
double x, y;
_glfwPlatformGetCursorPos(window, &x, &y);
_glfwPlatformGetCursorPos(window, &window->virtualCursorPosX, &window->virtualCursorPosY);
_glfwPlatformSetCursorMode(window, value);
_glfwInputCursorPos(window, x, y);
}
else if (mode == GLFW_STICKY_KEYS)
{

3
glfw/wl_init.c vendored
View file

@ -96,9 +96,6 @@ pointerHandleEnter(
window->wl.cursorPosY = y;
_glfwPlatformSetCursor(window, window->wl.currentCursor);
_glfwInputCursorEnter(window, true);
// Ensure kitty updates the mouse position, see https://github.com/kovidgoyal/kitty/issues/8397
_glfwInputCursorPos(window, x, y);
_glfw.wl.cursorPreviousShape = GLFW_INVALID_CURSOR;
}
}

View file

@ -317,7 +317,7 @@ bool colorprofile_pop_colors(ColorProfile*, unsigned int);
void colorprofile_report_stack(ColorProfile*, unsigned int*, unsigned int*);
void set_mouse_cursor(MouseShape);
void enter_event(void);
void enter_event(int modifiers);
void mouse_event(const int, int, int);
void focus_in_event(void);
void scroll_event(double, double, int, int);

View file

@ -446,12 +446,12 @@ cursor_enter_callback(GLFWwindow *w, int entered) {
double x, y;
glfwGetCursorPos(w, &x, &y);
debug_input("Mouse cursor entered window: %llu at %fx%f\n", global_state.callback_os_window->id, x, y);
show_mouse_cursor(w);
monotonic_t now = monotonic();
global_state.callback_os_window->last_mouse_activity_at = now;
global_state.callback_os_window->mouse_x = x * global_state.callback_os_window->viewport_x_ratio;
global_state.callback_os_window->mouse_y = y * global_state.callback_os_window->viewport_y_ratio;
if (is_window_ready_for_callbacks()) enter_event();
show_mouse_cursor(w); // might result in a call to cursor_pos_callback which will set callback_os_window to NULL
if (is_window_ready_for_callbacks()) enter_event(mods_at_last_key_or_button_event);
request_tick_callback();
} else debug_input("Mouse cursor left window: %llu\n", global_state.callback_os_window->id);
global_state.callback_os_window = NULL;

View file

@ -360,6 +360,14 @@ detect_url(Screen *screen, unsigned int x, unsigned int y) {
} else set_mouse_cursor_for_screen(screen);
}
static bool
should_handle_in_kitty(Window *w, Screen *screen, int button) {
bool in_tracking_mode = (
screen->modes.mouse_tracking_mode == ANY_MODE ||
(screen->modes.mouse_tracking_mode == MOTION_MODE && button >= 0));
return !in_tracking_mode || global_state.active_drag_in_window == w->id;
}
static bool
set_mouse_position(Window *w, bool *mouse_cell_changed, bool *cell_half_changed) {
unsigned int x = 0, y = 0;
@ -385,11 +393,7 @@ HANDLER(handle_move_event) {
if (!set_mouse_position(w, &mouse_cell_changed, &cell_half_changed)) return;
Screen *screen = w->render_data.screen;
if (OPT(detect_urls)) detect_url(screen, w->mouse_pos.cell_x, w->mouse_pos.cell_y);
bool in_tracking_mode = (
screen->modes.mouse_tracking_mode == ANY_MODE ||
(screen->modes.mouse_tracking_mode == MOTION_MODE && button >= 0));
bool handle_in_kitty = !in_tracking_mode || global_state.active_drag_in_window == w->id;
if (handle_in_kitty) {
if (should_handle_in_kitty(w, screen, button)) {
handle_mouse_movement_in_kitty(w, button, mouse_cell_changed | cell_half_changed);
} else {
if (!mouse_cell_changed && screen->modes.mouse_tracking_protocol != SGR_PIXEL_PROTOCOL) return;
@ -691,7 +695,7 @@ update_mouse_pointer_shape(void) {
}
void
enter_event(void) {
enter_event(int modifiers) {
#ifdef __APPLE__
// On cocoa there is no way to configure the window manager to
// focus windows on mouse enter, so we do it ourselves
@ -699,6 +703,20 @@ enter_event(void) {
focus_os_window(global_state.callback_os_window, false, NULL);
}
#endif
// If the mouse is grabbed send a move event to update the cursor position
// since the last report.
if (global_state.redirect_mouse_handling || global_state.active_drag_in_window || global_state.tracked_drag_in_window) return;
unsigned window_idx; bool in_tab_bar;
Window *w = window_for_event(&window_idx, &in_tab_bar);
if (!w || in_tab_bar) return;
bool mouse_cell_changed = false;
bool cell_half_changed = false;
if (!set_mouse_position(w, &mouse_cell_changed, &cell_half_changed)) return;
Screen *screen = w->render_data.screen;
int button = currently_pressed_button();
if (!screen || should_handle_in_kitty(w, screen, button)) return;
int sz = encode_mouse_button(w, button, button >=0 ? DRAG : MOVE, modifiers);
if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, ESC_CSI, mouse_event_buf); }
}
static void