Skip to content

#582: Split-pane divider drag is broken in both TUI and GTK (falls through to text-selection) - #584

Merged
JDonaghy merged 3 commits into
developfrom
issue-582-split-pane-divider-drag-is-broken-in-bot
Jul 16, 2026
Merged

#582: Split-pane divider drag is broken in both TUI and GTK (falls through to text-selection)#584
JDonaghy merged 3 commits into
developfrom
issue-582-split-pane-divider-drag-is-broken-in-bot

Conversation

@JDonaghy

Copy link
Copy Markdown
Owner

Closes #582

Automated merge from the coordinator for assignment 899bfb2a85ff on issue #582.

Worker branch: issue-582-split-pane-divider-drag-is-broken-in-botdevelop.

JDonaghy and others added 3 commits July 16, 2026 16:00
Root cause: WindowLayout (vim window splits, one tree per Tab) had no
divider concept at all — no dividers(), no ratio-adjustment methods —
unlike GroupLayout (the separate editor-group-split feature), which
already had full working divider support. Dragging a :vsplit boundary
had no hit region to grab, so the click fell through to text-selection.

- core/window.rs: mirror GroupLayout's dividers()/set_ratio_at_index()/
  adjust_ratio_at_index()/parent_split_of() onto WindowLayout; add
  WindowDivider (a GroupDivider tagged with its owning GroupId, since
  each group's WindowLayout numbers splits independently).
- core/engine/windows.rs: Engine::calculate_window_dividers(); rewire
  the dead Ctrl-W +/-/</>/=/_/| resize commands (previously only ever
  touched group_layout, a no-op for window splits) to try the active
  window's split first, falling back to the editor-group split — this
  preserves the existing group-split behavior locked in by
  tests/vim_compat_batch.rs while fixing window splits.
- render.rs: shared divider_hit_test/divider_ratio_from_pos helpers
  (generic over a new DividerGeometry trait), used by both the new
  window-divider paths AND refactored into the pre-existing group-
  divider code in both backends, removing duplicated hit-test/drag math
  instead of adding a third copy.
- gtk/mod.rs, tui_main/{mod,mouse}.rs: thin per-backend wiring (hit-test
  + drag-state + drag-update + reset-on-mouse-up) mirroring the existing
  group-divider call sites.
- tests/wincmd.rs: new assertions that Ctrl-W resize/equalize/maximize
  actually move a real :vsplit's ratio (the pre-existing tests only
  checked window count, never the ratio).

No quadraui primitive covers this (checked primitives/split.rs — a
two-pane primitive, not an N-way tree); flagged as a follow-up quadraui
issue rather than blocking this fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…plit line

Smoke test failed 3 of 4 combos after the initial #582 fix:

- TUI :split (horizontal) — completely unclickable. `render_separators`
  draws nothing there by design (the upper window's own status line, at
  `position - 1`, already marks the boundary when `window_status_line`
  is on, the default) but the hit-test only accepted `position` exactly
  — one row below the only thing the user can see and click.
- TUI :vsplit (vertical) — ~50% flaky for the same reason: the visible
  separator/scrollbar glyph `render_separators` draws sits at
  `position - 1`, but the hit-test only accepted `position`.
- GTK :vsplit — nothing rendered at all; GTK never painted a window-
  divider line for either axis, unlike the horizontal case which is
  incidentally marked by the per-window status bar.

Fixes:
- tui_main/mouse.rs: widen the window-divider hit-test tolerance from
  `(0.0, 1.0)` to `(1.0, 1.0)` on both axes so both the visible glyph
  (`position - 1`) and the boundary cell (`position`) register. Updated
  the existing `:vsplit` test's "one column off must miss" case (it
  encoded the very off-by-one this fixes) and added a `:split` test for
  the previously-untested horizontal axis.
- render.rs: added `divider_to_split()`, converting a `DividerGeometry`
  divider into the `(quadraui::Split, quadraui::Rect)` pair backends
  need for `backend.draw_split()` — quadraui's existing divider-line
  primitive (already wired for both backends via `Surface::Split`),
  unused by the original #582 fix. Each divider is always a 2-pane
  boundary regardless of `WindowLayout` being an N-way tree, so the
  primitive applies per-divider without needing an N-way variant.
- gtk/mod.rs: paint window dividers via `divider_to_split` for the
  vertical (`:vsplit`) axis only — horizontal is left alone since the
  per-window status bar there already works and matches what the TUI
  fix aligns its hit-test to.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Iteration-2 smoke: GTK `:vsplit` still had no visible divider and its
drag still fell through to text-selection, despite 546a212 adding
`divider_to_split()` specifically to paint that line.

Root cause is not the paint call — it was wired correctly and does run.
Both the paint and the hit-test were individually "right", in two
different coordinate frames:

- `render_content` anchors `editor_bounds` at `AppShellLayout::
  main_content_bounds` — an ABSOLUTE rect, origin offset right by the
  activity bar (~48px) + sidebar and down by the title-bar band (#550
  moved window rects to this convention).
- Every divider hit-test/drag handler rebuilt its own `content_bounds`
  at `(0.0, 0.0)`, with a different height formula
  (`gtk_editor_bottom`) than the renderer's `editor_area_h`.

Clicks arrive in absolute DA coords (single-DA architecture, #217), so
the hit band sat one activity-bar-width left of the painted line. The
`:vsplit` band was therefore unreachable and the press fell through to
text-selection. `:split` only *appeared* to work because its y-error is
small: a click on the per-window status bar landed inside the 6px band
by luck, which is what the iteration-1 note misread as "the status bar
already marks the boundary".

Fixes:
- gtk/mod.rs: cache the exact `(editor_bounds, tab_bar_h)` each
  `render_content` pass painted with, and hit-test/drag against it via
  `painted_editor_bounds()`. Makes hit-test-agrees-with-paint true by
  construction rather than by two formulas being hand-synced. Applied to
  all four sites — window-divider AND editor-group-divider, press AND
  drag-motion — since the group path carried the identical latent bug.
- gtk/mod.rs: paint window dividers on BOTH axes, dropping the
  `Vertical`-only filter. `:split`'s status-bar "handle" is a
  coincidence of an unrelated feature, not a divider; a real line makes
  what is grabbable match what is drawn.
- render.rs: regression tests pinning the invariant the fix rests on —
  a divider's hit band and its painted rect both track `axis_start`, so
  an origin-shifted recomputation is NOT interchangeable with the
  painted one. Verified non-vacuous by re-injecting the origin bug.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Split-pane divider drag is broken in both TUI and GTK (falls through to text-selection)

1 participant