summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Silva <123550+andresilva@users.noreply.github.com>2026-03-02 21:12:27 +0000
committerGitHub <noreply@github.com>2026-03-02 21:12:27 +0000
commitfe0a20213783a3dcedb4ad30e79e5a6cc9dc3d75 (patch)
treedc802acd1b2de549d762a55a21d5c2c7694dd247
parent75a815fbf28b73f3b9f9b9246ed3eb1fbd9b2a58 (diff)
desktop/group: respect direction when moving window out of group (#13490)
-rw-r--r--hyprtester/src/tests/main/dwindle.cpp8
-rw-r--r--hyprtester/src/tests/main/groups.cpp53
-rw-r--r--src/desktop/view/Group.cpp18
-rw-r--r--src/desktop/view/Group.hpp3
-rw-r--r--src/layout/algorithm/tiled/dwindle/DwindleAlgorithm.cpp2
-rw-r--r--src/managers/KeybindManager.cpp4
6 files changed, 78 insertions, 10 deletions
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<size_t> 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<Vector2D> 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 <vector>
@@ -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<ITarget> 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<Desktop::View::CGroup> 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);