diff --git a/src/Window.cpp b/src/Window.cpp index 2c6781f46..d04650238 100644 --- a/src/Window.cpp +++ b/src/Window.cpp @@ -653,6 +653,27 @@ CWindow* CWindow::getGroupCurrent() { return curr; } +int CWindow::getGroupSize() { + int size = 1; + CWindow* curr = this; + while (curr->m_sGroupData.pNextWindow != this) { + curr = curr->m_sGroupData.pNextWindow; + size++; + } + return size; +} + +CWindow* CWindow::getGroupWindowByIndex(int index) { + const int SIZE = getGroupSize(); + index = ((index % SIZE) + SIZE) % SIZE; + CWindow* curr = getGroupHead(); + while (index > 0) { + curr = curr->m_sGroupData.pNextWindow; + index--; + } + return curr; +} + void CWindow::setGroupCurrent(CWindow* pWindow) { CWindow* curr = this->m_sGroupData.pNextWindow; bool isMember = false; @@ -701,10 +722,8 @@ void CWindow::setGroupCurrent(CWindow* pWindow) { } void CWindow::insertWindowToGroup(CWindow* pWindow) { - static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue; - - const auto BEGINAT = *USECURRPOS ? this : getGroupTail(); - const auto ENDAT = *USECURRPOS ? m_sGroupData.pNextWindow : getGroupHead(); + const auto BEGINAT = this; + const auto ENDAT = m_sGroupData.pNextWindow; if (!pWindow->m_sGroupData.pNextWindow) { BEGINAT->m_sGroupData.pNextWindow = pWindow; diff --git a/src/Window.hpp b/src/Window.hpp index 307ff1ded..fecdfc55a 100644 --- a/src/Window.hpp +++ b/src/Window.hpp @@ -345,6 +345,8 @@ class CWindow { CWindow* getGroupTail(); CWindow* getGroupCurrent(); CWindow* getGroupPrevious(); + CWindow* getGroupWindowByIndex(int); + int getGroupSize(); void setGroupCurrent(CWindow* pWindow); void insertWindowToGroup(CWindow* pWindow); void updateGroupOutputs(); diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 831e3b176..2c353ab2d 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -108,6 +108,7 @@ void CConfigManager::setDefaultVars() { configValues["misc:cursor_zoom_factor"].floatValue = 1.f; configValues["misc:cursor_zoom_rigid"].intValue = 0; configValues["misc:allow_session_lock_restore"].intValue = 0; + configValues["misc:groupbar_scrolling"].intValue = 1; configValues["misc:group_insert_after_current"].intValue = 1; configValues["misc:render_titles_in_groupbar"].intValue = 1; configValues["misc:groupbar_titles_font_size"].intValue = 8; diff --git a/src/helpers/Region.cpp b/src/helpers/Region.cpp index e510e3d3d..38a3760bb 100644 --- a/src/helpers/Region.cpp +++ b/src/helpers/Region.cpp @@ -92,6 +92,15 @@ std::vector CRegion::getRects() const { return result; } +wlr_box CRegion::getExtents() { + pixman_box32_t* box = pixman_region32_extents(&m_rRegion); + return {box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1}; +} + +bool CRegion::containsPoint(const Vector2D& vec) { + return pixman_region32_contains_point(&m_rRegion, vec.x, vec.y, nullptr); +} + bool CRegion::empty() { return !pixman_region32_not_empty(&m_rRegion); } diff --git a/src/helpers/Region.hpp b/src/helpers/Region.hpp index 1ad3e57e6..42458234f 100644 --- a/src/helpers/Region.hpp +++ b/src/helpers/Region.hpp @@ -42,6 +42,8 @@ class CRegion { CRegion& intersect(double x, double y, double w, double h); CRegion& translate(const Vector2D& vec); CRegion& invert(pixman_box32_t* box); + wlr_box getExtents(); + bool containsPoint(const Vector2D& vec); bool empty(); std::vector getRects() const; @@ -52,4 +54,4 @@ class CRegion { private: pixman_region32_t m_rRegion; -}; \ No newline at end of file +}; diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp index e513c17dc..5bee0f4f1 100644 --- a/src/layout/DwindleLayout.cpp +++ b/src/layout/DwindleLayout.cpp @@ -312,28 +312,32 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) { return; } + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); + // if it's a group, add the window if (OPENINGON->pWindow->m_sGroupData.pNextWindow && !OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked && !g_pKeybindManager->m_bGroupsLocked) { // target is an unlocked group - if (!pWindow->m_sGroupData.pNextWindow) { // source is not a group + if (!pWindow->m_sGroupData.pNextWindow || !pWindow->getGroupHead()->m_sGroupData.locked) { // source is not a group or an unlocked group + if (!pWindow->m_sGroupData.pNextWindow) + pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); + m_lDwindleNodesData.remove(*PNODE); - OPENINGON->pWindow->insertWindowToGroup(pWindow); + + const wlr_box box = OPENINGON->pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); + if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse + const int SIZE = OPENINGON->pWindow->getGroupSize(); + const int INDEX = (int)((MOUSECOORDS.x - box.x) * 2 * SIZE / box.width + 1) / 2 - 1; + CWindow* pWindowInsertAfter = OPENINGON->pWindow->getGroupWindowByIndex(INDEX); + pWindowInsertAfter->insertWindowToGroup(pWindow); + if (INDEX == -1) + std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head); + } else { + static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue; + (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); + } + OPENINGON->pWindow->setGroupCurrent(pWindow); - - pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); - pWindow->updateWindowDecos(); - recalculateWindow(pWindow); - - g_pCompositor->focusWindow(pWindow); - return; - } - - if (!pWindow->getGroupHead()->m_sGroupData.locked) { // source is an unlocked group - m_lDwindleNodesData.remove(*PNODE); - OPENINGON->pWindow->insertWindowToGroup(pWindow); - OPENINGON->pWindow->setGroupCurrent(pWindow); - pWindow->updateWindowDecos(); recalculateWindow(pWindow); @@ -361,8 +365,6 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) { const auto SIDEBYSIDE = NEWPARENT->size.x > NEWPARENT->size.y * *PWIDTHMULTIPLIER; NEWPARENT->splitTop = !SIDEBYSIDE; - const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); - static auto* const PFORCESPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:force_split")->intValue; static auto* const PERMANENTDIRECTIONOVERRIDE = &g_pConfigManager->getConfigValuePtr("dwindle:permanent_direction_override")->intValue; static auto* const PSMARTSPLIT = &g_pConfigManager->getConfigValuePtr("dwindle:smart_split")->intValue; diff --git a/src/layout/IHyprLayout.cpp b/src/layout/IHyprLayout.cpp index 7ed6dd2e5..09cce144c 100644 --- a/src/layout/IHyprLayout.cpp +++ b/src/layout/IHyprLayout.cpp @@ -56,6 +56,9 @@ void IHyprLayout::onWindowRemoved(CWindow* pWindow) { pWindow->setHidden(false); + pWindow->updateWindowDecos(); + g_pCompositor->updateWindowAnimatedDecorationValues(pWindow); + return; } } diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index cab344f10..cae0f67af 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -91,28 +91,32 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) { getNodeFromWindow(g_pCompositor->m_pLastWindow) : getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID); + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); + // if it's a group, add the window if (OPENINGON && OPENINGON->pWindow->m_sGroupData.pNextWindow && !OPENINGON->pWindow->getGroupHead()->m_sGroupData.locked && !g_pKeybindManager->m_bGroupsLocked && OPENINGON != PNODE) { // target is an unlocked group - if (!pWindow->m_sGroupData.pNextWindow) { // source is not a group + if (!pWindow->m_sGroupData.pNextWindow || !pWindow->getGroupHead()->m_sGroupData.locked) { // source is not a group or an unlocked group + if (!pWindow->m_sGroupData.pNextWindow) + pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); + m_lMasterNodesData.remove(*PNODE); - OPENINGON->pWindow->insertWindowToGroup(pWindow); + + const wlr_box box = OPENINGON->pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); + if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { // TODO: Deny when not using mouse + const int SIZE = OPENINGON->pWindow->getGroupSize(); + const int INDEX = (int)((MOUSECOORDS.x - box.x) * 2 * SIZE / box.width + 1) / 2 - 1; + CWindow* pWindowInsertAfter = OPENINGON->pWindow->getGroupWindowByIndex(INDEX); + pWindowInsertAfter->insertWindowToGroup(pWindow); + if (INDEX == -1) + std::swap(pWindow->m_sGroupData.pNextWindow->m_sGroupData.head, pWindow->m_sGroupData.head); + } else { + static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue; + (*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow); + } + OPENINGON->pWindow->setGroupCurrent(pWindow); - - pWindow->m_dWindowDecorations.emplace_back(std::make_unique(pWindow)); - pWindow->updateWindowDecos(); - recalculateWindow(pWindow); - - g_pCompositor->focusWindow(pWindow); - return; - } - - if (!pWindow->getGroupHead()->m_sGroupData.locked) { // source is an unlocked group - m_lMasterNodesData.remove(*PNODE); - OPENINGON->pWindow->insertWindowToGroup(pWindow); - OPENINGON->pWindow->setGroupCurrent(pWindow); - pWindow->updateWindowDecos(); recalculateWindow(pWindow); @@ -266,8 +270,8 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { return; const auto PWORKSPACEDATA = getMasterWorkspaceData(ws); - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); - const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID); + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); + const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID); if (!PMASTERNODE) return; @@ -276,11 +280,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { bool centerMasterWindow = false; static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue; - const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID); - const auto WINDOWS = getNodesOnWorkspace(PWORKSPACE->m_iID); - const auto STACKWINDOWS = WINDOWS - MASTERS; - const auto WSSIZE = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; - const auto WSPOS = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; + const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID); + const auto WINDOWS = getNodesOnWorkspace(PWORKSPACE->m_iID); + const auto STACKWINDOWS = WINDOWS - MASTERS; + const auto WSSIZE = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight; + const auto WSPOS = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft; if (orientation == ORIENTATION_CENTER) { if (STACKWINDOWS >= 2 || (*ALWAYSCENTER == 1)) { @@ -315,7 +319,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (WIDTH > widthLeft * 0.9f && mastersLeft > 1) WIDTH = widthLeft * 0.9f; - nd.size = Vector2D(WIDTH, HEIGHT); + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -324,11 +328,11 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { nextX += WIDTH; } } else { // orientation left, right or center - float WIDTH = WSSIZE.x; - float heightLeft = WSSIZE.y; - int mastersLeft = MASTERS; - float nextX = 0; - float nextY = 0; + float WIDTH = WSSIZE.x; + float heightLeft = WSSIZE.y; + int mastersLeft = MASTERS; + float nextX = 0; + float nextY = 0; if (STACKWINDOWS > 0 || centerMasterWindow) WIDTH *= PMASTERNODE->percMaster; @@ -347,7 +351,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (HEIGHT > heightLeft * 0.9f && mastersLeft > 1) HEIGHT = heightLeft * 0.9f; - nd.size = Vector2D(WIDTH, HEIGHT); + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -379,7 +383,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (WIDTH > widthLeft * 0.9f && slavesLeft > 1) WIDTH = widthLeft * 0.9f; - nd.size = Vector2D(WIDTH, HEIGHT); + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -404,7 +408,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) HEIGHT = heightLeft * 0.9f; - nd.size = Vector2D(WIDTH, HEIGHT); + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -431,13 +435,13 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { continue; if (onRight) { - nextX = WIDTH + PMASTERNODE->size.x; - nextY = nextYR; + nextX = WIDTH + PMASTERNODE->size.x; + nextY = nextYR; heightLeft = heightLeftR; slavesLeft = slavesLeftR; } else { - nextX = 0; - nextY = nextYL; + nextX = 0; + nextY = nextYL; heightLeft = heightLeftL; slavesLeft = slavesLeftL; } @@ -446,7 +450,7 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) HEIGHT = heightLeft * 0.9f; - nd.size = Vector2D(WIDTH, HEIGHT); + nd.size = Vector2D(WIDTH, HEIGHT); nd.position = WSPOS + Vector2D(nextX, nextY); applyNodeDataToWindow(&nd); @@ -593,13 +597,13 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne return; } - const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); - const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace); + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID); + const auto PWORKSPACEDATA = getMasterWorkspaceData(PMONITOR->activeWorkspace); static auto* const ALWAYSCENTER = &g_pConfigManager->getConfigValuePtr("master:always_center_master")->intValue; - eOrientation orientation = PWORKSPACEDATA->orientation; - bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1); - double delta = 0; + eOrientation orientation = PWORKSPACEDATA->orientation; + bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1); + double delta = 0; if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1 && !centered) return; @@ -631,9 +635,10 @@ void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorne (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getMastersOnWorkspace(PNODE->workspaceID); PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95); } else if (!PNODE->isMaster && (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) > 1) { - const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ? - (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / (getNodesOnWorkspace(PNODE->workspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) : - (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / (getNodesOnWorkspace(PNODE->workspaceID) - getMastersOnWorkspace(PNODE->workspaceID)); + const auto SIZE = PWORKSPACEDATA->orientation % 2 == 1 ? (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) / + (getNodesOnWorkspace(PNODE->workspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) : + (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / + (getNodesOnWorkspace(PNODE->workspaceID) - getMastersOnWorkspace(PNODE->workspaceID)); PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95); } } diff --git a/src/managers/KeybindManager.cpp b/src/managers/KeybindManager.cpp index 81a2aaf5e..d626b8c66 100644 --- a/src/managers/KeybindManager.cpp +++ b/src/managers/KeybindManager.cpp @@ -1226,13 +1226,13 @@ void CKeybindManager::toggleGroup(std::string args) { w->m_sGroupData.head = false; } - bool prevState = g_pKeybindManager->m_bGroupsLocked; + const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked; g_pKeybindManager->m_bGroupsLocked = true; for (auto& w : members) { g_pLayoutManager->getCurrentLayout()->onWindowCreated(w); w->updateWindowDecos(); } - g_pKeybindManager->m_bGroupsLocked = prevState; + g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; } } @@ -1951,9 +1951,28 @@ void CKeybindManager::mouse(std::string args) { if (PRESSED) { g_pKeybindManager->m_bIsMouseBindActive = true; - g_pInputManager->currentlyDraggedWindow = g_pCompositor->vectorToWindowIdeal(g_pInputManager->getMouseCoordsInternal()); - g_pInputManager->dragMode = MBIND_MOVE; + const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); + CWindow* pWindow = g_pCompositor->vectorToWindowIdeal(mouseCoords); + if (pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(mouseCoords) && pWindow->m_sGroupData.pNextWindow) { + const wlr_box box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); + if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { + const int SIZE = pWindow->getGroupSize(); + pWindow = pWindow->getGroupWindowByIndex((mouseCoords.x - box.x) * SIZE / box.width); + + // hack + g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow); + if (!pWindow->m_bIsFloating) { + const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_bGroupsLocked; + g_pKeybindManager->m_bGroupsLocked = true; + g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow); + g_pKeybindManager->m_bGroupsLocked = GROUPSLOCKEDPREV; + } + } + } + + g_pInputManager->currentlyDraggedWindow = pWindow; + g_pInputManager->dragMode = MBIND_MOVE; g_pLayoutManager->getCurrentLayout()->onBeginDragWindow(); } else { g_pKeybindManager->m_bIsMouseBindActive = false; @@ -2046,7 +2065,7 @@ void CKeybindManager::moveIntoGroup(std::string args) { if (!PWINDOW || PWINDOW->m_bIsFloating) return; - const auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg); + auto PWINDOWINDIR = g_pCompositor->getWindowInDirection(PWINDOW, arg); if (!PWINDOWINDIR || !PWINDOWINDIR->m_sGroupData.pNextWindow) return; @@ -2059,6 +2078,9 @@ void CKeybindManager::moveIntoGroup(std::string args) { g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW); // This removes groupped property! + static const auto* USECURRPOS = &g_pConfigManager->getConfigValuePtr("misc:group_insert_after_current")->intValue; + PWINDOWINDIR = *USECURRPOS ? PWINDOWINDIR : PWINDOWINDIR->getGroupTail(); + PWINDOWINDIR->insertWindowToGroup(PWINDOW); PWINDOWINDIR->setGroupCurrent(PWINDOW); PWINDOW->updateWindowDecos(); diff --git a/src/managers/input/InputManager.cpp b/src/managers/input/InputManager.cpp index bdb5c5274..1739e7cc1 100644 --- a/src/managers/input/InputManager.cpp +++ b/src/managers/input/InputManager.cpp @@ -545,11 +545,25 @@ void CInputManager::processMouseDownNormal(wlr_pointer_button_event* e) { if (!PASS && !*PPASSMOUSE) return; + const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); + const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords); + + if (w && !w->m_bIsFullscreen && !w->hasPopupAt(mouseCoords) && w->m_sGroupData.pNextWindow) { + const wlr_box box = w->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); + if (wlr_box_contains_point(&box, mouseCoords.x, mouseCoords.y)) { + if (e->state == WLR_BUTTON_PRESSED) { + const int SIZE = w->getGroupSize(); + CWindow* pWindow = w->getGroupWindowByIndex((mouseCoords.x - box.x) * SIZE / box.width); + if (w != pWindow) + w->setGroupCurrent(pWindow); + } + return; + } + } + // clicking on border triggers resize // TODO detect click on LS properly if (*PRESIZEONBORDER && !m_bLastFocusOnLS) { - const auto mouseCoords = g_pInputManager->getMouseCoordsInternal(); - const auto w = g_pCompositor->vectorToWindowIdeal(mouseCoords); if (w && !w->m_bIsFullscreen) { const wlr_box real = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; if ((!wlr_box_contains_point(&real, mouseCoords.x, mouseCoords.y) || w->isInCurvedCorner(mouseCoords.x, mouseCoords.y)) && !w->hasPopupAt(mouseCoords)) { @@ -613,7 +627,8 @@ void CInputManager::processMouseDownKill(wlr_pointer_button_event* e) { } void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { - static auto* const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue; + static auto* const PSCROLLFACTOR = &g_pConfigManager->getConfigValuePtr("input:touchpad:scroll_factor")->floatValue; + static auto* const PGROUPBARSCROLLING = &g_pConfigManager->getConfigValuePtr("misc:groupbar_scrolling")->intValue; auto factor = (*PSCROLLFACTOR <= 0.f || e->source != WLR_AXIS_SOURCE_FINGER ? 1.f : *PSCROLLFACTOR); @@ -621,6 +636,20 @@ void CInputManager::onMouseWheel(wlr_pointer_axis_event* e) { g_pCompositor->notifyIdleActivity(); + const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal(); + const auto pWindow = g_pCompositor->vectorToWindowIdeal(MOUSECOORDS); + + if (*PGROUPBARSCROLLING && pWindow && !pWindow->m_bIsFullscreen && !pWindow->hasPopupAt(MOUSECOORDS) && pWindow->m_sGroupData.pNextWindow) { + const wlr_box box = pWindow->getDecorationByType(DECORATION_GROUPBAR)->getWindowDecorationRegion().getExtents(); + if (wlr_box_contains_point(&box, MOUSECOORDS.x, MOUSECOORDS.y)) { + if (e->delta > 0) + pWindow->setGroupCurrent(pWindow->m_sGroupData.pNextWindow); + else + pWindow->setGroupCurrent(pWindow->getGroupPrevious()); + return; + } + } + if (passEvent) wlr_seat_pointer_notify_axis(g_pCompositor->m_sSeat.seat, e->time_msec, e->orientation, factor * e->delta, std::round(factor * e->delta_discrete), e->source); } @@ -1546,7 +1575,7 @@ void CInputManager::setCursorIconOnBorder(CWindow* w) { wlr_box box = {w->m_vRealPosition.vec().x, w->m_vRealPosition.vec().y, w->m_vRealSize.vec().x, w->m_vRealSize.vec().y}; eBorderIconDirection direction = BORDERICON_NONE; wlr_box boxFullGrabInput = {box.x - *PEXTENDBORDERGRAB - BORDERSIZE, box.y - *PEXTENDBORDERGRAB - BORDERSIZE, box.width + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE), - box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; + box.height + 2 * (*PEXTENDBORDERGRAB + BORDERSIZE)}; if (!wlr_box_contains_point(&boxFullGrabInput, mouseCoords.x, mouseCoords.y) || (!m_lCurrentlyHeldButtons.empty() && !currentlyDraggedWindow)) { direction = BORDERICON_NONE; diff --git a/src/render/decorations/CHyprDropShadowDecoration.cpp b/src/render/decorations/CHyprDropShadowDecoration.cpp index 15f993c92..ee1a65a57 100644 --- a/src/render/decorations/CHyprDropShadowDecoration.cpp +++ b/src/render/decorations/CHyprDropShadowDecoration.cpp @@ -2,7 +2,7 @@ #include "../../Compositor.hpp" -CHyprDropShadowDecoration::CHyprDropShadowDecoration(CWindow* pWindow) { +CHyprDropShadowDecoration::CHyprDropShadowDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) { m_pWindow = pWindow; } diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 2414357e1..89e047caf 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -7,7 +7,7 @@ static CTexture m_tGradientActive; static CTexture m_tGradientInactive; -CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) { +CHyprGroupBarDecoration::CHyprGroupBarDecoration(CWindow* pWindow) : IHyprWindowDecoration(pWindow) { m_pWindow = pWindow; } @@ -306,3 +306,7 @@ void CHyprGroupBarDecoration::refreshGradients() { renderGradientTo(m_tGradientActive, ((CGradientValueData*)PCOLACTIVE->get())->m_vColors[0]); renderGradientTo(m_tGradientInactive, ((CGradientValueData*)PCOLINACTIVE->get())->m_vColors[0]); } + +bool CHyprGroupBarDecoration::allowsInput() { + return true; +} diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index ac6d103f4..118c7a649 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -33,6 +33,8 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { virtual SWindowDecorationExtents getWindowDecorationReservedArea(); + virtual bool allowsInput(); + private: SWindowDecorationExtents m_seExtents; @@ -52,4 +54,4 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { // STitleTexs* overriden = nullptr; // TODO: make shit shared in-group to decrease VRAM usage. std::deque> titleTexs; } m_sTitleTexs; -}; \ No newline at end of file +}; diff --git a/src/render/decorations/IHyprWindowDecoration.cpp b/src/render/decorations/IHyprWindowDecoration.cpp index 3ad5591f1..a87c334ab 100644 --- a/src/render/decorations/IHyprWindowDecoration.cpp +++ b/src/render/decorations/IHyprWindowDecoration.cpp @@ -2,12 +2,29 @@ #include "../../Window.hpp" +IHyprWindowDecoration::IHyprWindowDecoration(CWindow* pWindow) { + m_pWindow = pWindow; +} + IHyprWindowDecoration::~IHyprWindowDecoration() {} SWindowDecorationExtents IHyprWindowDecoration::getWindowDecorationReservedArea() { return SWindowDecorationExtents{}; } +CRegion IHyprWindowDecoration::getWindowDecorationRegion() { + const SWindowDecorationExtents RESERVED = getWindowDecorationReservedArea(); + const int BORDERSIZE = m_pWindow->getRealBorderSize(); + return CRegion(m_pWindow->m_vRealPosition.vec().x - (BORDERSIZE + RESERVED.topLeft.x) * (int)(RESERVED.topLeft.x != 0), + m_pWindow->m_vRealPosition.vec().y - (BORDERSIZE + RESERVED.topLeft.y) * (int)(RESERVED.topLeft.y != 0), + m_pWindow->m_vRealSize.vec().x + (BORDERSIZE + RESERVED.topLeft.x) * (int)(RESERVED.topLeft.x != 0) + + (BORDERSIZE + RESERVED.bottomRight.x) * (int)(RESERVED.bottomRight.x != 0), + m_pWindow->m_vRealSize.vec().y + (BORDERSIZE + RESERVED.topLeft.y) * (int)(RESERVED.topLeft.y != 0) + + (BORDERSIZE + RESERVED.bottomRight.y) * (int)(RESERVED.bottomRight.y != 0)) + .subtract(CRegion(m_pWindow->m_vRealPosition.vec().x - BORDERSIZE, m_pWindow->m_vRealPosition.vec().y - BORDERSIZE, m_pWindow->m_vRealSize.vec().x + 2 * BORDERSIZE, + m_pWindow->m_vRealSize.vec().y + 2 * BORDERSIZE)); +} + bool IHyprWindowDecoration::allowsInput() { return false; -} \ No newline at end of file +} diff --git a/src/render/decorations/IHyprWindowDecoration.hpp b/src/render/decorations/IHyprWindowDecoration.hpp index e5eb1bb97..fec7305da 100644 --- a/src/render/decorations/IHyprWindowDecoration.hpp +++ b/src/render/decorations/IHyprWindowDecoration.hpp @@ -1,6 +1,7 @@ #pragma once #include "../../defines.hpp" +#include "../../helpers/Region.hpp" enum eDecorationType { DECORATION_NONE = -1, @@ -19,6 +20,7 @@ class CMonitor; class IHyprWindowDecoration { public: + IHyprWindowDecoration(CWindow*); virtual ~IHyprWindowDecoration() = 0; virtual SWindowDecorationExtents getWindowDecorationExtents() = 0; @@ -33,5 +35,10 @@ class IHyprWindowDecoration { virtual SWindowDecorationExtents getWindowDecorationReservedArea(); + virtual CRegion getWindowDecorationRegion(); + virtual bool allowsInput(); -}; \ No newline at end of file + + private: + CWindow* m_pWindow = nullptr; +};