diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 84ac1a41b09..47d8133aa85 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -772,6 +772,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_GRADIENT, .data = SConfigOptionDescription::SGradientData{"0x66775500"}, }, + SConfigOptionDescription{ + .value = "group:auto_group", + .description = "automatically group new windows", + .type = CONFIG_OPTION_BOOL, + .data = SConfigOptionDescription::SBoolData{true}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 27e8fdb05ad..0477be34b1f 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -376,6 +376,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:insert_after_current", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:focus_removed_window", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:merge_groups_on_drag", Hyprlang::INT{1}); + m_pConfig->addConfigValue("group:auto_group", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:enabled", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:font_family", {STRVAL_EMPTY}); m_pConfig->addConfigValue("group:groupbar:font_size", Hyprlang::INT{8}); diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 544483b1921..1c2c7cfa71a 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -322,7 +322,7 @@ void Events::listener_mapWindow(void* owner, void* data) { PWINDOW->updateWindowData(); if (PWINDOW->m_bIsFloating) { - g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(PWINDOW); + g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW); PWINDOW->m_bCreatedOverFullscreen = true; // size and move rules diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index c936d59cead..a38841fe603 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -340,26 +340,7 @@ void CHyprDwindleLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dir return; } - // if it's a group, add the window - if (OPENINGON->pWindow->m_sGroupData.pNextWindow.lock() // target is group - && pWindow->canBeGroupedInto(OPENINGON->pWindow.lock()) && !m_vOverrideFocalPoint) { // we are not moving window - m_lDwindleNodesData.remove(*PNODE); - - static auto USECURRPOS = CConfigValue("group:insert_after_current"); - (*USECURRPOS ? OPENINGON->pWindow.lock() : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); - - OPENINGON->pWindow->setGroupCurrent(pWindow); - pWindow->applyGroupRules(); - pWindow->updateWindowDecos(); - recalculateWindow(pWindow); - - if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); - - return; - } - - // If it's not, get the node under our cursor + // get the node under our cursor m_lDwindleNodesData.push_back(SDwindleNodeData()); const auto NEWPARENT = &m_lDwindleNodesData.back(); diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index c5a5373cc00..0fb78d02270 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -9,23 +9,25 @@ #include "../xwayland/XSurface.hpp" void IHyprLayout::onWindowCreated(PHLWINDOW pWindow, eDirection direction) { - if (pWindow->m_bIsFloating) { - onWindowCreatedFloating(pWindow); - } else { - CBox desiredGeometry = {}; - g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); + CBox desiredGeometry = {}; + g_pXWaylandManager->getGeometryForWindow(pWindow, &desiredGeometry); - if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { - const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); - pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f; - } else { - pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height); - } + if (desiredGeometry.width <= 5 || desiredGeometry.height <= 5) { + const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID); + pWindow->m_vLastFloatingSize = PMONITOR->vecSize / 2.f; + } else + pWindow->m_vLastFloatingSize = Vector2D(desiredGeometry.width, desiredGeometry.height); + + pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize; - pWindow->m_vPseudoSize = pWindow->m_vLastFloatingSize; + bool autoGrouped = IHyprLayout::onWindowCreatedAutoGroup(pWindow); + if (autoGrouped) + return; + if (pWindow->m_bIsFloating) + onWindowCreatedFloating(pWindow); + else onWindowCreatedTiling(pWindow, direction); - } } void IHyprLayout::onWindowRemoved(PHLWINDOW pWindow) { @@ -178,6 +180,47 @@ void IHyprLayout::onWindowCreatedFloating(PHLWINDOW pWindow) { } } +bool IHyprLayout::onWindowCreatedAutoGroup(PHLWINDOW pWindow) { + static auto AUTOGROUP = CConfigValue("group:auto_group"); + if ((*AUTOGROUP || g_pInputManager->m_bWasDraggingWindow) // check if auto_group is enabled, or, if the user is manually dragging the window into the group. + && g_pCompositor->m_pLastWindow.lock() // check if a focused window exists. + && g_pCompositor->m_pLastWindow != pWindow // fixes a freeze when activating togglefloat to transform a floating group into a tiled group. + && g_pCompositor->m_pLastWindow->m_pWorkspace == + pWindow + ->m_pWorkspace // fix for multimonitor: when there is a focused group in monitor 1 and monitor 2 is empty, this enables adding the first window of monitor 2 when using the mouse to focus it. + && g_pCompositor->m_pLastWindow->m_sGroupData.pNextWindow.lock() // check if the focused window is a group + && pWindow->canBeGroupedInto(g_pCompositor->m_pLastWindow.lock()) // check if the new window can be grouped into the focused group + && !g_pXWaylandManager->shouldBeFloated(pWindow)) { // don't group XWayland windows that should be floated. + + switch (pWindow->m_bIsFloating) { + case false: + if (g_pCompositor->m_pLastWindow->m_bIsFloating) + pWindow->m_bIsFloating = true; + break; + + case true: + if (!g_pCompositor->m_pLastWindow->m_bIsFloating) + pWindow->m_bIsFloating = false; + break; + } + + static auto USECURRPOS = CConfigValue("group:insert_after_current"); + (*USECURRPOS ? g_pCompositor->m_pLastWindow : g_pCompositor->m_pLastWindow->getGroupTail())->insertWindowToGroup(pWindow); + + g_pCompositor->m_pLastWindow->setGroupCurrent(pWindow); + pWindow->applyGroupRules(); + pWindow->updateWindowDecos(); + recalculateWindow(pWindow); + + if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) + pWindow->addWindowDeco(std::make_unique(pWindow)); + + return true; + } + + return false; +} + void IHyprLayout::onBeginDragWindow() { const auto DRAGGINGWINDOW = g_pInputManager->currentlyDraggedWindow.lock(); diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index 7e0d5704b05..f9e2de0da74 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -47,6 +47,7 @@ class IHyprLayout { virtual void onWindowCreated(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT); virtual void onWindowCreatedTiling(PHLWINDOW, eDirection direction = DIRECTION_DEFAULT) = 0; virtual void onWindowCreatedFloating(PHLWINDOW); + virtual bool onWindowCreatedAutoGroup(PHLWINDOW); /* Return tiled status diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 8fa324b0d3d..04a6ea29091 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -116,26 +116,6 @@ void CHyprMasterLayout::onWindowCreatedTiling(PHLWINDOW pWindow, eDirection dire return; } - // if it's a group, add the window - if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow.lock() // target is group - && pWindow->canBeGroupedInto(OPENINGON->pWindow.lock())) { - - m_lMasterNodesData.remove(*PNODE); - - static auto USECURRPOS = CConfigValue("group:insert_after_current"); - (*USECURRPOS ? OPENINGON->pWindow.lock() : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); - - OPENINGON->pWindow->setGroupCurrent(pWindow); - pWindow->applyGroupRules(); - pWindow->updateWindowDecos(); - recalculateWindow(pWindow); - - if (!pWindow->getDecorationByType(DECORATION_GROUPBAR)) - pWindow->addWindowDeco(std::make_unique(pWindow)); - - return; - } - pWindow->applyGroupRules(); static auto PDROPATCURSOR = CConfigValue("master:drop_at_cursor");