From edf7098345b4498e937d25ace9d9b535c0eade34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Silva?= <123550+andresilva@users.noreply.github.com> Date: Tue, 3 Mar 2026 20:56:02 +0000 Subject: [PATCH] desktop/window: fix floating windows being auto-grouped (#13475) --------- Co-authored-by: Aqa-Ib <16420574+Aqa-Ib@users.noreply.github.com> --- hyprtester/src/tests/clients/child-window.cpp | 27 +++++++++++++ hyprtester/src/tests/main/groups.cpp | 40 +++++++++++++++++++ src/desktop/view/Window.cpp | 11 ++--- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/hyprtester/src/tests/clients/child-window.cpp b/hyprtester/src/tests/clients/child-window.cpp index 1b497c3d..a5680d4f 100644 --- a/hyprtester/src/tests/clients/child-window.cpp +++ b/hyprtester/src/tests/clients/child-window.cpp @@ -118,6 +118,33 @@ static bool test() { Tests::killAllWindows(); EXPECT(Tests::windowCount(), 0); + // test that child windows (shouldBeFloated) are not auto-grouped + NLog::log("{}Test child windows are not auto-grouped", Colors::GREEN); + auto kitty = Tests::spawnKitty(); + if (!kitty) { + NLog::log("{}Error: kitty did not spawn", Colors::RED); + return false; + } + + // create group and enable auto-grouping + OK(getFromSocket("/dispatch togglegroup")); + OK(getFromSocket("/keyword group:auto_group true")); + + SClient client2; + if (!startClient(client2)) + return false; + + EXPECT(Tests::windowCount(), 2); + createChild(client2); + EXPECT(Tests::windowCount(), 3); + + // child has set_parent so shouldBeFloated returns true, it should not be auto-grouped + EXPECT_COUNT_STRING(getFromSocket("/clients"), "grouped: 0", 1); + + stopClient(client2); + Tests::killAllWindows(); + EXPECT(Tests::windowCount(), 0); + return !ret; } diff --git a/hyprtester/src/tests/main/groups.cpp b/hyprtester/src/tests/main/groups.cpp index c1309cc0..2f9c5062 100644 --- a/hyprtester/src/tests/main/groups.cpp +++ b/hyprtester/src/tests/main/groups.cpp @@ -254,6 +254,46 @@ static bool test() { EXPECT(Tests::windowCount(), 0); } + // test that we deny a floated window getting auto-grouped into a tiled group. + NLog::log("{}Test that we deny a floated window getting auto-grouped into a tiled group.", Colors::GREEN); + + OK(getFromSocket("/keyword windowrule[kitty-tiled]:match:class kitty_tiled")); + OK(getFromSocket("/keyword windowrule[kitty-tiled]:tile yes")); + auto kittyProcE = Tests::spawnKitty("kitty_tiled"); + if (!kittyProcE) { + NLog::log("{}Error: kitty did not spawn", Colors::RED); + return false; + } + OK(getFromSocket("/dispatch togglegroup")); + + OK(getFromSocket("/keyword windowrule[kitty-floated]:match:class kitty_floated")); + OK(getFromSocket("/keyword windowrule[kitty-floated]:float yes")); + auto kittyProcF = Tests::spawnKitty("kitty_floated"); + if (!kittyProcF) { + NLog::log("{}Error: kitty did not spawn", Colors::RED); + return false; + } + + EXPECT(Tests::windowCount(), 2); + + { + auto clients = getFromSocket("/clients"); + auto classPos = clients.find("class: kitty_floated"); + if (classPos == std::string::npos) { + NLog::log("{}Could not find kitty_floated in clients output", Colors::RED); + ret = 1; + } else { + auto entryStart = clients.rfind("Window ", classPos); + auto entryEnd = clients.find("\n\n", classPos); + auto windowEntry = clients.substr(entryStart, entryEnd - entryStart); + EXPECT_CONTAINS(windowEntry, "floating: 1"); + EXPECT_CONTAINS(windowEntry, "grouped: 0"); + } + } + + Tests::killAllWindows(); + EXPECT(Tests::windowCount(), 0); + return !ret; } diff --git a/src/desktop/view/Window.cpp b/src/desktop/view/Window.cpp index 77c5f330..5d414c49 100644 --- a/src/desktop/view/Window.cpp +++ b/src/desktop/view/Window.cpp @@ -1947,11 +1947,12 @@ void CWindow::mapWindow() { g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", m_self.lock(), PWORKSPACE->m_name, m_class, m_title)}); Event::bus()->m_events.window.openEarly.emit(m_self.lock()); - if (*PAUTOGROUP // auto_group enabled - && Desktop::focusState()->window() // focused window exists - && canBeGroupedInto(Desktop::focusState()->window()->m_group) // we can group - && Desktop::focusState()->window()->m_workspace == m_workspace // workspaces match, we're not opening on another ws - && !isModal() && !(parent() && m_isFloating) && !isX11OverrideRedirect() // not a modal, floating child or X11 OR + if (*PAUTOGROUP // auto_group enabled + && Desktop::focusState()->window() // focused window exists + && canBeGroupedInto(Desktop::focusState()->window()->m_group) // we can group + && Desktop::focusState()->window()->m_workspace == m_workspace // workspaces match, we're not opening on another ws + && !g_pXWaylandManager->shouldBeFloated(m_self.lock()) && !isX11OverrideRedirect() // not a window that should float or X11 + && !(m_isFloating && !Desktop::focusState()->window()->m_isFloating) // do not auto-group a floated window into a tiled group ) { // add to group if we are focused on one Desktop::focusState()->window()->m_group->add(m_self.lock());