From 6f45fce9e88b07ea3761a5629bafc7e51088c6d6 Mon Sep 17 00:00:00 2001 From: Aqa-Ib Date: Sun, 6 Oct 2024 18:18:28 +0200 Subject: [PATCH] layout: add drag_into_group to control whether dragging a window into a unlocked group will merge them --- src/config/ConfigDescriptions.hpp | 6 ++ src/config/ConfigManager.cpp | 1 + src/layout/IHyprLayout.cpp | 65 ++++++++++++++++--- src/layout/IHyprLayout.hpp | 5 ++ .../decorations/CHyprGroupBarDecoration.cpp | 41 +++++++++++- 5 files changed, 105 insertions(+), 13 deletions(-) diff --git a/src/config/ConfigDescriptions.hpp b/src/config/ConfigDescriptions.hpp index 385d4e59e1d..7d69004e0ad 100644 --- a/src/config/ConfigDescriptions.hpp +++ b/src/config/ConfigDescriptions.hpp @@ -778,6 +778,12 @@ inline static const std::vector CONFIG_OPTIONS = { .type = CONFIG_OPTION_BOOL, .data = SConfigOptionDescription::SBoolData{true}, }, + SConfigOptionDescription{ + .value = "group:drag_into_group", + .description = "whether dragging a window into a unlocked group will merge them. Options: 0 (disabled), 1 (enabled), 2 (only when dragging into the groupbar)", + .type = CONFIG_OPTION_INT, + .data = SConfigOptionDescription::SRangeData{1, 0, 2}, + }, /* * group:groupbar: diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 2ce07ff0bb3..1f15f8f47de 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -378,6 +378,7 @@ CConfigManager::CConfigManager() { 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:drag_into_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/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index f090e87ddbe..936b0f414ed 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -335,21 +335,45 @@ void IHyprLayout::onEndDragWindow() { g_pInputManager->currentlyDraggedWindow.reset(); g_pInputManager->m_bWasDraggingWindow = true; - if (DRAGGINGWINDOW->m_bDraggingTiled) { - DRAGGINGWINDOW->m_bIsFloating = false; - g_pInputManager->refocus(); - changeWindowFloatingMode(DRAGGINGWINDOW); - DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; - } else if (g_pInputManager->dragMode == MBIND_MOVE) { + if (g_pInputManager->dragMode == MBIND_MOVE) { g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - PHLWINDOW pWindow = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING | FLOATING_ONLY, DRAGGINGWINDOW); + PHLWINDOW pWindow = g_pCompositor->vectorToWindowUnified(MOUSECOORDS, RESERVED_EXTENTS | INPUT_EXTENTS | ALLOW_FLOATING, DRAGGINGWINDOW); if (pWindow) { if (pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, DRAGGINGWINDOW)) return; - if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow)) { + bool denied = false; + if (!pWindow->m_bIsFloating && !DRAGGINGWINDOW->m_bDraggingTiled) + denied = true; + + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (pWindow->m_sGroupData.pNextWindow.lock() && DRAGGINGWINDOW->canBeGroupedInto(pWindow) && *PDRAGINTOGROUP == 1 && !denied) { + // fix grouping into a floating group + if (pWindow->m_bIsFloating) { + g_pXWaylandManager->setWindowSize(DRAGGINGWINDOW, pWindow->m_vRealSize.goal()); // match the size of the window + if (DRAGGINGWINDOW->m_sGroupData.pNextWindow.lock()) { + std::vector members; + PHLWINDOW curr = DRAGGINGWINDOW->getGroupHead(); + do { + members.push_back(curr); + curr = curr->m_sGroupData.pNextWindow.lock(); + } while (curr != members[0]); + + for (auto it = members.begin(); it != members.end(); ++it) { + (*it)->m_vRealSize = pWindow->m_vRealSize.goal(); // match the size of group members + g_pLayoutManager->getCurrentLayout()->matchFloatingState(*it, pWindow); // match the floating state of group members + } + } + } + + if (DRAGGINGWINDOW->m_bDraggingTiled) { + changeWindowFloatingMode(DRAGGINGWINDOW); + DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; + DRAGGINGWINDOW->m_bDraggingTiled = false; + } + static auto USECURRPOS = CConfigValue("group:insert_after_current"); (*USECURRPOS ? pWindow : pWindow->getGroupTail())->insertWindowToGroup(DRAGGINGWINDOW); pWindow->setGroupCurrent(DRAGGINGWINDOW); @@ -361,6 +385,13 @@ void IHyprLayout::onEndDragWindow() { } } + if (DRAGGINGWINDOW->m_bDraggingTiled) { + DRAGGINGWINDOW->m_bIsFloating = false; + g_pInputManager->refocus(); + changeWindowFloatingMode(DRAGGINGWINDOW); + DRAGGINGWINDOW->m_vLastFloatingSize = m_vDraggingWindowOriginalFloatSize; + } + g_pHyprRenderer->damageWindow(DRAGGINGWINDOW); g_pCompositor->focusWindow(DRAGGINGWINDOW); @@ -553,10 +584,10 @@ void IHyprLayout::changeWindowFloatingMode(PHLWINDOW pWindow) { pWindow->m_vLastFloatingSize = PSAVEDSIZE; - // move to narnia because we don't wanna find our own node. onWindowCreated should apply the coords back. + // move to narnia because we don't wanna find our own node. onWindowCreatedTiling should apply the coords back. pWindow->m_vPosition = Vector2D(-999999, -999999); - onWindowCreated(pWindow); + onWindowCreatedTiling(pWindow); pWindow->m_vRealPosition.setValue(PSAVEDPOS); pWindow->m_vRealSize.setValue(PSAVEDSIZE); @@ -758,4 +789,18 @@ Vector2D IHyprLayout::predictSizeForNewWindow(PHLWINDOW pWindow) { return sizePredicted; } +void IHyprLayout::matchFloatingState(PHLWINDOW pTarget, PHLWINDOW pReference) { + switch (pTarget->m_bIsFloating) { + case false: + if (pReference->m_bIsFloating) + pTarget->m_bIsFloating = true; + break; + + case true: + if (!pReference->m_bIsFloating) + pTarget->m_bIsFloating = false; + break; + } +} + IHyprLayout::~IHyprLayout() {} diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp index f9e2de0da74..4aadf628f8f 100644 --- a/src/layout/IHyprLayout.hpp +++ b/src/layout/IHyprLayout.hpp @@ -196,6 +196,11 @@ class IHyprLayout { virtual Vector2D predictSizeForNewWindow(PHLWINDOW pWindow); virtual Vector2D predictSizeForNewWindowFloating(PHLWINDOW pWindow); + /* + Change the target window to match the reference window floating state + */ + virtual void matchFloatingState(PHLWINDOW pTarget, PHLWINDOW pReference); + private: int m_iMouseMoveEventCount; Vector2D m_vBeginDragXY; diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 4cdb9043e53..ef53d15db99 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -402,8 +402,9 @@ bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { } bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWINDOW pDraggedWindow) { - static auto PSTACKED = CConfigValue("group:groupbar:stacked"); - if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock())) + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); + static auto PDRAGINTOGROUP = CConfigValue("group:drag_into_group"); + if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2)) return false; const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; @@ -442,8 +443,42 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND } members[0]->m_sGroupData.head = true; members[0]->m_sGroupData.locked = WASLOCKED; - } else { + } else g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pDraggedWindow); + + // fix grouping into a floating group + if (pWindowInsertAfter->m_bIsFloating) { + g_pXWaylandManager->setWindowSize(pDraggedWindow, pWindowInsertAfter->m_vRealSize.goal()); // match the size of the window + if (pDraggedWindow->m_sGroupData.pNextWindow.lock()) { + std::vector members; + PHLWINDOW curr = pDraggedWindow->getGroupHead(); + do { + members.push_back(curr); + curr = curr->m_sGroupData.pNextWindow.lock(); + } while (curr != members[0]); + + for (auto it = members.begin(); it != members.end(); ++it) { + (*it)->m_vRealSize = pWindowInsertAfter->m_vRealSize.goal(); // match the size of group members + g_pLayoutManager->getCurrentLayout()->matchFloatingState(*it, pWindowInsertAfter); // match the floating state of group members + } + } + } + + // fix grouping a floating window into a tiling group + if (!pWindowInsertAfter->m_bIsFloating && !g_pLayoutManager->getCurrentLayout()->isWindowTiled(pDraggedWindow)) { + if (pDraggedWindow->m_sGroupData.pNextWindow.lock()) { + std::vector members; + PHLWINDOW curr = pDraggedWindow->getGroupHead(); + do { + members.push_back(curr); + curr = curr->m_sGroupData.pNextWindow.lock(); + } while (curr != members[0]); + + for (auto it = members.begin(); it != members.end(); ++it) { + g_pLayoutManager->getCurrentLayout()->matchFloatingState(*it, pWindowInsertAfter); // match the floating state of group members + } + } else + g_pLayoutManager->getCurrentLayout()->matchFloatingState(pDraggedWindow, pWindowInsertAfter); } pWindowInsertAfter->insertWindowToGroup(pDraggedWindow);