From b0cb7be9aa816e394c9f600eae09cabdd9a4460e Mon Sep 17 00:00:00 2001 From: Tom Benham Date: Thu, 15 Jan 2026 11:43:44 +0100 Subject: [PATCH 1/3] swallowing: fix unwanted reswallow when process opens a secondary window --- src/desktop/view/Window.cpp | 12 ++++++++---- src/desktop/view/Window.hpp | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/desktop/view/Window.cpp b/src/desktop/view/Window.cpp index 77c5f3301..7bc70d464 100644 --- a/src/desktop/view/Window.cpp +++ b/src/desktop/view/Window.cpp @@ -1939,9 +1939,12 @@ void CWindow::mapWindow() { // Verify window swallowing. Get the swallower before calling onWindowCreated(m_self.lock()) because getSwallower() wouldn't get it after if m_self.lock() gets auto grouped. const auto SWALLOWER = getSwallower(); - m_swallowed = SWALLOWER; - if (m_swallowed) - m_swallowed->m_currentlySwallowed = true; + // m_hasSwallower prevents secondary windows to swallow the parent when it's been unswallowed with `toggleswallow`. + if (SWALLOWER && !SWALLOWER->m_hasSwallower) { + SWALLOWER->m_currentlySwallowed = true; + SWALLOWER->m_hasSwallower = true; + m_swallowed = SWALLOWER; + } // emit the IPC event before the layout might focus the window to avoid a focus event first g_pEventManager->postEvent(SHyprIPCEvent{"openwindow", std::format("{:x},{},{},{}", m_self.lock(), PWORKSPACE->m_name, m_class, m_title)}); @@ -2068,7 +2071,7 @@ void CWindow::mapWindow() { } // swallow - if (SWALLOWER) { + if (m_swallowed) { g_layoutManager->removeTarget(SWALLOWER->layoutTarget()); SWALLOWER->setHidden(true); } @@ -2166,6 +2169,7 @@ void CWindow::unmapWindow() { } m_swallowed->m_groupSwallowed = false; + m_swallowed->m_hasSwallower = false; m_swallowed.reset(); } diff --git a/src/desktop/view/Window.hpp b/src/desktop/view/Window.hpp index d689ae3f9..a9e302d2b 100644 --- a/src/desktop/view/Window.hpp +++ b/src/desktop/view/Window.hpp @@ -235,6 +235,7 @@ namespace Desktop::View { PHLWINDOWREF m_swallowed; bool m_currentlySwallowed = false; bool m_groupSwallowed = false; + bool m_hasSwallower = false; // for toplevel monitor events MONITORID m_lastSurfaceMonitorID = -1; From 0545f39ae59fc3318bc509980c4eb4fa6c392ffb Mon Sep 17 00:00:00 2001 From: Tom Benham Date: Thu, 15 Jan 2026 11:51:11 +0100 Subject: [PATCH 2/3] swallowing: improved naming coherency --- src/debug/HyprCtl.cpp | 4 +-- src/desktop/view/Window.cpp | 46 ++++++++++++++++----------------- src/desktop/view/Window.hpp | 4 +-- src/managers/KeybindManager.cpp | 16 ++++++------ 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/debug/HyprCtl.cpp b/src/debug/HyprCtl.cpp index 417767e19..77c37340d 100644 --- a/src/debug/HyprCtl.cpp +++ b/src/debug/HyprCtl.cpp @@ -401,7 +401,7 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { escapeJSONStrings(!w->m_workspace ? "" : w->m_workspace->m_name), (sc(w->m_isFloating) == 1 ? "true" : "false"), w->monitorID(), escapeJSONStrings(w->m_class), escapeJSONStrings(w->m_title), escapeJSONStrings(w->m_initialClass), escapeJSONStrings(w->m_initialTitle), w->getPID(), (sc(w->m_isX11) == 1 ? "true" : "false"), (w->m_pinned ? "true" : "false"), sc(w->m_fullscreenState.internal), sc(w->m_fullscreenState.client), (w->m_createdOverFullscreen ? "true" : "false"), - getGroupedData(w, format), getTagsData(w, format), rc(w->m_swallowed.get()), getFocusHistoryID(w), + getGroupedData(w, format), getTagsData(w, format), rc(w->m_swallowee.get()), getFocusHistoryID(w), (g_pInputManager->isWindowInhibiting(w, false) ? "true" : "false"), escapeJSONStrings(w->xdgTag().value_or("")), escapeJSONStrings(w->xdgDescription().value_or("")), escapeJSONStrings(NContentType::toString(w->getContentType())), w->m_stableID); } else { @@ -416,7 +416,7 @@ std::string CHyprCtl::getWindowData(PHLWINDOW w, eHyprCtlOutputFormat format) { sc(w->m_realSize->goal().x), sc(w->m_realSize->goal().y), w->m_workspace ? w->workspaceID() : WORKSPACE_INVALID, (!w->m_workspace ? "" : w->m_workspace->m_name), sc(w->m_isFloating), w->monitorID(), w->m_class, w->m_title, w->m_initialClass, w->m_initialTitle, w->getPID(), sc(w->m_isX11), sc(w->m_pinned), sc(w->m_fullscreenState.internal), sc(w->m_fullscreenState.client), sc(w->m_createdOverFullscreen), - getGroupedData(w, format), getTagsData(w, format), rc(w->m_swallowed.get()), getFocusHistoryID(w), sc(g_pInputManager->isWindowInhibiting(w, false)), + getGroupedData(w, format), getTagsData(w, format), rc(w->m_swallowee.get()), getFocusHistoryID(w), sc(g_pInputManager->isWindowInhibiting(w, false)), w->xdgTag().value_or(""), w->xdgDescription().value_or(""), NContentType::toString(w->getContentType()), w->m_stableID); } } diff --git a/src/desktop/view/Window.cpp b/src/desktop/view/Window.cpp index 7bc70d464..f41601d68 100644 --- a/src/desktop/view/Window.cpp +++ b/src/desktop/view/Window.cpp @@ -518,10 +518,10 @@ void CWindow::moveToWorkspace(PHLWORKSPACE pWorkspace) { Event::bus()->m_events.window.moveToWorkspace.emit(m_self.lock(), pWorkspace); } - if (const auto SWALLOWED = m_swallowed.lock()) { - if (SWALLOWED->m_currentlySwallowed) { - SWALLOWED->moveToWorkspace(pWorkspace); - SWALLOWED->m_monitor = m_monitor; + if (const auto SWALLOWEE = m_swallowee.lock()) { + if (SWALLOWEE->m_currentlySwallowed) { + SWALLOWEE->moveToWorkspace(pWorkspace); + SWALLOWEE->m_monitor = m_monitor; } } @@ -1265,7 +1265,7 @@ void CWindow::warpCursor(bool force) { g_pCompositor->warpCursorTo(middle(), force); } -PHLWINDOW CWindow::getSwallower() { +PHLWINDOW CWindow::getSwallowee() { static auto PSWALLOWREGEX = CConfigValue("misc:swallow_regex"); static auto PSWALLOWEXREGEX = CConfigValue("misc:swallow_exception_regex"); static auto PSWALLOW = CConfigValue("misc:enable_swallow"); @@ -1937,13 +1937,13 @@ void CWindow::mapWindow() { updateWindowData(); - // Verify window swallowing. Get the swallower before calling onWindowCreated(m_self.lock()) because getSwallower() wouldn't get it after if m_self.lock() gets auto grouped. - const auto SWALLOWER = getSwallower(); + // Verify window swallowing. Get the swallowee before calling onWindowCreated(m_self.lock()) because getSwallowee() wouldn't get it after if m_self.lock() gets auto grouped. + const auto SWALLOWEE = getSwallowee(); // m_hasSwallower prevents secondary windows to swallow the parent when it's been unswallowed with `toggleswallow`. - if (SWALLOWER && !SWALLOWER->m_hasSwallower) { - SWALLOWER->m_currentlySwallowed = true; - SWALLOWER->m_hasSwallower = true; - m_swallowed = SWALLOWER; + if (SWALLOWEE && !SWALLOWEE->m_hasSwallower) { + SWALLOWEE->m_currentlySwallowed = true; + SWALLOWEE->m_hasSwallower = true; + m_swallowee = SWALLOWEE; } // emit the IPC event before the layout might focus the window to avoid a focus event first @@ -2071,9 +2071,9 @@ void CWindow::mapWindow() { } // swallow - if (m_swallowed) { - g_layoutManager->removeTarget(SWALLOWER->layoutTarget()); - SWALLOWER->setHidden(true); + if (m_swallowee) { + g_layoutManager->removeTarget(SWALLOWEE->layoutTarget()); + SWALLOWEE->setHidden(true); } m_firstMap = false; @@ -2157,20 +2157,20 @@ void CWindow::unmapWindow() { g_pHyprRenderer->makeSnapshot(m_self.lock()); // swallowing - if (valid(m_swallowed)) { - if (m_swallowed->m_currentlySwallowed) { - m_swallowed->m_currentlySwallowed = false; - m_swallowed->setHidden(false); + if (const auto SWALLOWEE = m_swallowee.lock()) { + if (SWALLOWEE->m_currentlySwallowed) { + SWALLOWEE->m_currentlySwallowed = false; + SWALLOWEE->setHidden(false); if (m_group) - m_swallowed->m_groupSwallowed = true; // flag for the swallowed window to be created into the group where it belongs when auto_group = false. + SWALLOWEE->m_groupSwallowed = true; // flag for the swallowed window to be created into the group where it belongs when auto_group = false. - g_layoutManager->newTarget(m_swallowed->layoutTarget(), m_workspace->m_space); + g_layoutManager->newTarget(SWALLOWEE->layoutTarget(), m_workspace->m_space); } - m_swallowed->m_groupSwallowed = false; - m_swallowed->m_hasSwallower = false; - m_swallowed.reset(); + SWALLOWEE->m_groupSwallowed = false; + SWALLOWEE->m_hasSwallower = false; + m_swallowee.reset(); } bool wasLastWindow = false; diff --git a/src/desktop/view/Window.hpp b/src/desktop/view/Window.hpp index a9e302d2b..2e55b65d8 100644 --- a/src/desktop/view/Window.hpp +++ b/src/desktop/view/Window.hpp @@ -232,7 +232,7 @@ namespace Desktop::View { PHLANIMVAR m_movingToWorkspaceAlpha; // swallowing - PHLWINDOWREF m_swallowed; + PHLWINDOWREF m_swallowee; bool m_currentlySwallowed = false; bool m_groupSwallowed = false; bool m_hasSwallower = false; @@ -323,7 +323,7 @@ namespace Desktop::View { std::string fetchTitle(); std::string fetchClass(); void warpCursor(bool force = false); - PHLWINDOW getSwallower(); + PHLWINDOW getSwallowee(); bool isX11OverrideRedirect(); bool isModal(); Vector2D realToReportSize(); diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index c9c512ae5..4e421eb89 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -2205,19 +2205,19 @@ SDispatchResult CKeybindManager::tagWindow(std::string args) { SDispatchResult CKeybindManager::toggleSwallow(std::string args) { PHLWINDOWREF pWindow = Desktop::focusState()->window(); - if (!valid(pWindow) || !valid(pWindow->m_swallowed)) + if (!valid(pWindow) || !valid(pWindow->m_swallowee)) return {}; - if (pWindow->m_swallowed->m_currentlySwallowed) { + if (pWindow->m_swallowee->m_currentlySwallowed) { // Unswallow - pWindow->m_swallowed->m_currentlySwallowed = false; - pWindow->m_swallowed->setHidden(false); - g_layoutManager->newTarget(pWindow->m_swallowed->layoutTarget(), pWindow->m_workspace->m_space); + pWindow->m_swallowee->m_currentlySwallowed = false; + pWindow->m_swallowee->setHidden(false); + g_layoutManager->newTarget(pWindow->m_swallowee->layoutTarget(), pWindow->m_workspace->m_space); } else { // Reswallow - pWindow->m_swallowed->m_currentlySwallowed = true; - pWindow->m_swallowed->setHidden(true); - g_layoutManager->removeTarget(pWindow->m_swallowed->layoutTarget()); + pWindow->m_swallowee->m_currentlySwallowed = true; + pWindow->m_swallowee->setHidden(true); + g_layoutManager->removeTarget(pWindow->m_swallowee->layoutTarget()); } return {}; From 6067a883b3f04dd29fb864f733390a26b4f851ab Mon Sep 17 00:00:00 2001 From: Tom Benham Date: Thu, 15 Jan 2026 11:53:12 +0100 Subject: [PATCH 3/3] clang-format --- src/desktop/view/Window.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/desktop/view/Window.cpp b/src/desktop/view/Window.cpp index f41601d68..793efb257 100644 --- a/src/desktop/view/Window.cpp +++ b/src/desktop/view/Window.cpp @@ -1942,8 +1942,8 @@ void CWindow::mapWindow() { // m_hasSwallower prevents secondary windows to swallow the parent when it's been unswallowed with `toggleswallow`. if (SWALLOWEE && !SWALLOWEE->m_hasSwallower) { SWALLOWEE->m_currentlySwallowed = true; - SWALLOWEE->m_hasSwallower = true; - m_swallowee = SWALLOWEE; + SWALLOWEE->m_hasSwallower = true; + m_swallowee = SWALLOWEE; } // emit the IPC event before the layout might focus the window to avoid a focus event first @@ -2169,7 +2169,7 @@ void CWindow::unmapWindow() { } SWALLOWEE->m_groupSwallowed = false; - SWALLOWEE->m_hasSwallower = false; + SWALLOWEE->m_hasSwallower = false; m_swallowee.reset(); }