92 lines
3.6 KiB
Diff
92 lines
3.6 KiB
Diff
|
|
--- a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp
|
||
|
|
+++ b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp
|
||
|
|
@@ -297,6 +297,56 @@
|
||
|
|
recalculate();
|
||
|
|
}
|
||
|
|
|
||
|
|
+// Moving a split only changes that node's ratio, so every split nested on
|
||
|
|
+// either side of it gets rescaled and edges that weren't dragged slide along.
|
||
|
|
+// Record the size of each region that doesn't touch the moved edge, so it can
|
||
|
|
+// be pinned afterwards and only the windows along the edge absorb the resize.
|
||
|
|
+struct SFarSide {
|
||
|
|
+ SP<SDwindleNodeData> node;
|
||
|
|
+ bool farIsSecond = false;
|
||
|
|
+ float size = 0;
|
||
|
|
+};
|
||
|
|
+using FarSides = std::vector<SFarSide>;
|
||
|
|
+
|
||
|
|
+static void collectFarSides(const SP<SDwindleNodeData>& node, bool vertical, bool edgeAtStart, FarSides& out) {
|
||
|
|
+ if (!node || !node->children[0] || !node->children[1])
|
||
|
|
+ return;
|
||
|
|
+
|
||
|
|
+ const auto C0 = node->children[0].lock();
|
||
|
|
+ const auto C1 = node->children[1].lock();
|
||
|
|
+
|
||
|
|
+ if (node->splitTop == vertical) {
|
||
|
|
+ // split along the resize axis: pin the far child, follow the near one
|
||
|
|
+ const auto FARCHILD = edgeAtStart ? C1 : C0;
|
||
|
|
+ out.push_back({node, edgeAtStart, (float)(vertical ? FARCHILD->box.h : FARCHILD->box.w)});
|
||
|
|
+ collectFarSides(edgeAtStart ? C0 : C1, vertical, edgeAtStart, out);
|
||
|
|
+ } else {
|
||
|
|
+ // perpendicular split: both children touch the edge
|
||
|
|
+ collectFarSides(C0, vertical, edgeAtStart, out);
|
||
|
|
+ collectFarSides(C1, vertical, edgeAtStart, out);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+static FarSides collectFarSides(const SP<SDwindleNodeData>& split, bool vertical) {
|
||
|
|
+ FarSides out;
|
||
|
|
+ collectFarSides(split->children[0].lock(), vertical, false, out);
|
||
|
|
+ collectFarSides(split->children[1].lock(), vertical, true, out);
|
||
|
|
+ return out;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+// parents come before their children in `far`, so each node's box is already
|
||
|
|
+// final by the time its own ratio is recomputed
|
||
|
|
+static void restoreFarSides(const FarSides& far, bool vertical, bool force) {
|
||
|
|
+ for (const auto& [node, farIsSecond, size] : far) {
|
||
|
|
+ const float TOTAL = vertical ? node->box.h : node->box.w;
|
||
|
|
+ if (TOTAL <= 0)
|
||
|
|
+ continue;
|
||
|
|
+
|
||
|
|
+ node->splitRatio = std::clamp(farIsSecond ? 2.f - size / TOTAL * 2.f : size / TOTAL * 2.f, 0.1F, 1.9F);
|
||
|
|
+ node->recalcSizePosRecursive(force);
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
void CDwindleAlgorithm::resizeTarget(const Vector2D& Δ, SP<ITarget> target, eRectCorner corner) {
|
||
|
|
if (!validMapped(target->window()))
|
||
|
|
return;
|
||
|
|
@@ -356,6 +406,8 @@
|
||
|
|
}
|
||
|
|
|
||
|
|
if (PHOUTER) {
|
||
|
|
+ const auto HFAR = collectFarSides(PHOUTER->pParent.lock(), false);
|
||
|
|
+
|
||
|
|
PHOUTER->pParent->splitRatio = std::clamp(PHOUTER->pParent->splitRatio + allowedMovement.x * 2.f / PHOUTER->pParent->box.w, 0.1, 1.9);
|
||
|
|
|
||
|
|
if (PHINNER) {
|
||
|
|
@@ -368,9 +420,13 @@
|
||
|
|
PHINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||
|
|
} else
|
||
|
|
PHOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||
|
|
+
|
||
|
|
+ restoreFarSides(HFAR, false, *PANIMATE == 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (PVOUTER) {
|
||
|
|
+ const auto VFAR = collectFarSides(PVOUTER->pParent.lock(), true);
|
||
|
|
+
|
||
|
|
PVOUTER->pParent->splitRatio = std::clamp(PVOUTER->pParent->splitRatio + allowedMovement.y * 2.f / PVOUTER->pParent->box.h, 0.1, 1.9);
|
||
|
|
|
||
|
|
if (PVINNER) {
|
||
|
|
@@ -383,6 +439,8 @@
|
||
|
|
PVINNER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||
|
|
} else
|
||
|
|
PVOUTER->pParent->recalcSizePosRecursive(*PANIMATE == 0);
|
||
|
|
+
|
||
|
|
+ restoreFarSides(VFAR, true, *PANIMATE == 0);
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
// get the correct containers to apply splitratio to
|