From 7c79e2fc9eb531879142ba243846099ef6cd434f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Mar 2026 02:21:50 +0000 Subject: [PATCH] Fix text selection via click-and-drag in unfocused splits The regression was introduced by commit b277a016b which added an early `return` in handle_button_event that prevented kitty's internal text selection from starting on focus-transfer clicks to unfocused splits. Changes: - In handle_button_event: replace the early return with a local suppress_child_forwarding flag that prevents PRESS from being forwarded to child processes in mouse-tracking mode, while still allowing dispatch_mouse_event to run (which starts text selection) - In mouse_event's active_drag_in_window release path: clear suppress_left_mouse_release to prevent stale flags after drags Fixes #9713 Fixes #9715 --- kitty/mouse.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/kitty/mouse.c b/kitty/mouse.c index 65d331e75..9a72d2de9 100644 --- a/kitty/mouse.c +++ b/kitty/mouse.c @@ -839,13 +839,16 @@ HANDLER(handle_button_event) { if (handle_scrollbar_mouse(w, button, is_release ? RELEASE : PRESS, modifiers)) return; + bool suppress_child_forwarding = false; if (osw->is_focused && window_idx != t->active_window && !is_release) { call_boss(switch_focus_to_in_active_tab, "K", t->windows[window_idx].id); if (button == GLFW_MOUSE_BUTTON_LEFT) { - // Treat split-focus transfer clicks as focus-only and suppress - // the matching release to avoid release-without-press reports. + // Treat split-focus transfer clicks as focus-only for child processes: + // suppress forwarding the left press and matching release to the child + // to avoid release-without-press reports. Still allow kitty to process + // the event internally (e.g., start text selection via click-and-drag). osw->suppress_left_mouse_release = true; - return; + suppress_child_forwarding = true; } } @@ -856,7 +859,7 @@ HANDLER(handle_button_event) { if (!set_mouse_position(w, &a, &b)) return; id_type wid = w->id; if (!dispatch_mouse_event(w, button, is_release ? -1 : 1, modifiers, screen->modes.mouse_tracking_mode != 0)) { - if (screen->modes.mouse_tracking_mode != 0) { + if (!suppress_child_forwarding && screen->modes.mouse_tracking_mode != 0) { int sz = encode_mouse_button(w, button, is_release ? RELEASE : PRESS, modifiers); if (sz > 0) { mouse_event_buf[sz] = 0; write_escape_code_to_child(screen, ESC_CSI, mouse_event_buf); } } @@ -1211,6 +1214,10 @@ mouse_event(const int button, int modifiers, int action) { w = window_for_id(global_state.active_drag_in_window); if (w) { end_drag(w); + // Clear any stale suppress flag that was set during a focus-transfer + // press, since the drag release bypasses handle_button_event where + // it would normally be cleared. + if (osw) osw->suppress_left_mouse_release = false; debug("handled as drag end\n"); dispatch_possible_click(w, button, modifiers); return;