Appends a synthetic TabBarData(tab_id=-1, title='+') to tab_bar_data
while a window drag is active. The existing tab highlight machinery
(_set_drag_target_tab / mark_tab_bar_dirty) handles hover highlighting
with no extra state. Dropping on it falls through the existing new-tab
branch in on_window_drop (tab_for_id(-1) returns None). Mark tab bar
dirty at drag start so the indicator appears immediately, and again
after set_window_being_dragged() on drop so it clears right away.
splits.py: insert_window_next_to called split_and_add on self.pairs_root
instead of on the pair found by pair_for_window. split_and_add only handles
direct children, so nested dest windows fell to 'else: self.two = pair',
silently replacing an entire subtree. Lost windows were re-added by
do_layout, producing phantom panes.
tabs.py: on_window_drop returned early (window not found) before calling
_clear_force_show_title_bars, leaving the drag overlay stuck on screen.
quadrant=5: title bar hover — full window overlay + title bar highlight
quadrant=6: body hover (non-Splits) — full window overlay only
quadrant=1-4: Splits body hover — directional half-window overlay
Previously quadrant=5 was used for all full-window cases, causing
is_drag_target=True to fire on body hover which incorrectly lit up
the title bar highlight whenever hovering any window body.
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#9713Fixes#9715
This ensures that Ctrl+H behaves like Backspace and correctly clears
the pre-edit state, preventing uncommitted characters from remaining
on the screen when using IMEs like the Japanese one on macOS.
When kitty loses focus and the user scrolls in another
application, X11 XI scroll valuators accumulate position values. When the
user returns to kitty and scrolls, delta (value - v->value) uses the stale
pre-focus-loss value, causing a massive unexpected scroll jump.
Fix: reset scroll valuators (mark them uninitialized) on FocusOut so the
first scroll event after focus is regained sets the baseline without firing
a scroll event.
Fixes#9703Fixes#9707
On 32-bit platforms Py_ssize_t is int (signed 32-bit), while
os_window->num_tabs is unsigned int. Direct comparison triggers
-Werror=sign-compare. Cast the unsigned side to Py_ssize_t to
silence the warning. The value can never overflow Py_ssize_t
since num_tabs is bounded by the number of open tabs.
During a window title-bar drag, render a semi-transparent tint over
the destination window to preview the drop outcome:
- Full-window tint (quadrant=5) when hovering any window in swap-based
layouts (Tall, Stack, Fat, etc.) or over a title bar — swap is the
result so the whole window is highlighted.
- Half-window directional tint (quadrant 1-4) when hovering in the
Splits layout — a real directional insert happens so only the target
half is highlighted.
- 150ms fade-in; clears immediately on drop or drag exit.
Implementation follows the visual_bell TINT_PROGRAM infrastructure:
two new Screen fields (start_drag_overlay_at, drag_overlay_quadrant),
draw_drag_preview_overlay() in shaders.c called from draw_cells() after
both render paths, set_window_drag_overlay() C→Python bridge in state.c,
and the same child-monitor.c needs_render + set_maximum_wait hooks that
visual_bell uses to keep frames firing during animation.
Layout detection uses hasattr(layout, 'insert_window_next_to') — the
same guard _insert_window_in_direction uses internally — so the overlay
always matches the actual drop behavior.
- start_window_drag now force-shows title bars on all tabs during a drag
so the user can actually drop onto them to trigger a swap. The cleanup
code to clear force_show_title_bars already existed but the corresponding
set was never written.
- on_window_drop_move now only highlights a destination window's title bar
when the cursor is actually within the title bar row, so the visual
feedback accurately reflects what will happen on drop (swap vs split).
- Dropping a window onto the empty space in the tab bar (past the last tab)
now creates a new tab and moves the window into it.