diff --git a/hyprtester/src/tests/main/layout.cpp b/hyprtester/src/tests/main/layout.cpp index 98e54f79..186d7034 100644 --- a/hyprtester/src/tests/main/layout.cpp +++ b/hyprtester/src/tests/main/layout.cpp @@ -53,6 +53,54 @@ static void testCrashOnGeomUpdate() { // shouldnt crash OK(getFromSocket("/dispatch movefocus r")); + + OK(getFromSocket("/reload")); + + NLog::log("{}Killing all windows", Colors::YELLOW); + Tests::killAllWindows(); +} + +// Test if size + pos is preserved after fs cycle +static void testPosPreserve() { + Tests::spawnKitty(); + + OK(getFromSocket("/dispatch setfloating class:kitty")); + OK(getFromSocket("/dispatch resizewindowpixel exact 1337 69, class:kitty")); + OK(getFromSocket("/dispatch movewindowpixel exact 420 420, class:kitty")); + + { + auto str = getFromSocket("/activewindow"); + EXPECT_CONTAINS(str, "at: 420,420"); + EXPECT_CONTAINS(str, "size: 1337,69"); + } + + OK(getFromSocket("/dispatch fullscreen")); + OK(getFromSocket("/dispatch fullscreen")); + + { + auto str = getFromSocket("/activewindow"); + EXPECT_CONTAINS(str, "size: 1337,69"); + } + + OK(getFromSocket("/dispatch movewindow r")); + + { + auto str = getFromSocket("/activewindow"); + EXPECT_CONTAINS(str, "at: 581,420"); + EXPECT_CONTAINS(str, "size: 1337,69"); + } + + OK(getFromSocket("/dispatch fullscreen")); + OK(getFromSocket("/dispatch fullscreen")); + + { + auto str = getFromSocket("/activewindow"); + EXPECT_CONTAINS(str, "at: 581,420"); + EXPECT_CONTAINS(str, "size: 1337,69"); + } + + NLog::log("{}Killing all windows", Colors::YELLOW); + Tests::killAllWindows(); } static bool test() { @@ -66,6 +114,7 @@ static bool test() { swar(); testCrashOnGeomUpdate(); + testPosPreserve(); // clean up NLog::log("Cleaning up", Colors::YELLOW); diff --git a/src/layout/LayoutManager.cpp b/src/layout/LayoutManager.cpp index 56fa508d..4a93809c 100644 --- a/src/layout/LayoutManager.cpp +++ b/src/layout/LayoutManager.cpp @@ -61,6 +61,13 @@ void CLayoutManager::resizeTarget(const Vector2D& Δ, SP target, eRectC target->space()->resizeTarget(Δ, target, corner); } +void CLayoutManager::setTargetGeom(const CBox& box, SP target) { + if (!target->floating()) + return; + + target->space()->setTargetGeom(box, target); +} + std::expected CLayoutManager::layoutMsg(const std::string_view& sv) { const auto MONITOR = Desktop::focusState()->monitor(); diff --git a/src/layout/LayoutManager.hpp b/src/layout/LayoutManager.hpp index 638c9f4c..e99911d5 100644 --- a/src/layout/LayoutManager.hpp +++ b/src/layout/LayoutManager.hpp @@ -53,6 +53,7 @@ namespace Layout { void moveMouse(const Vector2D& mousePos); void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); void moveTarget(const Vector2D& Δ, SP target); + void setTargetGeom(const CBox& box, SP target); // floats only void endDragTarget(); std::expected layoutMsg(const std::string_view& sv); diff --git a/src/layout/algorithm/Algorithm.cpp b/src/layout/algorithm/Algorithm.cpp index a5f7ffcc..cfb5b7e3 100644 --- a/src/layout/algorithm/Algorithm.cpp +++ b/src/layout/algorithm/Algorithm.cpp @@ -262,3 +262,10 @@ SP CAlgorithm::getNextCandidate(SP old) { // god damn it, maybe empty? return nullptr; } + +void CAlgorithm::setTargetGeom(const CBox& box, SP target) { + if (!target->floating() || !std::ranges::contains(m_floatingTargets, target)) + return; + + m_floating->setTargetGeom(box, target); +} diff --git a/src/layout/algorithm/Algorithm.hpp b/src/layout/algorithm/Algorithm.hpp index 3ee26a3c..7df6c5c1 100644 --- a/src/layout/algorithm/Algorithm.hpp +++ b/src/layout/algorithm/Algorithm.hpp @@ -40,6 +40,8 @@ namespace Layout { void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); void moveTarget(const Vector2D& Δ, SP target); + void setTargetGeom(const CBox& box, SP target); // only for float + void updateFloatingAlgo(UP&& algo); void updateTiledAlgo(UP&& algo); diff --git a/src/layout/algorithm/FloatingAlgorithm.hpp b/src/layout/algorithm/FloatingAlgorithm.hpp index 2c9ff14b..40e53034 100644 --- a/src/layout/algorithm/FloatingAlgorithm.hpp +++ b/src/layout/algorithm/FloatingAlgorithm.hpp @@ -17,6 +17,9 @@ namespace Layout { // a target is being moved by a delta virtual void moveTarget(const Vector2D& Δ, SP target) = 0; + // a target is moved to a pos x size + virtual void setTargetGeom(const CBox& geom, SP target) = 0; + virtual void recenter(SP t); virtual void recalculate(); diff --git a/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.cpp b/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.cpp index 1fe3b068..0d069e4f 100644 --- a/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.cpp +++ b/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.cpp @@ -116,6 +116,8 @@ void CDefaultFloatingAlgorithm::newTarget(SP target) { PWINDOW->m_reportedSize = PWINDOW->m_pendingReportedSize; } } + + updateTarget(target); } void CDefaultFloatingAlgorithm::movedTarget(SP target, std::optional focalPoint) { @@ -152,6 +154,8 @@ void CDefaultFloatingAlgorithm::movedTarget(SP target, std::optionalsetPositionGlobal(fitBoxInWorkArea(CBox{NEW_POS, LAST_SIZE}, target)); } + + updateTarget(target); } CBox CDefaultFloatingAlgorithm::fitBoxInWorkArea(const CBox& box, SP t) { @@ -173,6 +177,7 @@ CBox CDefaultFloatingAlgorithm::fitBoxInWorkArea(const CBox& box, SP t) void CDefaultFloatingAlgorithm::removeTarget(SP target) { target->rememberFloatingSize(target->position().size()); + m_datas.erase(target); } void CDefaultFloatingAlgorithm::resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner) { @@ -184,6 +189,8 @@ void CDefaultFloatingAlgorithm::resizeTarget(const Vector2D& Δ, SP tar if (g_layoutManager->dragController()->target() == target) target->warpPositionSize(); + + updateTarget(target); } void CDefaultFloatingAlgorithm::moveTarget(const Vector2D& Δ, SP target) { @@ -193,12 +200,17 @@ void CDefaultFloatingAlgorithm::moveTarget(const Vector2D& Δ, SP targe if (g_layoutManager->dragController()->target() == target) target->warpPositionSize(); + + updateTarget(target); } void CDefaultFloatingAlgorithm::swapTargets(SP a, SP b) { auto posABackup = a->position(); a->setPositionGlobal(b->position()); b->setPositionGlobal(posABackup); + + updateTarget(a); + updateTarget(b); } void CDefaultFloatingAlgorithm::moveTargetInDirection(SP t, Math::eDirection dir, bool silent) { @@ -216,4 +228,25 @@ void CDefaultFloatingAlgorithm::moveTargetInDirection(SP t, Math::eDire } t->setPositionGlobal(pos); + + updateTarget(t); +} + +void CDefaultFloatingAlgorithm::recenter(SP t) { + if (!m_datas.contains(t)) { + IFloatingAlgorithm::recenter(t); + return; + } + + t->setPositionGlobal(m_datas.at(t).lastBox); +} + +void CDefaultFloatingAlgorithm::setTargetGeom(const CBox& geom, SP target) { + target->setPositionGlobal(geom); + + updateTarget(target); +} + +void CDefaultFloatingAlgorithm::updateTarget(SP t) { + m_datas[t] = {.lastBox = t->position()}; } diff --git a/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.hpp b/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.hpp index ef94e371..1e87fac1 100644 --- a/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.hpp +++ b/src/layout/algorithm/floating/default/DefaultFloatingAlgorithm.hpp @@ -1,5 +1,7 @@ #include "../../FloatingAlgorithm.hpp" +#include + namespace Layout { class CAlgorithm; } @@ -17,10 +19,22 @@ namespace Layout::Floating { virtual void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); virtual void moveTarget(const Vector2D& Δ, SP target); + virtual void setTargetGeom(const CBox& geom, SP target); + virtual void swapTargets(SP a, SP b); virtual void moveTargetInDirection(SP t, Math::eDirection dir, bool silent); + virtual void recenter(SP t); + private: CBox fitBoxInWorkArea(const CBox& box, SP t); + + void updateTarget(SP); + + struct SWindowData { + CBox lastBox; + }; + + std::map, SWindowData> m_datas; }; }; \ No newline at end of file diff --git a/src/layout/space/Space.cpp b/src/layout/space/Space.cpp index 33e5bb8c..db3925f6 100644 --- a/src/layout/space/Space.cpp +++ b/src/layout/space/Space.cpp @@ -183,6 +183,11 @@ void CSpace::moveTargetInDirection(SP t, Math::eDirection dir, bool sil m_algorithm->moveTargetInDirection(t, dir, silent); } +void CSpace::setTargetGeom(const CBox& box, SP target) { + if (m_algorithm) + m_algorithm->setTargetGeom(box, target); +} + SP CSpace::getNextCandidate(SP old) { return !m_algorithm ? nullptr : m_algorithm->getNextCandidate(old); } diff --git a/src/layout/space/Space.hpp b/src/layout/space/Space.hpp index ff3d18e6..e29a6d8f 100644 --- a/src/layout/space/Space.hpp +++ b/src/layout/space/Space.hpp @@ -47,6 +47,7 @@ namespace Layout { void resizeTarget(const Vector2D& Δ, SP target, eRectCorner corner = CORNER_NONE); void moveTarget(const Vector2D& Δ, SP target); + void setTargetGeom(const CBox& box, SP target); // only for float SP algorithm() const; diff --git a/src/layout/supplementary/DragController.cpp b/src/layout/supplementary/DragController.cpp index a28aef07..be70f4ac 100644 --- a/src/layout/supplementary/DragController.cpp +++ b/src/layout/supplementary/DragController.cpp @@ -239,6 +239,8 @@ void CDragStateController::dragEnd() { draggingTarget->damageEntire(); + g_layoutManager->setTargetGeom(draggingTarget->position(), draggingTarget); + Desktop::focusState()->fullWindowFocus(draggingTarget->window(), Desktop::FOCUS_REASON_DESKTOP_STATE_CHANGE); m_wasDraggingWindow = false;