Skip to content

feat: add BSP normalization#2135

Open
OliverGuy wants to merge 2 commits into
nikitabobko:mainfrom
OliverGuy:feat/binary-tree-normalization
Open

feat: add BSP normalization#2135
OliverGuy wants to merge 2 commits into
nikitabobko:mainfrom
OliverGuy:feat/binary-tree-normalization

Conversation

@OliverGuy

Copy link
Copy Markdown

Cf. #260.

What

A new enable-normalization-binary-tree config option. When enabled, every tiling container is normalized to at most two children, with each level's orientation derived from its rectangle's aspect ratio, producing an i3/bspwm-style binary space partition.

Why

Users coming from BSP-style window managers expect new splits to follow the longer edge automatically instead of piling siblings into a single container.

How

NormalizeBinaryTree() recursively wraps surplus children into a nested container (forceBinaryTree), then sets each level's orientation and split position from its computed rect. Gated behind the new flag in normalizeContainers(); setOrientation is exposed on TilingContainer for it.

PR checklist

  • Explain your changes in the relevant commit messages rather than in the PR description. The PR description must not contain more information than the commit messages (except for images and other media).
  • Each commit must explain what/why/how and motivation in its description. https://cbea.ms/git-commit/
  • Don't forget to link the appropriate issues/discussions in commit messages (if applicable).
  • Each commit must be an atomic change (a PR may contain several commits). Don't introduce new functional changes together with refactorings in the same commit.
  • ./test.sh exits with non-zero exit code.
  • Avoid merge commits, always rebase and force push.

OliverGuy and others added 2 commits July 5, 2026 22:03
Cf. nikitabobko#260

What: a new `enable-normalization-binary-tree` config option. When
enabled, every tiling container is normalized to at most two children,
with each level's orientation derived from its rectangle's aspect ratio,
producing an i3/bspwm-style binary space partition.

Why: users coming from BSP-style window managers expect new splits to
follow the longer edge automatically instead of piling siblings into a
single container.

How: normalizeBinaryTree() recursively wraps surplus children into a
nested container (forceBinaryTree), then sets each level's orientation and
split position from its computed rect. Gated behind the new flag in
normalizeContainers(); setOrientation is exposed on TilingContainer for it.
What: with enable-normalization-binary-tree, `move <dir>` on a window at the
workspace's edge in that direction now applies the boundary action (e.g.
crosses to the adjacent monitor with --boundaries all-monitors-outer-frame)
instead of being popped out one container level.

Why: binary-tree normalization re-nests a window as soon as `move` bubbles it
out of its container, so it could never reach the workspace-root edge that
triggers a monitor crossing — it just oscillated inside its container and
never left the monitor.

How: in MoveCommand's move-out branch, when the window has no target in the
direction anywhere up the tree (closestParent(hasChildrenInDirection:) == nil,
i.e. it is at the workspace edge) and enableNormalizationBinaryTree is set,
route to hitWorkspaceBoundaries instead of moveOut. Non-binary-tree configs
keep the existing i3-style move-out behaviour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@OliverGuy
OliverGuy force-pushed the feat/binary-tree-normalization branch from c85f9ed to 3204d8d Compare July 8, 2026 19:56
whoislikemiha added a commit to whoislikemiha/AeroSpace that referenced this pull request Jul 11, 2026
…hrows annotations and the unnecessary try from non-throwing async MoveCommand tests.\n\nWhy: Swift 6.3 reports the unnecessary try as a warning, and AeroSpace compiles tests with warnings as errors. This caused BSP PR nikitabobko#2135 to fail the repository's full test gate.\n\nHow: use plain await for the non-throwing command and let SwiftFormat remove the redundant throws declarations.
whoislikemiha added a commit to whoislikemiha/AeroSpace that referenced this pull request Jul 11, 2026
What: remove redundant throws annotations and the unnecessary try from non-throwing async MoveCommand tests.

Why: Swift 6.3 reports the unnecessary try as a warning, and AeroSpace compiles tests with warnings as errors. This caused BSP PR nikitabobko#2135 to fail the repository's full test gate.

How: use plain await for the non-throwing command and let SwiftFormat remove the redundant throws declarations.
@whoislikemiha

Copy link
Copy Markdown

The full ./test.sh gate currently fails on Swift 6.3.3 because testBinaryTree_edgeMoveHitsBoundaryInsteadOfUnnesting uses try await for a non-throwing call. With warnings-as-errors:

error: no calls to throwing functions occur within 'try' expression

I ran the complete gate after applying the SwiftFormat-compatible fix; build, tests, lint, Periphery, and generated-file checks all pass. Cherry-pickable commit: whoislikemiha/AeroSpace@bf5c86a

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