Skip to content

Add "box" option to pane-border-indicators#4940

Open
patrick-motard wants to merge 9 commits intotmux:masterfrom
patrick-motard:feature/pane-box-borders
Open

Add "box" option to pane-border-indicators#4940
patrick-motard wants to merge 9 commits intotmux:masterfrom
patrick-motard:feature/pane-box-borders

Conversation

@patrick-motard
Copy link
Copy Markdown

@patrick-motard patrick-motard commented Mar 19, 2026

Reopening #4747 with additional fixes since the original PR.

Add a new "box" option for pane-border-indicators that draws a complete box border around the active pane instead of using shared separator borders between panes. Also adds "box-all" to draw borders around every pane.

Screen.Recording.2026-03-18.at.10.59.36.PM.mov

Changes

  • Add PANE_BORDER_BOX / PANE_BORDER_BOX_ALL constants and window_pane_box_mode() helper
  • Reduce internal screen buffer and PTY by 2 in each dimension to reserve space for box borders
  • Offset pane content drawing by 1 to account for box border
  • Adjust cursor positioning for box mode offset in screen-write, tty, and server-client
  • Draw styled box border for active pane, blank borders for inactive panes
  • Skip normal pane separator borders when box mode is active
  • Clear separator cells between panes that would otherwise show old borders
  • Handle mouse clicks on box borders correctly
  • Add viewport clipping support so box borders work correctly when the window is larger than the terminal
  • Add "box-all" variant that draws borders around all panes, not just the active one
  • Document both options in tmux.1

Test plan

  • Single pane: box mode inactive, no borders drawn
  • Horizontal split: box borders on active pane, blank on inactive
  • Vertical split: same behavior
  • box-all: borders on all panes
  • Switch between off/box/box-all dynamically
  • Mouse clicks on borders and within panes work correctly
  • Resize terminal: borders update correctly
  • Viewport panning works with box borders

Add infrastructure for a new "box" pane border indicator mode:

- Add PANE_BORDER_BOX constant (value 4) to tmux.h
- Add window_pane_box_mode() function to detect when box mode is active
- Box mode requires: pane-border-indicators set to "box", more than
  one pane in the window, and pane size at least 3x3

The detection function will be used by subsequent commits to adjust
screen sizing, content positioning, and border drawing.
When box mode is active, reduce both the screen buffer and PTY size
by 2 in each dimension to reserve space for the border:

- window_pane_resize(): Reduce screen buffer to (sx-2, sy-2)
- window_pane_send_resize(): Report PTY size as (sx-2, sy-2)
- options_push_changes(): Resize screen/PTY when option changes

This ensures the shell receives the correct terminal dimensions and
content cannot be written in the border area.
Adjust content and cursor positioning when box mode is active:

- screen_write_set_client_cb(): Apply +1 offset to xoff/yoff for
  content positioning inside the border
- server_client_reset_state(): Account for box mode offset when
  calculating cursor position
- tty_window_offset1(): Account for box mode offset in view offset
  calculation

This ensures content is rendered inside the border area and the
cursor appears at the correct position.
Add screen_redraw_draw_active_box() to draw a complete box border
around the active pane when box mode is enabled:

- Draw styled border (using pane-active-border-style) for active pane
- Draw blank spaces for inactive pane border areas
- Skip normal pane separator borders when box mode is active
- Adjust pane content drawing to account for box mode offset
- Call box drawing on border redraws, window redraws, and pane redraws

The box border uses the configured pane-border-lines style for the
line drawing characters.
Add "box" as a valid choice for the pane-border-indicators window
option. Update the option description to mention the new box mode.
Update tmux.1 man page to document the new "box" value for
pane-border-indicators, explaining that it draws a complete box
around the active pane and that content is inset to prevent reflow.
When box mode is active, the separator columns and rows between panes
were not being cleared, causing old border characters to persist.
Each pane's box is drawn within its allocated space, but the layout
system places separator cells between panes that were left untouched.

Add code to clear:
- The separator column immediately to the right of each pane
- The separator row immediately below each pane
- The corner cell where separators intersect
Add MouseDown1Border key binding so clicking on any pane border
selects that pane. Extend window_get_active_at() to include box
border areas and adjacent separator cells in hit detection, which
allows drag-to-resize to work correctly in box mode. Add box border
edge detection as a fallback in server_client_check_mouse_in_pane()
after traditional separator detection.
Fix border rendering when windows are larger than the terminal by
adding viewport offset calculations (ctx->ox/oy) to all coordinate
computations in screen_redraw_draw_active_box(). Borders are now
clipped to the visible viewport and only drawn when within bounds.

Add "box-all" option to pane-border-indicators that draws visible
borders around all panes, not just the active one. Active pane uses
pane-active-border-style, inactive panes use pane-border-style.

Update man page and add basic regression test for option parsing.
@patrick-motard patrick-motard force-pushed the feature/pane-box-borders branch from 64bd580 to ed89b69 Compare March 19, 2026 03:49
@patrick-motard
Copy link
Copy Markdown
Author

Still seeing a few unwanted artifacts when panes are larger than the viewport. Working on fixing those.

@Isaqdn03
Copy link
Copy Markdown

I was literally just talking to a friend about how much we've wanted a more containerized approach to managing panes. This is exactly it. Really hoping they merge this

@Isaqdn03
Copy link
Copy Markdown

image

working quite well, built it from the branch and it's working well on Arch/Hyprland with heavy borders.

@Isaqdn03
Copy link
Copy Markdown

Hey @patrick-motard, great work on this PR! I've been testing it on Arch Linux with Hyprland + Ghostty and the box borders look amazing.

I found a content clipping bug and have a fix for it:

Bug: In screen_redraw_draw_pane(), the tty_draw_line source offset calculation doesn't account for the box mode offset. When box mode is active, rr->px includes the +1 box offset, but the screen buffer was already resized to sx-2 (starting at column 0). So rr->px - wp->xoff evaluates to 1 instead of 0, causing the first column of content to be skipped and the content to appear shifted/clipped by the left border.

Visible symptom: Content in panes gets cut off at the left edge and bottom — the box border overlaps the leftmost column of text.

Fix (in screen-redraw.c, inside screen_redraw_draw_pane):

// Before:
tty_draw_line(tty, s, rr->px - wp->xoff, j,
    rr->nx, rr->px, y, &defaults, palette);

// After:
u_int   src_x;
src_x = rr->px - wp->xoff;
if (box_mode)
    src_x -= 1;
tty_draw_line(tty, s, src_x, j,
    rr->nx, rr->px, y, &defaults, palette);

Tested with pane-border-indicators box-all + pane-border-lines heavy, multiple pane layouts (horizontal, vertical, mixed). Content now renders correctly within the box borders.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants