Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
PhosphorTiles::SplitTree Class Reference

A binary split tree for interactive window tiling. More...

#include <phosphor-tiles/include/PhosphorTiles/SplitTree.h>

Public Member Functions

 SplitTree ()
 Construct an empty tree (no root)
 
 SplitTree (SplitTree &&other) noexcept
 Move constructor.
 
SplitTreeoperator= (SplitTree &&other) noexcept
 Move assignment.
 
 ~SplitTree ()
 
 SplitTree (const SplitTree &)=delete
 
SplitTreeoperator= (const SplitTree &)=delete
 
const SplitNoderoot () const noexcept
 Get the root node of the tree.
 
SplitNoderoot () noexcept
 
bool isEmpty () const noexcept
 Check if the tree has no nodes.
 
int leafCount () const noexcept
 Count the number of leaf nodes (windows)
 
int treeHeight () const noexcept
 Get the maximum height of the tree.
 
const SplitNodeleafForWindow (const QString &windowId) const
 Find the leaf node for a given window ID.
 
SplitNodeleafForWindow (const QString &windowId)
 
QStringList leafOrder () const
 Get window IDs in depth-first left-to-right order.
 
void insertAtFocused (const QString &windowId, const QString &focusedWindowId, qreal initialRatio=0.0)
 Insert a window by splitting the focused window's leaf.
 
void insertAtEnd (const QString &windowId, qreal initialRatio=0.0)
 Insert a window by splitting the rightmost leaf.
 
void insertAtPosition (const QString &windowId, int position, qreal initialRatio=0.0)
 Insert a window by splitting the leaf at a given position.
 
void remove (const QString &windowId)
 Remove a window, collapsing its parent and promoting its sibling.
 
void swap (const QString &windowId1, const QString &windowId2)
 Swap two windows' positions in the tree.
 
bool swapLeaves (const QString &a, const QString &b)
 Swap the stored window ids on two existing leaves.
 
void resizeSplit (const QString &windowId, qreal newRatio)
 Adjust the split ratio of a window's parent node.
 
QVector< QRect > applyGeometry (const QRect &area, int innerGap) const
 Compute zone rectangles by recursively splitting the area.
 
bool rebuildFromOrder (const QStringList &tiledWindows, qreal defaultSplitRatio=AutotileDefaults::DefaultSplitRatio)
 Rebuild tree from a new window order, preserving split ratios where possible.
 
QJsonObject toJson () const
 Serialize the tree to JSON.
 

Static Public Member Functions

static std::unique_ptr< SplitTreefromJson (const QJsonObject &json)
 Deserialize a tree from JSON.
 

Detailed Description

A binary split tree for interactive window tiling.

SplitTree manages a binary tree of split nodes where each leaf represents a tiled window and each internal node defines how its area is divided between two children. This enables per-split ratio adjustment and interactive insert/remove operations (similar to bspwm).

Unlike BSPAlgorithm (which rebuilds the tree from scratch each frame), SplitTree is a persistent data structure that is mutated incrementally as windows are added, removed, swapped, or resized.

This class is NOT a QObject. It is movable via unique_ptr members.

Warning
This class is not thread-safe. All access must be serialized by the caller.

Constructor & Destructor Documentation

◆ SplitTree() [1/3]

PhosphorTiles::SplitTree::SplitTree ( )

Construct an empty tree (no root)

◆ SplitTree() [2/3]

PhosphorTiles::SplitTree::SplitTree ( SplitTree &&  other)
noexcept

Move constructor.

◆ ~SplitTree()

PhosphorTiles::SplitTree::~SplitTree ( )

◆ SplitTree() [3/3]

PhosphorTiles::SplitTree::SplitTree ( const SplitTree )
delete

Member Function Documentation

◆ applyGeometry()

QVector< QRect > PhosphorTiles::SplitTree::applyGeometry ( const QRect &  area,
int  innerGap 
) const

Compute zone rectangles by recursively splitting the area.

Parameters
areaAvailable screen area
innerGapGap between adjacent zones in pixels
Returns
Vector of zone geometries in depth-first left-to-right order
Note
When gap exceeds available space in a split, the first subtree receives the full parent rect and each leaf of the second subtree is emitted as a 1×1 rect anchored at the parent's origin. This preserves the invariant that the returned rect count equals leafCount, which downstream code relies on to map tiled windows to zones by position. Windows under the degenerate second subtree land effectively offscreen; this is intentional. A warning is logged via lcTilesLib.

◆ fromJson()

static std::unique_ptr< SplitTree > PhosphorTiles::SplitTree::fromJson ( const QJsonObject &  json)
static

Deserialize a tree from JSON.

Parameters
jsonSerialized tree
Returns
Reconstructed tree, or nullptr on error

◆ insertAtEnd()

void PhosphorTiles::SplitTree::insertAtEnd ( const QString &  windowId,
qreal  initialRatio = 0.0 
)

Insert a window by splitting the rightmost leaf.

If the tree is empty, creates a root leaf.

Parameters
windowIdNew window to insert
initialRatioSplit ratio for the new split (0 = use DefaultSplitRatio)

◆ insertAtFocused()

void PhosphorTiles::SplitTree::insertAtFocused ( const QString &  windowId,
const QString &  focusedWindowId,
qreal  initialRatio = 0.0 
)

Insert a window by splitting the focused window's leaf.

If the tree is empty, creates a root leaf. If the focused window is not found, falls back to insertAtEnd.

Parameters
windowIdNew window to insert
focusedWindowIdCurrently focused window to split

◆ insertAtPosition()

void PhosphorTiles::SplitTree::insertAtPosition ( const QString &  windowId,
int  position,
qreal  initialRatio = 0.0 
)

Insert a window by splitting the leaf at a given position.

Position is a depth-first index. If position >= leafCount, falls back to insertAtEnd.

Parameters
windowIdNew window to insert
positionDepth-first leaf index to split
initialRatioSplit ratio for the new split (0 = use DefaultSplitRatio)

◆ isEmpty()

bool PhosphorTiles::SplitTree::isEmpty ( ) const
noexcept

Check if the tree has no nodes.

◆ leafCount()

int PhosphorTiles::SplitTree::leafCount ( ) const
noexcept

Count the number of leaf nodes (windows)

◆ leafForWindow() [1/2]

SplitNode * PhosphorTiles::SplitTree::leafForWindow ( const QString &  windowId)

◆ leafForWindow() [2/2]

const SplitNode * PhosphorTiles::SplitTree::leafForWindow ( const QString &  windowId) const

Find the leaf node for a given window ID.

Parameters
windowIdWindow to search for
Returns
Leaf node, or nullptr if not found

◆ leafOrder()

QStringList PhosphorTiles::SplitTree::leafOrder ( ) const

Get window IDs in depth-first left-to-right order.

Returns
Ordered list of window IDs from all leaf nodes

◆ operator=() [1/2]

SplitTree & PhosphorTiles::SplitTree::operator= ( const SplitTree )
delete

◆ operator=() [2/2]

SplitTree & PhosphorTiles::SplitTree::operator= ( SplitTree &&  other)
noexcept

Move assignment.

◆ rebuildFromOrder()

bool PhosphorTiles::SplitTree::rebuildFromOrder ( const QStringList &  tiledWindows,
qreal  defaultSplitRatio = AutotileDefaults::DefaultSplitRatio 
)

Rebuild tree from a new window order, preserving split ratios where possible.

Parameters
tiledWindowsOrdered list of tiled window IDs
defaultSplitRatioDefault split ratio for new internal nodes
Returns
true if all windows were preserved, false if the input had to be truncated (size exceeded MaxRuntimeTreeDepth). Callers that care about lossless round-tripping should observe the return value and clamp their own state to match.

◆ remove()

void PhosphorTiles::SplitTree::remove ( const QString &  windowId)

Remove a window, collapsing its parent and promoting its sibling.

Parameters
windowIdWindow to remove

◆ resizeSplit()

void PhosphorTiles::SplitTree::resizeSplit ( const QString &  windowId,
qreal  newRatio 
)

Adjust the split ratio of a window's parent node.

Parameters
windowIdWindow whose parent split to resize
newRatioNew split ratio (clamped to MinSplitRatio..MaxSplitRatio)

◆ root() [1/2]

const SplitNode * PhosphorTiles::SplitTree::root ( ) const
noexcept

Get the root node of the tree.

Returns
Root node, or nullptr if tree is empty

◆ root() [2/2]

SplitNode * PhosphorTiles::SplitTree::root ( )
noexcept

◆ swap()

void PhosphorTiles::SplitTree::swap ( const QString &  windowId1,
const QString &  windowId2 
)

Swap two windows' positions in the tree.

Only swaps the windowId strings on the leaf nodes; tree structure remains unchanged.

Parameters
windowId1First window
windowId2Second window

◆ swapLeaves()

bool PhosphorTiles::SplitTree::swapLeaves ( const QString &  a,
const QString &  b 
)

Swap the stored window ids on two existing leaves.

Fast-path variant of swap that reports whether both leaves were actually found. Callers can use the return value to decide whether the swap succeeded or whether a fallback rebuild is required.

Tree structure, split ratios, split directions, and child ordering are left untouched; only the windowId strings on the two leaf nodes are exchanged.

Parameters
aFirst window id
bSecond window id
Returns
true if both leaves were located and their ids swapped; false otherwise (tree is left unchanged in the false case). Swapping an id with itself returns true as a no-op when the leaf exists, and false when it doesn't.

◆ toJson()

QJsonObject PhosphorTiles::SplitTree::toJson ( ) const

Serialize the tree to JSON.

◆ treeHeight()

int PhosphorTiles::SplitTree::treeHeight ( ) const
noexcept

Get the maximum height of the tree.

Returns
Height (0 for empty tree, 1 for single leaf)

The documentation for this class was generated from the following file: