diff --git a/hyprtester/src/tests/main/dwindle.cpp b/hyprtester/src/tests/main/dwindle.cpp index cb645245..664a8d73 100644 --- a/hyprtester/src/tests/main/dwindle.cpp +++ b/hyprtester/src/tests/main/dwindle.cpp @@ -64,16 +64,16 @@ static void test13349() { { auto str = getFromSocket("/activewindow"); - EXPECT_CONTAINS(str, "at: 22,547"); - EXPECT_CONTAINS(str, "size: 931,511"); + EXPECT_CONTAINS(str, "at: 497,22"); + EXPECT_CONTAINS(str, "size: 456,1036"); } OK(getFromSocket("/dispatch movewindow r")); { auto str = getFromSocket("/activewindow"); - EXPECT_CONTAINS(str, "at: 967,547"); - EXPECT_CONTAINS(str, "size: 931,511"); + EXPECT_CONTAINS(str, "at: 967,22"); + EXPECT_CONTAINS(str, "size: 456,1036"); } // clean up diff --git a/hyprtester/src/tests/main/groups.cpp b/hyprtester/src/tests/main/groups.cpp index 6e7375ef..c1309cc0 100644 --- a/hyprtester/src/tests/main/groups.cpp +++ b/hyprtester/src/tests/main/groups.cpp @@ -201,6 +201,59 @@ static bool test() { NLog::log("{}Expecting 0 windows", Colors::YELLOW); EXPECT(Tests::windowCount(), 0); + // test movewindoworgroup: direction should be respected when extracting from group + NLog::log("{}Test movewindoworgroup respects direction out of group", Colors::YELLOW); + OK(getFromSocket("/keyword group:groupbar:enabled 0")); + { + auto kittyE = Tests::spawnKitty(); + if (!kittyE) { + NLog::log("{}Error: kitty did not spawn", Colors::RED); + return false; + } + + // group kitty, and new windows should be auto-grouped + OK(getFromSocket("/dispatch togglegroup")); + + auto kittyF = Tests::spawnKitty(); + if (!kittyF) { + NLog::log("{}Error: kitty did not spawn", Colors::RED); + return false; + } + EXPECT(Tests::windowCount(), 2); + + // both windows should be grouped at the same position + { + auto str = getFromSocket("/clients"); + EXPECT_COUNT_STRING(str, "at: 22,22", 2); + } + + // move active window out of group to the right + NLog::log("{}Test movewindoworgroup r", Colors::YELLOW); + OK(getFromSocket("/dispatch movewindoworgroup r")); + + // the group should stay at x=22, the extracted window should be to the right + { + auto str = getFromSocket("/clients"); + EXPECT_COUNT_STRING(str, "at: 22,22", 1); + } + + // move it back into the group + OK(getFromSocket("/dispatch moveintogroup l")); + + // move active window out of group downward + NLog::log("{}Test movewindoworgroup d", Colors::YELLOW); + OK(getFromSocket("/dispatch movewindoworgroup d")); + + // the group should stay at y=22, the extracted window should be below + { + auto str = getFromSocket("/clients"); + EXPECT_COUNT_STRING(str, "at: 22,22", 1); + } + + Tests::killAllWindows(); + EXPECT(Tests::windowCount(), 0); + } + return !ret; } diff --git a/src/desktop/view/Group.cpp b/src/desktop/view/Group.cpp index a14ea0be..06884cff 100644 --- a/src/desktop/view/Group.cpp +++ b/src/desktop/view/Group.cpp @@ -120,7 +120,7 @@ void CGroup::add(PHLWINDOW w) { m_target->recalc(); } -void CGroup::remove(PHLWINDOW w) { +void CGroup::remove(PHLWINDOW w, Math::eDirection dir) { std::optional idx; for (size_t i = 0; i < m_windows.size(); ++i) { if (m_windows.at(i) == w) { @@ -156,8 +156,20 @@ void CGroup::remove(PHLWINDOW w) { updateWindowVisibility(); // do this here: otherwise the new current is hidden and workspace rules get wrong data - if (!REMOVING_GROUP) - w->m_target->assignToSpace(m_target->space()); + if (!REMOVING_GROUP) { + std::optional focalPoint; + if (dir != Math::DIRECTION_DEFAULT) { + const auto box = m_target->position(); + switch (dir) { + case Math::DIRECTION_RIGHT: focalPoint = Vector2D(box.x + box.w, box.y + box.h / 2.0); break; + case Math::DIRECTION_LEFT: focalPoint = Vector2D(box.x, box.y + box.h / 2.0); break; + case Math::DIRECTION_DOWN: focalPoint = Vector2D(box.x + box.w / 2.0, box.y + box.h); break; + case Math::DIRECTION_UP: focalPoint = Vector2D(box.x + box.w / 2.0, box.y); break; + default: break; + } + } + w->m_target->assignToSpace(m_target->space(), focalPoint); + } } void CGroup::moveCurrent(bool next) { diff --git a/src/desktop/view/Group.hpp b/src/desktop/view/Group.hpp index 8a7bb840..36c4baae 100644 --- a/src/desktop/view/Group.hpp +++ b/src/desktop/view/Group.hpp @@ -1,6 +1,7 @@ #pragma once #include "../DesktopTypes.hpp" +#include "../../helpers/math/Direction.hpp" #include @@ -17,7 +18,7 @@ namespace Desktop::View { bool has(PHLWINDOW w) const; void add(PHLWINDOW w); - void remove(PHLWINDOW w); + void remove(PHLWINDOW w, Math::eDirection dir = Math::DIRECTION_DEFAULT); void moveCurrent(bool next); void setCurrent(size_t idx); void setCurrent(PHLWINDOW w); diff --git a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp index a1fcf521..1c8c43a7 100644 --- a/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp +++ b/src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp @@ -184,7 +184,7 @@ void CDwindleAlgorithm::addTarget(SP target, bool newTarget) { // whether or not the override persists after opening one window if (*PERMANENTDIRECTIONOVERRIDE == 0) m_overrideDirection = Math::DIRECTION_DEFAULT; - } else if (*PSMARTSPLIT == 1) { + } else if (*PSMARTSPLIT == 1 || m_overrideFocalPoint) { const auto PARENT_CENTER = NEWPARENT->box.pos() + NEWPARENT->box.size() / 2; const auto PARENT_PROPORTIONS = NEWPARENT->box.h / NEWPARENT->box.w; const auto DELTA = MOUSECOORDS - PARENT_CENTER; diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c360bd27..1640efc3 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2750,7 +2750,9 @@ void CKeybindManager::moveWindowOutOfGroup(PHLWINDOW pWindow, const std::string& WP group = pWindow->m_group; - pWindow->m_group->remove(pWindow); + const auto direction = !dir.empty() ? Math::fromChar(dir[0]) : Math::DIRECTION_DEFAULT; + + pWindow->m_group->remove(pWindow, direction); if (*BFOCUSREMOVEDWINDOW || !group) { Desktop::focusState()->fullWindowFocus(pWindow, Desktop::FOCUS_REASON_KEYBIND);