From 8685fd7b0c2afe06c798554dea80c53f98d73894 Mon Sep 17 00:00:00 2001 From: Mikhail Date: Fri, 6 Mar 2026 23:47:48 +0300 Subject: dwindle: add rotatesplit layoutmsg and tests (#13235) --- .../algorithm/tiled/dwindle/DwindleAlgorithm.cpp | 50 ++++++++++++++++++++++ .../algorithm/tiled/dwindle/DwindleAlgorithm.hpp | 1 + 2 files changed, 51 insertions(+) (limited to 'src/layout/algorithm/tiled') diff --git a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp index 716097ba..7ef36753 100644 --- a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp +++ b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp @@ -666,6 +666,19 @@ std::expected CDwindleAlgorithm::layoutMsg(const std::string_ if (!swapSplit(CURRENT_NODE)) return std::unexpected("can't swapsplit in the current workspace"); } + } else if (ARGS[0] == "rotatesplit") { + if (CURRENT_NODE) { + int angle = 90; + if (!ARGS[1].empty()) { + try { + angle = std::stoi(std::string{ARGS[1]}); + } catch (const std::exception& e) { + Log::logger->log(Log::WARN, "Invalid angle argument for rotatesplit: {}", ARGS[1]); + return std::unexpected("Invalid angle argument"); + } + } + rotateSplit(CURRENT_NODE, angle); + } } else if (ARGS[0] == "movetoroot") { auto node = CURRENT_NODE; if (!ARGS[1].empty()) { @@ -760,6 +773,43 @@ bool CDwindleAlgorithm::swapSplit(SP x) { return true; } +void CDwindleAlgorithm::rotateSplit(SP x, int angle) { + if (!x || !x->pParent) + return; + + if (x->pTarget->fullscreenMode() != FSMODE_NONE) + return; + + // normalize the angle to multiples of 90 degrees + int normalizedAngle = ((sc(angle / 90) % 4) + 4) % 4; // ensures positive modulo + + auto pParent = x->pParent; + + bool shouldSwap = false; + + switch (normalizedAngle) { + case 0: // 0 degrees - no change + break; + case 1: + if (pParent->splitTop) + shouldSwap = true; + pParent->splitTop = !pParent->splitTop; + break; + case 2: shouldSwap = true; break; + case 3: + if (!pParent->splitTop) + shouldSwap = true; + pParent->splitTop = !pParent->splitTop; + break; + default: break; // should never happen + } + + if (shouldSwap) + std::swap(pParent->children[0], pParent->children[1]); + + pParent->recalcSizePosRecursive(); +} + bool CDwindleAlgorithm::moveToRoot(SP x, bool stable) { if (!x || !x->pParent) return false; diff --git a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp index 97ea2908..41cbf8bb 100644 --- a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp +++ b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.hpp @@ -50,6 +50,7 @@ namespace Layout::Tiled { bool toggleSplit(SP); bool swapSplit(SP); + void rotateSplit(SP, int angle = 90); bool moveToRoot(SP, bool stable = true); Math::eDirection m_overrideDirection = Math::DIRECTION_DEFAULT; -- cgit v1.2.3