diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 9d8a538c..b0c44408 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -359,6 +359,7 @@ CConfigManager::CConfigManager() { m_pConfig->addConfigValue("group:groupbar:render_titles", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:scrolling", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:text_color", Hyprlang::INT{0xffffffff}); + m_pConfig->addConfigValue("group:groupbar:stacked", Hyprlang::INT{0}); m_pConfig->addConfigValue("debug:int", Hyprlang::INT{0}); m_pConfig->addConfigValue("debug:log_damage", Hyprlang::INT{0}); diff --git a/src/render/decorations/CHyprGroupBarDecoration.cpp b/src/render/decorations/CHyprGroupBarDecoration.cpp index 451701b4..318999ed 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.cpp +++ b/src/render/decorations/CHyprGroupBarDecoration.cpp @@ -1,6 +1,7 @@ #include "CHyprGroupBarDecoration.hpp" #include "../../Compositor.hpp" #include "../../config/ConfigValue.hpp" +#include "managers/LayoutManager.hpp" #include #include @@ -12,6 +13,7 @@ static CTexture m_tGradientLockedInactive; constexpr int BAR_INDICATOR_HEIGHT = 3; constexpr int BAR_PADDING_OUTER_VERT = 2; +constexpr int BAR_PADDING_OUTER_HORZ = 2; constexpr int BAR_TEXT_PAD = 2; constexpr int BAR_HORIZONTAL_PADDING = 2; @@ -32,6 +34,7 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { static auto PRENDERTITLES = CConfigValue("group:groupbar:render_titles"); static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); static auto PPRIORITY = CConfigValue("group:groupbar:priority"); + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); SDecorationPositioningInfo info; info.policy = DECORATION_POSITION_STICKY; @@ -39,16 +42,20 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() { info.priority = *PPRIORITY; info.reserved = true; - if (*PENABLED && m_pWindow->m_sSpecialRenderData.decorate) - info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2}, {0, 0}}; - else + if (*PENABLED && m_pWindow->m_sSpecialRenderData.decorate) { + if (*PSTACKED) { + const auto ONEBARHEIGHT = BAR_PADDING_OUTER_VERT + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); + info.desiredExtents = {{0, (ONEBARHEIGHT * m_dwGroupMembers.size()) + 2 + BAR_PADDING_OUTER_VERT}, {0, 0}}; + } else + info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2}, {0, 0}}; + } else info.desiredExtents = {{0, 0}, {0, 0}}; - return info; } void CHyprGroupBarDecoration::onPositioningReply(const SDecorationPositioningReply& reply) { m_bAssignedBox = reply.assignedGeometry; + g_pLayoutManager->getCurrentLayout()->recalculateWindow(m_pWindow.lock()); } eDecorationType CHyprGroupBarDecoration::getDecorationType() { @@ -96,24 +103,31 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) { static auto PTITLEFONTSIZE = CConfigValue("group:groupbar:font_size"); static auto PHEIGHT = CConfigValue("group:groupbar:height"); static auto PGRADIENTS = CConfigValue("group:groupbar:gradients"); + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); if (!*PENABLED || !m_pWindow->m_sSpecialRenderData.decorate) return; const auto ASSIGNEDBOX = assignedBoxGlobal(); - m_fBarWidth = (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; + const auto ONEBARHEIGHT = BAR_PADDING_OUTER_VERT + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0); + m_fBarWidth = *PSTACKED ? ASSIGNEDBOX.w : (ASSIGNEDBOX.w - BAR_HORIZONTAL_PADDING * (barsToDraw - 1)) / barsToDraw; + m_fBarHeight = *PSTACKED ? ((ASSIGNEDBOX.h - 2 - BAR_PADDING_OUTER_VERT) - BAR_PADDING_OUTER_VERT * (barsToDraw)) / barsToDraw : ASSIGNEDBOX.h - BAR_PADDING_OUTER_VERT; - const auto DESIREDHEIGHT = BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2; - if (DESIREDHEIGHT != ASSIGNEDBOX.h) + const auto DESIREDHEIGHT = *PSTACKED ? (ONEBARHEIGHT * m_dwGroupMembers.size()) + 2 + BAR_PADDING_OUTER_VERT : BAR_PADDING_OUTER_VERT * 2 + ONEBARHEIGHT; + if (DESIREDHEIGHT != ASSIGNEDBOX.h) { g_pDecorationPositioner->repositionDeco(this); + } int xoff = 0; + int yoff = 0; for (int i = 0; i < barsToDraw; ++i) { - CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x, - ASSIGNEDBOX.y + ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth, - BAR_INDICATOR_HEIGHT}; + const auto WINDOWINDEX = *PSTACKED ? m_dwGroupMembers.size() - i - 1 : i; + + CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x, + ASSIGNEDBOX.y + ASSIGNEDBOX.h - yoff - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth, + BAR_INDICATOR_HEIGHT}; if (rect.width <= 0 || rect.height <= 0) break; @@ -133,38 +147,43 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) { const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; - CColor color = m_dwGroupMembers[i].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0]; + CColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? PCOLACTIVE->m_vColors[0] : PCOLINACTIVE->m_vColors[0]; color.a *= a; g_pHyprOpenGL->renderRect(&rect, color); rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x, - ASSIGNEDBOX.y - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y + BAR_PADDING_OUTER_VERT, m_fBarWidth, - ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT * 2}; + ASSIGNEDBOX.y + ASSIGNEDBOX.h - yoff - ONEBARHEIGHT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth, + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0)}; rect.scale(pMonitor->scale); if (*PGRADIENTS) { - const auto& GRADIENTTEX = (m_dwGroupMembers[i].lock() == g_pCompositor->m_pLastWindow.lock() ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : - (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); + const auto& GRADIENTTEX = + (m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : + (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); if (GRADIENTTEX.m_iTexID != 0) g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0); } if (*PRENDERTITLES) { - CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle); + CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[WINDOWINDEX]->m_szTitle); if (!pTitleTex) - pTitleTex = m_sTitleTexs.titleTexs - .emplace_back(std::make_unique( - m_dwGroupMembers[i].lock(), Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale)) - .get(); + pTitleTex = + m_sTitleTexs.titleTexs + .emplace_back(std::make_unique(m_dwGroupMembers[WINDOWINDEX].lock(), + Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale)) + .get(); - rect.y += (ASSIGNEDBOX.h / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; + rect.y += (*PHEIGHT / 2.0 - (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) / 2.0) * pMonitor->scale; rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale; g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f); } - xoff += BAR_HORIZONTAL_PADDING + m_fBarWidth; + if (*PSTACKED) + yoff += ONEBARHEIGHT; + else + xoff += BAR_HORIZONTAL_PADDING + m_fBarWidth; } if (*PRENDERTITLES) @@ -335,13 +354,18 @@ void refreshGroupBarGradients() { } bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); if (m_pWindow.lock() == m_pWindow->m_sGroupData.pNextWindow.lock()) return false; const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; - const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); + const float BARRELATIVEY = pos.y - assignedBoxGlobal().y; + const int WINDOWINDEX = *PSTACKED ? (BARRELATIVEY / (m_fBarHeight + BAR_PADDING_OUTER_VERT)) : (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); - if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) + if (!*PSTACKED && (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth)) + return false; + + if (*PSTACKED && (BARRELATIVEY - (m_fBarHeight + BAR_PADDING_OUTER_VERT) * WINDOWINDEX < BAR_PADDING_OUTER_VERT)) return false; PHLWINDOW pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); @@ -364,11 +388,13 @@ 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())) return false; - const float BARRELATIVEX = pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; - const int WINDOWINDEX = BARRELATIVEX < 0 ? -1 : (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); + const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; + const float BARSIZE = *PSTACKED ? m_fBarHeight + BAR_PADDING_OUTER_VERT : m_fBarWidth + BAR_HORIZONTAL_PADDING; + const int WINDOWINDEX = BARRELATIVE < 0 ? -1 : BARRELATIVE / BARSIZE; PHLWINDOW pWindowInsertAfter = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); PHLWINDOW pWindowInsertEnd = pWindowInsertAfter->m_sGroupData.pNextWindow.lock(); @@ -423,11 +449,13 @@ bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWIND } bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPointer::SButtonEvent& e) { + static auto PSTACKED = CConfigValue("group:groupbar:stacked"); if (m_pWindow->m_bIsFullscreen && m_pWindow->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL) return true; const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; - const int WINDOWINDEX = (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); + const float BARRELATIVEY = pos.y - assignedBoxGlobal().y; + const int WINDOWINDEX = *PSTACKED ? (BARRELATIVEY / (m_fBarHeight + BAR_PADDING_OUTER_VERT)) : (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); static auto PFOLLOWMOUSE = CConfigValue("input:follow_mouse"); // close window on middle click @@ -446,7 +474,9 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPo return true; // click on padding - if (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth) { + const auto TABPAD = !*PSTACKED && (BARRELATIVEX - (m_fBarWidth + BAR_HORIZONTAL_PADDING) * WINDOWINDEX > m_fBarWidth); + const auto STACKPAD = *PSTACKED && (BARRELATIVEY - (m_fBarHeight + BAR_PADDING_OUTER_VERT) * WINDOWINDEX < BAR_PADDING_OUTER_VERT); + if (TABPAD || STACKPAD) { if (!g_pCompositor->isWindowActive(m_pWindow.lock())) g_pCompositor->focusWindow(m_pWindow.lock()); return true; diff --git a/src/render/decorations/CHyprGroupBarDecoration.hpp b/src/render/decorations/CHyprGroupBarDecoration.hpp index 3fe653cc..e3f553c5 100644 --- a/src/render/decorations/CHyprGroupBarDecoration.hpp +++ b/src/render/decorations/CHyprGroupBarDecoration.hpp @@ -54,6 +54,7 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration { std::deque m_dwGroupMembers; float m_fBarWidth; + float m_fBarHeight; CTitleTex* textureFromTitle(const std::string&); void invalidateTextures();