Skip to content

feat(layout): add layout-toggle-split action for dwindle - #444

Merged
ItsLemmy merged 2 commits into
noctalia-dev:mainfrom
c0mpile:pr-dwindle-window-split-toggle
Oct 14, 2026
Merged

ItsLemmy merged 2 commits into
noctalia-dev:mainfrom
c0mpile:pr-dwindle-window-split-toggle

Conversation

@c0mpile

@c0mpile c0mpile commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds a layout-toggle-split action that flips the split holding the focused tile in the dwindle layout between side by side and stacked, keeping its ratio. This is the equivalent of Hyprland's togglesplit. It is refused outside the dwindle layout and when layout.dwindle.preserve_split is disabled. docs/user/actions.md and docs/user/layout.md are updated.

Motivation

Dwindle picks each split's direction from the tile's longer edge, and preserve_split freezes that choice. There was no way to change a split's direction afterwards, short of closing and re-opening windows. This lets a user change a split's orientation with a keybind. It requires preserve_split because, without it, the next arrange would flip the split back to the longer-edge direction.

Type of Change

  • New feature

Testing

  • Manual: set layout.mode = "dwindle" and layout.dwindle.preserve_split = true, bound layout-toggle-split, and opened three windows. Toggling on a stacked pair flips it to side by side and back.
  • Manual: with preserve_split = false, the action is refused with an error naming the setting. After switching the workspace to the scrolling layout, it is refused with "requires the dwindle layout".
  • No automated harness check was added.

Manual Coverage

  • Tested in a nested Umbriel session
  • Tested in a native Umbriel session
  • Tested with multiple monitors
  • Tested with a scaled output
  • Tested with native Wayland applications
  • Tested with X11 applications through Xwayland
  • Tested with the scrolling layout
  • Tested with the dwindle layout

Checklist

  • This PR is ready for review, or it is marked as Draft.
  • This change fits SCOPE.md, or its scope was agreed in an issue or on Discord first.
  • I read and followed the relevant guidance in CONTRIBUTING.md.
  • I ran just format, or this PR has no C++ changes.
  • I ran the relevant build, test, lint, or verification commands, or explained why they were not run.
  • I functionally verified compositor behavior where automated checks are insufficient.
  • I self-reviewed the changes.
  • I checked for new warnings or errors.
  • I updated docs/ and examples/config.toml, or this PR does not change user-facing configuration or behavior.
  • I used canonical names for config keys, IPC actions, paths, and identifiers.

Additional Notes

The flip does not set the split's locked flag, because preserve_split already keeps splits fixed during arrange.

@ItsLemmy ItsLemmy added the talia-review Ask Talia for a preliminary AI review (removed once posted) label Oct 13, 2026

@talia-review talia-review Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talia preliminary review

Check Result
Merge score 🟢 4/5 — No issues found; likely ready after CI and human review
Findings None found
Review depth 3/5 — how thoroughly the changed code could be checked by reading it
Coverage 11 of 11 changed files reviewed

What Talia checked: Verified the new toggleSplit orientation test matches arrangeNode's HSplit/VSplit/AutoSplit resolution, that the preserve_split guard reads the same resolved workspace config DwindleLayout uses (setConfig(&m_layoutConfig)), and that enum/handler/spec/doc/cheatsheet tables stay index- and group-aligned; no runtime arrange path was executed.

Run details
  • Commit reviewed: b684b91
  • Source lookups: 30 file reads, 22 searches
  • Prompt version: 859b7490ca3d

Preliminary automated review: Talia read the changed code and related source; nothing was built, run or tested, and AI can make mistakes. It is not a scope acceptance or a promise to merge; a human reviewer makes the final call. See our ethos.

@ItsLemmy

Copy link
Copy Markdown
Member

Thanks, the toggle itself works well. One change, though: I don't think it should require preserve_split.

Splits already have a locked flag. Directional drops set it, and arrangeNode never reorients a locked split, whatever preserve_split is set to. If toggleSplit set parent->locked = true, the flipped direction would stick without preserve_split, and the extra guard and refusal path could go.

preserve_split is a global choice about whether automatic splits follow geometry. A split the user flipped by hand should stay put either way, just like a directional drop. Could you:

  • set locked in toggleSplit;
  • drop the preserveSplit check in actionLayoutToggleSplit (keep the dwindle-layout check);
  • remove the preserve_split mentions from the header comment, docs/user/layout.md, docs/user/actions.md, and examples/config.toml
  • add a unit test in tests/unit/dwindle_layout.cpp checking that a toggled split survives arrange with preserve_split off?

@ItsLemmy
ItsLemmy marked this pull request as draft October 13, 2026 22:01
@c0mpile
c0mpile force-pushed the pr-dwindle-window-split-toggle branch from b684b91 to 7a21540 Compare October 14, 2026 00:15
@c0mpile

c0mpile commented Oct 14, 2026

Copy link
Copy Markdown
Contributor Author

I've amended the commit and force-pushed:

  • toggleSplit now sets parent->locked = true, so the flipped direction sticks whatever preserve_split is set to.
  • actionLayoutToggleSplit no longer checks preserveSplit and has no refusal path for it. The dwindle-layout check is still there.
  • I removed the preserve_split mentions from the header comment, docs/user/layout.md, docs/user/actions.md and examples/config.toml.
  • I added toggledSplitSurvivesArrangeWhenPreserveSplitIsOff in tests/unit/dwindle_layout.cpp. It toggles a two-window split with preserve_split off, arranges twice and checks the windows are still stacked. It fails without the locked = true line.
  • I also added a harness check, layout/dwindle_toggle_split, which runs the action through a headless compositor with real clients. It checks that the action is refused outside dwindle, that it stacks a side-by-side pair, and that the pair stays stacked after a config reload and a third window.

The unit tests pass (114/114). The full harness run has 3 failures (effect/registry, effect/selection, render/renderer_recovery). They fail the same way on the branch without these changes, and they're shader and renderer checks.

@c0mpile
c0mpile marked this pull request as ready for review October 14, 2026 00:19
@ItsLemmy

Copy link
Copy Markdown
Member

thx!

@ItsLemmy
ItsLemmy merged commit 0fa8343 into noctalia-dev:main Oct 14, 2026
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.

2 participants