decoration: Stacked group tabs (#5886)

* Stacked group tabs

* Fix index when creating groupbar title textures

* Changes for stacked dnd

* formatting

* Don't remove internal horizontal padding when calculating stacked bar
width
This commit is contained in:
zakk4223 2024-05-16 06:38:10 -04:00 committed by GitHub
parent de9798fcf9
commit ca0833c9ed
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 60 additions and 28 deletions

View file

@ -359,6 +359,7 @@ CConfigManager::CConfigManager() {
m_pConfig->addConfigValue("group:groupbar:render_titles", Hyprlang::INT{1}); m_pConfig->addConfigValue("group:groupbar:render_titles", Hyprlang::INT{1});
m_pConfig->addConfigValue("group:groupbar:scrolling", 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: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:int", Hyprlang::INT{0});
m_pConfig->addConfigValue("debug:log_damage", Hyprlang::INT{0}); m_pConfig->addConfigValue("debug:log_damage", Hyprlang::INT{0});

View file

@ -1,6 +1,7 @@
#include "CHyprGroupBarDecoration.hpp" #include "CHyprGroupBarDecoration.hpp"
#include "../../Compositor.hpp" #include "../../Compositor.hpp"
#include "../../config/ConfigValue.hpp" #include "../../config/ConfigValue.hpp"
#include "managers/LayoutManager.hpp"
#include <ranges> #include <ranges>
#include <pango/pangocairo.h> #include <pango/pangocairo.h>
@ -12,6 +13,7 @@ static CTexture m_tGradientLockedInactive;
constexpr int BAR_INDICATOR_HEIGHT = 3; constexpr int BAR_INDICATOR_HEIGHT = 3;
constexpr int BAR_PADDING_OUTER_VERT = 2; constexpr int BAR_PADDING_OUTER_VERT = 2;
constexpr int BAR_PADDING_OUTER_HORZ = 2;
constexpr int BAR_TEXT_PAD = 2; constexpr int BAR_TEXT_PAD = 2;
constexpr int BAR_HORIZONTAL_PADDING = 2; constexpr int BAR_HORIZONTAL_PADDING = 2;
@ -32,6 +34,7 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() {
static auto PRENDERTITLES = CConfigValue<Hyprlang::INT>("group:groupbar:render_titles"); static auto PRENDERTITLES = CConfigValue<Hyprlang::INT>("group:groupbar:render_titles");
static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:gradients"); static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:gradients");
static auto PPRIORITY = CConfigValue<Hyprlang::INT>("group:groupbar:priority"); static auto PPRIORITY = CConfigValue<Hyprlang::INT>("group:groupbar:priority");
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
SDecorationPositioningInfo info; SDecorationPositioningInfo info;
info.policy = DECORATION_POSITION_STICKY; info.policy = DECORATION_POSITION_STICKY;
@ -39,16 +42,20 @@ SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() {
info.priority = *PPRIORITY; info.priority = *PPRIORITY;
info.reserved = true; info.reserved = true;
if (*PENABLED && m_pWindow->m_sSpecialRenderData.decorate) 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}}; info.desiredExtents = {{0, BAR_PADDING_OUTER_VERT * 2 + BAR_INDICATOR_HEIGHT + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0) + 2}, {0, 0}};
else } else
info.desiredExtents = {{0, 0}, {0, 0}}; info.desiredExtents = {{0, 0}, {0, 0}};
return info; return info;
} }
void CHyprGroupBarDecoration::onPositioningReply(const SDecorationPositioningReply& reply) { void CHyprGroupBarDecoration::onPositioningReply(const SDecorationPositioningReply& reply) {
m_bAssignedBox = reply.assignedGeometry; m_bAssignedBox = reply.assignedGeometry;
g_pLayoutManager->getCurrentLayout()->recalculateWindow(m_pWindow.lock());
} }
eDecorationType CHyprGroupBarDecoration::getDecorationType() { eDecorationType CHyprGroupBarDecoration::getDecorationType() {
@ -96,23 +103,30 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
static auto PTITLEFONTSIZE = CConfigValue<Hyprlang::INT>("group:groupbar:font_size"); static auto PTITLEFONTSIZE = CConfigValue<Hyprlang::INT>("group:groupbar:font_size");
static auto PHEIGHT = CConfigValue<Hyprlang::INT>("group:groupbar:height"); static auto PHEIGHT = CConfigValue<Hyprlang::INT>("group:groupbar:height");
static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:gradients"); static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:gradients");
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
if (!*PENABLED || !m_pWindow->m_sSpecialRenderData.decorate) if (!*PENABLED || !m_pWindow->m_sSpecialRenderData.decorate)
return; return;
const auto ASSIGNEDBOX = assignedBoxGlobal(); 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; const auto DESIREDHEIGHT = *PSTACKED ? (ONEBARHEIGHT * m_dwGroupMembers.size()) + 2 + BAR_PADDING_OUTER_VERT : BAR_PADDING_OUTER_VERT * 2 + ONEBARHEIGHT;
if (DESIREDHEIGHT != ASSIGNEDBOX.h) if (DESIREDHEIGHT != ASSIGNEDBOX.h) {
g_pDecorationPositioner->repositionDeco(this); g_pDecorationPositioner->repositionDeco(this);
}
int xoff = 0; int xoff = 0;
int yoff = 0;
for (int i = 0; i < barsToDraw; ++i) { for (int i = 0; i < barsToDraw; ++i) {
const auto WINDOWINDEX = *PSTACKED ? m_dwGroupMembers.size() - i - 1 : i;
CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x, 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, 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}; BAR_INDICATOR_HEIGHT};
if (rect.width <= 0 || rect.height <= 0) if (rect.width <= 0 || rect.height <= 0)
@ -133,37 +147,42 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a) {
const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE; const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE;
const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE; 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; color.a *= a;
g_pHyprOpenGL->renderRect(&rect, color); g_pHyprOpenGL->renderRect(&rect, color);
rect = {ASSIGNEDBOX.x + xoff - pMonitor->vecPosition.x + m_pWindow->m_vFloatingOffset.x, 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.y + ASSIGNEDBOX.h - yoff - ONEBARHEIGHT - pMonitor->vecPosition.y + m_pWindow->m_vFloatingOffset.y, m_fBarWidth,
ASSIGNEDBOX.h - BAR_INDICATOR_HEIGHT - BAR_PADDING_OUTER_VERT * 2}; (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0)};
rect.scale(pMonitor->scale); rect.scale(pMonitor->scale);
if (*PGRADIENTS) { if (*PGRADIENTS) {
const auto& GRADIENTTEX = (m_dwGroupMembers[i].lock() == g_pCompositor->m_pLastWindow.lock() ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) : const auto& GRADIENTTEX =
(m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_pLastWindow.lock() ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive)); (GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
if (GRADIENTTEX.m_iTexID != 0) if (GRADIENTTEX.m_iTexID != 0)
g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0); g_pHyprOpenGL->renderTexture(GRADIENTTEX, &rect, 1.0);
} }
if (*PRENDERTITLES) { if (*PRENDERTITLES) {
CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[i]->m_szTitle); CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[WINDOWINDEX]->m_szTitle);
if (!pTitleTex) if (!pTitleTex)
pTitleTex = m_sTitleTexs.titleTexs pTitleTex =
.emplace_back(std::make_unique<CTitleTex>( m_sTitleTexs.titleTexs
m_dwGroupMembers[i].lock(), Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale)) .emplace_back(std::make_unique<CTitleTex>(m_dwGroupMembers[WINDOWINDEX].lock(),
Vector2D{m_fBarWidth * pMonitor->scale, (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale}, pMonitor->scale))
.get(); .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; rect.height = (*PTITLEFONTSIZE + 2 * BAR_TEXT_PAD) * pMonitor->scale;
g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f); g_pHyprOpenGL->renderTexture(pTitleTex->tex, &rect, 1.f);
} }
if (*PSTACKED)
yoff += ONEBARHEIGHT;
else
xoff += BAR_HORIZONTAL_PADDING + m_fBarWidth; xoff += BAR_HORIZONTAL_PADDING + m_fBarWidth;
} }
@ -335,13 +354,18 @@ void refreshGroupBarGradients() {
} }
bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) { bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) {
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
if (m_pWindow.lock() == m_pWindow->m_sGroupData.pNextWindow.lock()) if (m_pWindow.lock() == m_pWindow->m_sGroupData.pNextWindow.lock())
return false; return false;
const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; 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; return false;
PHLWINDOW pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX); PHLWINDOW pWindow = m_pWindow->getGroupWindowByIndex(WINDOWINDEX);
@ -364,11 +388,13 @@ bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) {
} }
bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWINDOW pDraggedWindow) { bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWINDOW pDraggedWindow) {
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock())) if (!pDraggedWindow->canBeGroupedInto(m_pWindow.lock()))
return false; return false;
const float BARRELATIVEX = pos.x - assignedBoxGlobal().x - m_fBarWidth / 2; const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_fBarHeight + BAR_PADDING_OUTER_VERT) / 2 : pos.x - assignedBoxGlobal().x - m_fBarWidth / 2;
const int WINDOWINDEX = BARRELATIVEX < 0 ? -1 : (BARRELATIVEX) / (m_fBarWidth + BAR_HORIZONTAL_PADDING); 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 pWindowInsertAfter = m_pWindow->getGroupWindowByIndex(WINDOWINDEX);
PHLWINDOW pWindowInsertEnd = pWindowInsertAfter->m_sGroupData.pNextWindow.lock(); 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) { bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPointer::SButtonEvent& e) {
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
if (m_pWindow->m_bIsFullscreen && m_pWindow->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL) if (m_pWindow->m_bIsFullscreen && m_pWindow->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL)
return true; return true;
const float BARRELATIVEX = pos.x - assignedBoxGlobal().x; 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<Hyprlang::INT>("input:follow_mouse"); static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
// close window on middle click // close window on middle click
@ -446,7 +474,9 @@ bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPo
return true; return true;
// click on padding // 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())) if (!g_pCompositor->isWindowActive(m_pWindow.lock()))
g_pCompositor->focusWindow(m_pWindow.lock()); g_pCompositor->focusWindow(m_pWindow.lock());
return true; return true;

View file

@ -54,6 +54,7 @@ class CHyprGroupBarDecoration : public IHyprWindowDecoration {
std::deque<PHLWINDOWREF> m_dwGroupMembers; std::deque<PHLWINDOWREF> m_dwGroupMembers;
float m_fBarWidth; float m_fBarWidth;
float m_fBarHeight;
CTitleTex* textureFromTitle(const std::string&); CTitleTex* textureFromTitle(const std::string&);
void invalidateTextures(); void invalidateTextures();