hyprland: dwindle resize only moves the dragged edge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
81b8cd173d
commit
fa0a654f5f
2 changed files with 99 additions and 1 deletions
91
patches/hyprland-dwindle-pin-far-sides.patch
Normal file
91
patches/hyprland-dwindle-pin-far-sides.patch
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
--- 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue