133 Commits

Author SHA1 Message Date
Kovid Goyal
238573e799 Fix splits layout options serialization
Fixes #10124
2026-06-10 07:34:47 +05:30
Mark Stuart
852fc4a662 Add equalize action and equalize_on_close option to Splits layout
Adds an `equalize` layout action that redistributes split sizes so each
window receives a proportional share of space along each axis.

Also adds an `equalize_on_close` layout option that automatically
equalizes splits whenever a window is closed, keeping the remaining
windows balanced without requiring an explicit key binding.

These two features compose well. For example, to keep splits balanced
at all times - equalizing on every open and close:

    enabled_layouts splits:equalize_on_close=true
    map ctrl+' combine : launch --location=hsplit --cwd=current : layout_action equalize
    map ctrl+/ combine : launch --location=vsplit --cwd=current : layout_action equalize

A standalone key binding for manual rebalancing is also supported:

    map ctrl+shift+e layout_action equalize
2026-05-29 20:02:42 +01:00
copilot-swe-agent[bot]
20185fc317 Fix display corruption when maximizing horizontal split with window_padding_width >= 4 (issue #9946)
Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/3b0c9eab-24ba-4934-a941-be477477cee4

Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com>
2026-05-01 15:04:46 +00:00
Kovid Goyal
fcb260bdfa Sort imports 2026-04-19 21:53:09 +05:30
Kovid Goyal
04fcac72ec Update minimum python to 3.11 from 3.10
3.10 is failing in CI and I cant be arsed to figure out why. It's anyway
a few months from EOL
2026-04-19 21:41:58 +05:30
copilot-swe-agent[bot]
96d10e51a0 Fix drag resize direction bugs and add comprehensive tests
Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/12198e55-3901-439b-9fba-9b5f5b470416

Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com>
2026-04-01 03:48:49 +00:00
copilot-swe-agent[bot]
c3a111fbd2 Fix inverted border drag direction in splits layout
Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/10200944-3143-4347-880c-f4d5b96749f5

Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com>
2026-03-31 16:28:19 +00:00
Kovid Goyal
3d369f8632 Cleanup handling of drag_overlay_mode 2026-03-28 13:26:56 +05:30
mcrmck
6c37c1c391 Fix mypy: annotate drag_overlay_mode with full union type in Vertical and Tall
Bare literal assignments (drag_overlay_mode = 'axis_y') cause mypy to
narrow-infer the type as Literal['axis_y'] on the parent class, making
the subclass override (Horizontal = 'axis_x', Fat = 'axis_x') an
incompatible assignment. Fix by explicitly annotating Vertical and Tall
with the full union type from the base class, so the declared type stays
wide and subclasses can freely assign any valid mode.

Also removes unused ClassVar/Literal imports from splits.py.
2026-03-27 02:25:35 -04:00
mcrmck
d1b8df6975 Fix mypy error: remove narrowing ClassVar[Literal] annotations from layout subclasses
Horizontal extends Vertical, and Fat extends Tall. Declaring
drag_overlay_mode with a narrower Literal type in the subclass
conflicts with the parent's declared type, causing mypy error
"Incompatible types in assignment". Since the base Layout class already
declares the full union type, subclasses only need a bare assignment.

Also removes now-unused ClassVar and Literal imports from vertical.py,
tall.py, and grid.py.
2026-03-27 02:17:59 -04:00
mcrmck
a368a90e37 Add directional drag-and-drop inserts for Vertical, Horizontal, Tall, Fat, Grid
Previously, body drops in all non-Splits layouts showed a full-window overlay
and performed a positional swap. This adds proper top/bottom or left/right
half-window overlays and true before/after insertion for the five layouts
Kovid identified.

Architecture:

- New `drag_overlay_mode` ClassVar on Layout ('full'|'axis_y'|'axis_x'|'free')
  controls both overlay display and valid direction axis. Layout subclasses set
  one line; tabs.py and boss.py dispatch on this attribute instead of hasattr.

- New `insert_window_group_next_to(target_group_id, after)` on WindowList
  performs a positional insert (not swap) by popping the active group and
  inserting it before or after the target.

- New base `insert_window_next_to` on Layout uses insert_window_group_next_to
  for axis_x/axis_y layouts and falls back to swap for 'full' (Stack).
  Splits overrides this with its existing tree-based implementation.

- `_insert_window_in_direction` in boss.py collapses from a 7-line hasattr
  branch to a single layout.insert_window_next_to() call.

Direction constraints:
  Vertical, Tall, Grid -> top/bottom (axis_y)
  Horizontal, Fat      -> left/right (axis_x)
  Splits               -> 4-way free (unchanged)
  Stack                -> full-window swap (unchanged)
2026-03-27 02:08:41 -04:00
mcrmck
5c0a4accb3 Fix two bugs: splits layout corruption and overlay stuck on early drop exit
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.
2026-03-20 01:34:01 -04:00
mcrmck
462f7025fb Merge upstream/master into feat-draggable-window-title-bars
Resolves conflict in kitty/tabs.py by keeping both force_show_title_bars
and renaming_in_window fields.
2026-03-17 22:40:28 -04:00
copilot-swe-agent[bot]
551acca0e4 Implement maximize layout action for splits layout
Fixes #9629
Fixes #9630
2026-03-09 15:27:54 +05:30
mcrmck
59c963c481 Add draggable window title bars
Implements drag-to-reorder for window title bars, following up on the
merged window title bar feature (#9450) and the design discussion in #9619.

- Drag a title bar and drop on another title bar to swap positions
- Drop on a window body quadrant (left/right/top/bottom) to insert as
  a directional split; Splits layout uses insert_window_next_to(), other
  layouts fall back to move_window_to_group()
- Drop on a tab bar tab to move the window into that tab
- Drop on another OS window to move into its active tab
- Drop outside kitty to detach into a new OS window
- Tab bar highlights the hovered tab during a window drag, mirroring
  how the destination window title bar is highlighted
- toggle_window_title_bars action temporarily force-shows title bars
  for drag-to-reorder when they are normally hidden, auto-hiding after
  the drag completes
- window_title_bar_drag_threshold option (default 5px) controls how far
  the mouse must move before a drag is initiated; 0 disables dragging

MIME type follows the same convention as tab dragging:
application/net.kovidgoyal.kitty-window-{PID}

Ref: #9619
2026-03-08 20:56:38 -04:00
Kovid Goyal
e1a14551fa Cleanup previous PR 2026-03-05 09:25:10 +05:30
Kovid Goyal
b66703ec85 Merge branch 'pane-title-bar' of https://github.com/mcrmck/kitty 2026-03-05 08:31:50 +05:30
mcrmck
f2ae5d0028 Add window_title_bar_min_windows option, simplify window_title_bar
- Add window_title_bar_min_windows (0=never, 1=always, 2+=threshold)
  similar to tab_bar_min_tabs, to control when title bars appear
- Remove 'none' choice from window_title_bar so it purely controls
  position (top/bottom); disabling is now via min_windows 0
- Only hide title bar for truly empty template strings, not
  whitespace-only, so users can have intentionally blank bars

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 21:14:54 -05:00
mcrmck
dd26469cb3 Rework window title bar architecture per review feedback
- Eliminate double set_geometry() call: removed _apply_window_title_bars()
  which post-processed geometry causing expensive SIGWINCH to children
- Move title bar screen ownership to Window objects instead of central
  manager, with show_title_bar flag set during layout before do_layout()
- Window.set_geometry() now handles title bar geometry internally:
  self.geometry stays at layout-computed value (borders/padding correct),
  only C-side render data diverges via adjusted top/bottom
- Hide title bar for 1-row windows (ynum <= 1)
- Hide title bar when template evaluates to empty/whitespace
- Optimize C render loop: merge title bar GPU prep and draw into existing
  per-window loops, use trd pointer and is_visible=false, use
  num_visible_windows > 1 guard. Eliminates separate iteration passes.
- Simplify WindowTitleBarManager to thin coordinator

Note on C-side GPU prep placement: the suggested patch placed
send_cell_data_to_gpu for title bars inside the is_active_window branch
only. This caused a segfault (NULL deref in gleRunVertexSubmitImmediate)
because inactive windows' title bars had valid screen/geometry but no
GPU data uploaded, yet draw_cells was called for all visible title bars.
Moved to the per-window visibility block alongside the main window's
send_cell_data_to_gpu call so all visible title bars get GPU data
prepared. The draw loop matches the suggested patch exactly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 20:17:38 -05:00
Kovid Goyal
0930535642 Remove debug prints 2026-03-03 13:34:13 +05:30
Kovid Goyal
ad560715a6 Track border rect orientation explicitly 2026-03-02 21:34:48 +05:30
Kovid Goyal
e09e707dc6 Generalize leading edge special case 2026-03-02 19:28:04 +05:30
Kovid Goyal
ba8a8a0980 More work on splits drag resize 2026-03-02 16:43:21 +05:30
Kovid Goyal
c3d26f1cf0 Splits layout: cleanup resize drag handling 2026-03-02 16:17:04 +05:30
Kovid Goyal
a222df75cb Cleanup splits drag resize handling 2026-03-02 12:37:28 +05:30
Kovid Goyal
bc7523fe32 Merge branch 'fix/splits-layout-variable-shadowing' of https://github.com/noomz/kitty 2026-03-02 12:29:06 +05:30
Siriwat Uamganmsup
d5e45cf8d3 Splits layout: Fix variable shadowing in layout_pair causing corrupted pane positions
The for loops iterating over edge_border() results in layout_pair() used
top, bottom, left, right as loop variable names, which shadowed the
function's local variables tracking current layout position. This caused
sibling panes to be positioned at incorrect offsets when splitting a pane
that was itself a nested Pair (e.g. splitting the left pane horizontally
would cause the right pane to shift down half the screen).

Rename loop variables to etop, ebottom, eleft, eright to avoid shadowing.
2026-03-02 13:53:59 +07:00
Kovid Goyal
69b9993804 Fix border directionality in grid layout 2026-03-02 11:28:52 +05:30
Kovid Goyal
4264889e9a Fix border marking in tall/fat layout 2026-03-02 11:22:23 +05:30
Kovid Goyal
68d1a336fe Fix edge detection for borders in vert/horz layouts 2026-03-02 11:04:09 +05:30
mcrmck
cc32af250b Rename pane → window title bar per reviewer feedback
- Rename all options from pane_title_* to window_title_*
- Use foreground/background instead of fg/bg in color option names
- Change color options to to_color_or_none defaulting to None,
  falling back to corresponding tab bar colors
- Add bell_symbol, activity_symbol, progress_percent template vars
  using existing bell_on_tab and tab_activity_symbol options
- Add custom script support via window_title_bar.py in config dir
  (draw_window_title function exposed as {custom} in templates)
- Update C structs, Python references, and regenerate config files

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-01 23:53:28 -05:00
mcrmck
ab3a8ca56a Add pane title bar feature for window splits
Add an optional title bar that displays above or below each window pane
when multiple windows are visible in a tab. This is similar to tmux's
pane-border-format or Terminator's pane title bars.

New configuration options:
- pane_title_bar: none/top/bottom (default: none)
- pane_title_template: f-string template (same syntax as tab_title_template)
- active_pane_title_template: override for active pane
- pane_title_bar_active_fg/bg: colors for active pane title
- pane_title_bar_inactive_fg/bg: colors for inactive pane titles
- pane_title_bar_align: left/center/right text alignment

The title bars are rendered using virtual Screen objects registered with
the GPU, following the same model as the tab bar. Title bars are
automatically hidden when only a single window is visible.

Ref: https://github.com/kovidgoyal/kitty/discussions/9448

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-01 23:52:24 -05:00
Kovid Goyal
3281a8d634 DRYer 2026-03-02 08:45:34 +05:30
Kovid Goyal
6b54c201e5 Track window ids on border rects
More robust. Splits layout still needs work.
2026-03-02 08:31:36 +05:30
Kovid Goyal
2d1d340d41 Work on drag resize for splits layout 2026-02-28 07:37:49 +05:30
copilot-swe-agent[bot]
0ad9a15491 Implement drag resize target selection for splits layout
Fixes #9563
2026-02-26 21:57:43 +05:30
Kovid Goyal
09fcb7cef0 Implement resizing semantics based on layout
Still need to do splits layout but all others should be OK
2026-02-26 20:55:43 +05:30
Kovid Goyal
ccc0ce5ceb Do drag resize by dragging window borders 2026-02-26 17:36:41 +05:30
Kovid Goyal
852db16fc9 Cleanup mouse.c 2026-02-26 14:53:10 +05:30
Kovid Goyal
609f6ed960 Cleanup tracking of drag resize in Boss 2026-02-26 14:17:26 +05:30
mcrmck
02194b6965 Add mouse drag resize for window splits
Enable Ctrl+left-click-drag to resize window splits. Detects which
windows border the click position using neighbor information from the
layout, then resizes in cell-sized increments as the mouse moves.
Shows a move cursor during the drag operation.

Closes kovidgoyal/kitty#5959

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-31 20:22:00 -05:00
Kovid Goyal
df17142ea4 Fix #9355 2026-01-06 08:37:24 +05:30
Kovid Goyal
e49d940621 kitten @ ls: Also output the neighbors for every window 2025-11-16 21:01:55 +05:30
Kovid Goyal
f06f85a9e0 Cleanup previous PR 2025-10-15 09:12:32 +05:30
Jackie Li
6db3441e29 respect draw_window_borders_for_single_window=yes in lgd.draw_minimal_borders 2025-10-14 19:23:35 +01:00
Kovid Goyal
9740861ec5 Splits layout: Fix corrupted layout in some circs
Basically one function was adding a window id instead of a group id
to the pairs. Fixes #9059
2025-10-02 10:43:36 +05:30
Kovid Goyal
f925327755 Fix de-serialization of some layouts
Forgot that JSON converts dict keys to strings. Sigh.
2025-08-20 08:10:29 +05:30
Kovid Goyal
f91a0f6986 When saving session add option to save the foreground process running in the shell so that it is also restarted
Useful if user builds up session to save by running programs via
the shell.

Note that the serialization format for session files has changed
slightly, becoming more robust and allowing us to add more types
of saved data in the future, without overloading user_vars and thus
risking name conflicts.
2025-08-16 16:50:45 +05:30
Kovid Goyal
3fbdeedfa7 Also make deserialization robust against bools 2025-08-15 12:09:01 +05:30
Kovid Goyal
a8de8e45b0 Fix serialization of mirrored option 2025-08-15 12:04:24 +05:30