2022-05-28 20:46:20 +02:00
|
|
|
#include "CHyprGroupBarDecoration.hpp"
|
|
|
|
|
#include "../../Compositor.hpp"
|
2024-03-03 18:39:20 +00:00
|
|
|
#include "../../config/ConfigValue.hpp"
|
2024-05-16 06:38:10 -04:00
|
|
|
#include "managers/LayoutManager.hpp"
|
2023-05-22 21:40:32 +02:00
|
|
|
#include <ranges>
|
|
|
|
|
#include <pango/pangocairo.h>
|
2024-12-22 17:12:09 +01:00
|
|
|
#include "../pass/TexPassElement.hpp"
|
|
|
|
|
#include "../pass/RectPassElement.hpp"
|
2025-01-17 15:21:35 +00:00
|
|
|
#include "../Renderer.hpp"
|
|
|
|
|
#include "../../managers/input/InputManager.hpp"
|
2022-05-28 20:46:20 +02:00
|
|
|
|
2023-05-22 22:06:40 +02:00
|
|
|
// shared things to conserve VRAM
|
2024-06-08 10:07:59 +02:00
|
|
|
static SP<CTexture> m_tGradientActive = makeShared<CTexture>();
|
|
|
|
|
static SP<CTexture> m_tGradientInactive = makeShared<CTexture>();
|
|
|
|
|
static SP<CTexture> m_tGradientLockedActive = makeShared<CTexture>();
|
|
|
|
|
static SP<CTexture> m_tGradientLockedInactive = makeShared<CTexture>();
|
2023-11-26 17:59:49 +00:00
|
|
|
|
2025-03-12 10:09:09 -04:00
|
|
|
constexpr int BAR_TEXT_PAD = 2;
|
2023-05-22 22:06:40 +02:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
CHyprGroupBarDecoration::CHyprGroupBarDecoration(PHLWINDOW pWindow) : IHyprWindowDecoration(pWindow), m_window(pWindow) {
|
2024-03-03 18:39:20 +00:00
|
|
|
static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:enabled");
|
|
|
|
|
static auto PENABLED = CConfigValue<Hyprlang::INT>("group:groupbar:gradients");
|
2023-12-30 14:18:53 +00:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (m_tGradientActive->m_texID == 0 && *PENABLED && *PGRADIENTS)
|
2023-11-26 17:59:49 +00:00
|
|
|
refreshGroupBarGradients();
|
2022-05-28 20:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
2023-11-11 14:37:17 +00:00
|
|
|
SDecorationPositioningInfo CHyprGroupBarDecoration::getPositioningInfo() {
|
2025-01-31 13:32:36 +00:00
|
|
|
static auto PHEIGHT = CConfigValue<Hyprlang::INT>("group:groupbar:height");
|
2025-04-24 14:48:08 -04:00
|
|
|
static auto PINDICATORGAP = CConfigValue<Hyprlang::INT>("group:groupbar:indicator_gap");
|
2025-01-31 13:32:36 +00:00
|
|
|
static auto PINDICATORHEIGHT = CConfigValue<Hyprlang::INT>("group:groupbar:indicator_height");
|
|
|
|
|
static auto PENABLED = CConfigValue<Hyprlang::INT>("group:groupbar:enabled");
|
|
|
|
|
static auto PRENDERTITLES = CConfigValue<Hyprlang::INT>("group:groupbar:render_titles");
|
|
|
|
|
static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:gradients");
|
|
|
|
|
static auto PPRIORITY = CConfigValue<Hyprlang::INT>("group:groupbar:priority");
|
|
|
|
|
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
|
2025-03-12 10:09:09 -04:00
|
|
|
static auto POUTERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_out");
|
2025-04-02 23:26:46 +03:00
|
|
|
static auto PKEEPUPPERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:keep_upper_gap");
|
2023-11-11 14:37:17 +00:00
|
|
|
|
|
|
|
|
SDecorationPositioningInfo info;
|
2023-12-30 14:18:53 +00:00
|
|
|
info.policy = DECORATION_POSITION_STICKY;
|
|
|
|
|
info.edges = DECORATION_EDGE_TOP;
|
2024-03-03 18:39:20 +00:00
|
|
|
info.priority = *PPRIORITY;
|
2023-12-30 14:18:53 +00:00
|
|
|
info.reserved = true;
|
|
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (*PENABLED && m_window->m_windowData.decorate.valueOrDefault()) {
|
2024-05-16 06:38:10 -04:00
|
|
|
if (*PSTACKED) {
|
2025-04-24 14:48:08 -04:00
|
|
|
const auto ONEBARHEIGHT = *POUTERGAP + *PINDICATORHEIGHT + *PINDICATORGAP + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0);
|
2025-04-02 23:26:46 +03:00
|
|
|
info.desiredExtents = {{0, (ONEBARHEIGHT * m_dwGroupMembers.size()) + (*PKEEPUPPERGAP * *POUTERGAP)}, {0, 0}};
|
2024-05-16 06:38:10 -04:00
|
|
|
} else
|
2025-04-24 14:48:08 -04:00
|
|
|
info.desiredExtents = {{0, *POUTERGAP * (1 + *PKEEPUPPERGAP) + *PINDICATORHEIGHT + *PINDICATORGAP + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0)}, {0, 0}};
|
2024-05-16 06:38:10 -04:00
|
|
|
} else
|
2023-12-30 14:18:53 +00:00
|
|
|
info.desiredExtents = {{0, 0}, {0, 0}};
|
2023-11-11 14:37:17 +00:00
|
|
|
return info;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CHyprGroupBarDecoration::onPositioningReply(const SDecorationPositioningReply& reply) {
|
2025-05-05 23:44:49 +02:00
|
|
|
m_assignedBox = reply.assignedGeometry;
|
2022-05-28 20:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
eDecorationType CHyprGroupBarDecoration::getDecorationType() {
|
|
|
|
|
return DECORATION_GROUPBAR;
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-22 20:52:41 +02:00
|
|
|
//
|
|
|
|
|
|
2024-04-27 12:43:12 +01:00
|
|
|
void CHyprGroupBarDecoration::updateWindow(PHLWINDOW pWindow) {
|
2025-05-05 23:44:49 +02:00
|
|
|
if (m_window->m_groupData.pNextWindow.expired()) {
|
|
|
|
|
m_window->removeWindowDeco(this);
|
2022-07-05 17:31:47 +02:00
|
|
|
return;
|
2022-05-28 20:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
2023-02-19 21:07:32 +00:00
|
|
|
m_dwGroupMembers.clear();
|
2024-04-27 12:43:12 +01:00
|
|
|
PHLWINDOW head = pWindow->getGroupHead();
|
2024-12-22 17:12:09 +01:00
|
|
|
m_dwGroupMembers.emplace_back(head);
|
2022-05-28 20:46:20 +02:00
|
|
|
|
2025-04-28 22:25:22 +02:00
|
|
|
PHLWINDOW curr = head->m_groupData.pNextWindow.lock();
|
2023-02-19 21:07:32 +00:00
|
|
|
while (curr != head) {
|
2024-12-22 17:12:09 +01:00
|
|
|
m_dwGroupMembers.emplace_back(curr);
|
2025-04-28 22:25:22 +02:00
|
|
|
curr = curr->m_groupData.pNextWindow.lock();
|
2023-02-19 21:07:32 +00:00
|
|
|
}
|
2022-05-28 20:46:20 +02:00
|
|
|
|
|
|
|
|
damageEntire();
|
|
|
|
|
|
|
|
|
|
if (m_dwGroupMembers.size() == 0) {
|
2025-05-05 23:44:49 +02:00
|
|
|
m_window->removeWindowDeco(this);
|
2022-07-05 17:31:47 +02:00
|
|
|
return;
|
2022-05-28 20:46:20 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CHyprGroupBarDecoration::damageEntire() {
|
2023-11-11 14:37:17 +00:00
|
|
|
auto box = assignedBoxGlobal();
|
2025-05-05 23:44:49 +02:00
|
|
|
box.translate(m_window->m_floatingOffset);
|
2025-01-26 15:05:34 +00:00
|
|
|
g_pHyprRenderer->damageBox(box);
|
2022-05-28 20:46:20 +02:00
|
|
|
}
|
|
|
|
|
|
2024-10-31 00:20:32 +01:00
|
|
|
void CHyprGroupBarDecoration::draw(PHLMONITOR pMonitor, float const& a) {
|
2022-05-28 20:46:20 +02:00
|
|
|
// get how many bars we will draw
|
2024-03-03 18:39:20 +00:00
|
|
|
int barsToDraw = m_dwGroupMembers.size();
|
2023-05-22 21:40:32 +02:00
|
|
|
|
2025-02-09 17:58:09 +00:00
|
|
|
static auto PENABLED = CConfigValue<Hyprlang::INT>("group:groupbar:enabled");
|
|
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (!*PENABLED || !m_window->m_windowData.decorate.valueOrDefault())
|
2025-02-09 17:58:09 +00:00
|
|
|
return;
|
|
|
|
|
|
2025-01-31 13:32:36 +00:00
|
|
|
static auto PRENDERTITLES = CConfigValue<Hyprlang::INT>("group:groupbar:render_titles");
|
|
|
|
|
static auto PTITLEFONTSIZE = CConfigValue<Hyprlang::INT>("group:groupbar:font_size");
|
|
|
|
|
static auto PHEIGHT = CConfigValue<Hyprlang::INT>("group:groupbar:height");
|
2025-04-24 14:48:08 -04:00
|
|
|
static auto PINDICATORGAP = CConfigValue<Hyprlang::INT>("group:groupbar:indicator_gap");
|
2025-01-31 13:32:36 +00:00
|
|
|
static auto PINDICATORHEIGHT = CConfigValue<Hyprlang::INT>("group:groupbar:indicator_height");
|
|
|
|
|
static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:gradients");
|
|
|
|
|
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
|
|
|
|
|
static auto PROUNDING = CConfigValue<Hyprlang::INT>("group:groupbar:rounding");
|
|
|
|
|
static auto PGRADIENTROUNDING = CConfigValue<Hyprlang::INT>("group:groupbar:gradient_rounding");
|
|
|
|
|
static auto PGRADIENTROUNDINGONLYEDGES = CConfigValue<Hyprlang::INT>("group:groupbar:gradient_round_only_edges");
|
|
|
|
|
static auto PROUNDONLYEDGES = CConfigValue<Hyprlang::INT>("group:groupbar:round_only_edges");
|
2025-02-09 17:58:09 +00:00
|
|
|
static auto PGROUPCOLACTIVE = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:col.active");
|
|
|
|
|
static auto PGROUPCOLINACTIVE = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:col.inactive");
|
|
|
|
|
static auto PGROUPCOLACTIVELOCKED = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:col.locked_active");
|
|
|
|
|
static auto PGROUPCOLINACTIVELOCKED = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:col.locked_inactive");
|
2025-03-12 10:09:09 -04:00
|
|
|
static auto POUTERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_out");
|
|
|
|
|
static auto PINNERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_in");
|
2025-04-02 23:26:46 +03:00
|
|
|
static auto PKEEPUPPERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:keep_upper_gap");
|
|
|
|
|
static auto PTEXTOFFSET = CConfigValue<Hyprlang::INT>("group:groupbar:text_offset");
|
2025-02-09 17:58:09 +00:00
|
|
|
auto* const GROUPCOLACTIVE = (CGradientValueData*)(PGROUPCOLACTIVE.ptr())->getData();
|
|
|
|
|
auto* const GROUPCOLINACTIVE = (CGradientValueData*)(PGROUPCOLINACTIVE.ptr())->getData();
|
|
|
|
|
auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(PGROUPCOLACTIVELOCKED.ptr())->getData();
|
|
|
|
|
auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(PGROUPCOLINACTIVELOCKED.ptr())->getData();
|
|
|
|
|
|
|
|
|
|
const auto ASSIGNEDBOX = assignedBoxGlobal();
|
|
|
|
|
|
2025-04-24 14:48:08 -04:00
|
|
|
const auto ONEBARHEIGHT = *POUTERGAP + *PINDICATORHEIGHT + *PINDICATORGAP + (*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0);
|
2025-05-05 23:44:49 +02:00
|
|
|
m_barWidth = *PSTACKED ? ASSIGNEDBOX.w : (ASSIGNEDBOX.w - *PINNERGAP * (barsToDraw - 1)) / barsToDraw;
|
|
|
|
|
m_barHeight = *PSTACKED ? ((ASSIGNEDBOX.h - *POUTERGAP * *PKEEPUPPERGAP) - *POUTERGAP * (barsToDraw)) / barsToDraw : ASSIGNEDBOX.h - *POUTERGAP * *PKEEPUPPERGAP;
|
2023-11-11 14:37:17 +00:00
|
|
|
|
2025-04-02 23:26:46 +03:00
|
|
|
const auto DESIREDHEIGHT = *PSTACKED ? (ONEBARHEIGHT * m_dwGroupMembers.size()) + *POUTERGAP * *PKEEPUPPERGAP : *POUTERGAP * (1 + *PKEEPUPPERGAP) + ONEBARHEIGHT;
|
2024-12-22 17:12:09 +01:00
|
|
|
if (DESIREDHEIGHT != ASSIGNEDBOX.h)
|
2023-11-11 14:37:17 +00:00
|
|
|
g_pDecorationPositioner->repositionDeco(this);
|
2022-05-28 20:46:20 +02:00
|
|
|
|
2024-06-12 13:56:35 +00:00
|
|
|
float xoff = 0;
|
|
|
|
|
float yoff = 0;
|
2022-05-28 20:46:20 +02:00
|
|
|
|
|
|
|
|
for (int i = 0; i < barsToDraw; ++i) {
|
2024-05-16 06:38:10 -04:00
|
|
|
const auto WINDOWINDEX = *PSTACKED ? m_dwGroupMembers.size() - i - 1 : i;
|
|
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
CBox rect = {ASSIGNEDBOX.x + xoff - pMonitor->m_position.x + m_window->m_floatingOffset.x,
|
|
|
|
|
ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - *PINDICATORHEIGHT - *POUTERGAP - pMonitor->m_position.y + m_window->m_floatingOffset.y, m_barWidth,
|
2025-03-12 10:09:09 -04:00
|
|
|
*PINDICATORHEIGHT};
|
2022-05-28 20:46:20 +02:00
|
|
|
|
2025-04-30 23:45:20 +02:00
|
|
|
rect.scale(pMonitor->m_scale).round();
|
2022-09-18 12:13:16 +01:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
const bool GROUPLOCKED = m_window->getGroupHead()->m_groupData.locked || g_pKeybindManager->m_groupsLocked;
|
2024-03-03 18:39:20 +00:00
|
|
|
const auto* const PCOLACTIVE = GROUPLOCKED ? GROUPCOLACTIVELOCKED : GROUPCOLACTIVE;
|
|
|
|
|
const auto* const PCOLINACTIVE = GROUPLOCKED ? GROUPCOLINACTIVELOCKED : GROUPCOLINACTIVE;
|
2023-06-13 10:04:54 +00:00
|
|
|
|
2025-04-22 15:23:29 +02:00
|
|
|
CHyprColor color = m_dwGroupMembers[WINDOWINDEX].lock() == g_pCompositor->m_lastWindow.lock() ? PCOLACTIVE->m_colors[0] : PCOLINACTIVE->m_colors[0];
|
2022-06-25 20:31:54 +02:00
|
|
|
color.a *= a;
|
2025-02-09 17:58:09 +00:00
|
|
|
|
|
|
|
|
if (!rect.empty()) {
|
|
|
|
|
CRectPassElement::SRectData rectdata;
|
|
|
|
|
rectdata.color = color;
|
|
|
|
|
rectdata.box = rect;
|
|
|
|
|
if (*PROUNDING) {
|
|
|
|
|
if (*PROUNDONLYEDGES) {
|
|
|
|
|
static constexpr double PADDING = 20;
|
|
|
|
|
|
|
|
|
|
if (i == 0 && barsToDraw == 1)
|
|
|
|
|
rectdata.round = *PROUNDING;
|
|
|
|
|
else if (i == 0) {
|
|
|
|
|
double first = rect.w - (*PROUNDING * 2);
|
|
|
|
|
rectdata.round = *PROUNDING;
|
|
|
|
|
rectdata.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}};
|
2025-05-05 23:44:49 +02:00
|
|
|
g_pHyprRenderer->m_renderPass.add(makeShared<CRectPassElement>(rectdata));
|
2025-02-09 17:58:09 +00:00
|
|
|
rectdata.round = 0;
|
|
|
|
|
rectdata.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}};
|
|
|
|
|
} else if (i == barsToDraw - 1) {
|
|
|
|
|
double first = *PROUNDING * 2;
|
|
|
|
|
rectdata.round = 0;
|
|
|
|
|
rectdata.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}};
|
2025-05-05 23:44:49 +02:00
|
|
|
g_pHyprRenderer->m_renderPass.add(makeShared<CRectPassElement>(rectdata));
|
2025-02-09 17:58:09 +00:00
|
|
|
rectdata.round = *PROUNDING;
|
|
|
|
|
rectdata.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}};
|
|
|
|
|
}
|
|
|
|
|
} else
|
2025-01-31 13:32:36 +00:00
|
|
|
rectdata.round = *PROUNDING;
|
2025-02-09 17:58:09 +00:00
|
|
|
}
|
2025-05-05 23:44:49 +02:00
|
|
|
g_pHyprRenderer->m_renderPass.add(makeShared<CRectPassElement>(rectdata));
|
2025-01-31 13:32:36 +00:00
|
|
|
}
|
2022-05-28 20:46:20 +02:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
rect = {ASSIGNEDBOX.x + xoff - pMonitor->m_position.x + m_window->m_floatingOffset.x,
|
|
|
|
|
ASSIGNEDBOX.y + ASSIGNEDBOX.h - floor(yoff) - ONEBARHEIGHT - pMonitor->m_position.y + m_window->m_floatingOffset.y, m_barWidth,
|
2024-05-16 06:38:10 -04:00
|
|
|
(*PGRADIENTS || *PRENDERTITLES ? *PHEIGHT : 0)};
|
2025-04-30 23:45:20 +02:00
|
|
|
rect.scale(pMonitor->m_scale);
|
2024-01-15 15:17:42 +00:00
|
|
|
|
2025-02-09 17:58:09 +00:00
|
|
|
if (!rect.empty()) {
|
|
|
|
|
if (*PGRADIENTS) {
|
2025-04-22 15:23:29 +02:00
|
|
|
const auto GRADIENTTEX = (m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_lastWindow ? (GROUPLOCKED ? m_tGradientLockedActive : m_tGradientActive) :
|
|
|
|
|
(GROUPLOCKED ? m_tGradientLockedInactive : m_tGradientInactive));
|
2025-05-05 23:44:49 +02:00
|
|
|
if (GRADIENTTEX->m_texID) {
|
2025-02-09 17:58:09 +00:00
|
|
|
CTexPassElement::SRenderData data;
|
|
|
|
|
data.tex = GRADIENTTEX;
|
|
|
|
|
data.box = rect;
|
|
|
|
|
if (*PGRADIENTROUNDING) {
|
|
|
|
|
if (*PGRADIENTROUNDINGONLYEDGES) {
|
|
|
|
|
static constexpr double PADDING = 20;
|
|
|
|
|
|
|
|
|
|
if (i == 0 && barsToDraw == 1)
|
|
|
|
|
data.round = *PGRADIENTROUNDING;
|
|
|
|
|
else if (i == 0) {
|
|
|
|
|
double first = rect.w - (*PGRADIENTROUNDING * 2);
|
|
|
|
|
data.round = *PGRADIENTROUNDING;
|
|
|
|
|
data.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}};
|
2025-05-05 23:44:49 +02:00
|
|
|
g_pHyprRenderer->m_renderPass.add(makeShared<CTexPassElement>(data));
|
2025-02-09 17:58:09 +00:00
|
|
|
data.round = 0;
|
|
|
|
|
data.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}};
|
|
|
|
|
} else if (i == barsToDraw - 1) {
|
|
|
|
|
double first = *PGRADIENTROUNDING * 2;
|
|
|
|
|
data.round = 0;
|
|
|
|
|
data.clipBox = CBox{rect.pos() - Vector2D{PADDING, 0.F}, Vector2D{first + PADDING, rect.h}};
|
2025-05-05 23:44:49 +02:00
|
|
|
g_pHyprRenderer->m_renderPass.add(makeShared<CTexPassElement>(data));
|
2025-02-09 17:58:09 +00:00
|
|
|
data.round = *PGRADIENTROUNDING;
|
|
|
|
|
data.clipBox = CBox{rect.pos() + Vector2D{first, 0.F}, Vector2D{rect.w - first + PADDING, rect.h}};
|
|
|
|
|
}
|
|
|
|
|
} else
|
2025-01-31 13:32:36 +00:00
|
|
|
data.round = *PGRADIENTROUNDING;
|
2025-02-09 17:58:09 +00:00
|
|
|
}
|
2025-05-05 23:44:49 +02:00
|
|
|
g_pHyprRenderer->m_renderPass.add(makeShared<CTexPassElement>(data));
|
2025-01-31 13:32:36 +00:00
|
|
|
}
|
2024-12-22 17:12:09 +01:00
|
|
|
}
|
2023-11-11 14:37:17 +00:00
|
|
|
|
2025-02-09 17:58:09 +00:00
|
|
|
if (*PRENDERTITLES) {
|
2025-04-28 22:25:22 +02:00
|
|
|
CTitleTex* pTitleTex = textureFromTitle(m_dwGroupMembers[WINDOWINDEX]->m_title);
|
2025-02-09 17:58:09 +00:00
|
|
|
|
|
|
|
|
if (!pTitleTex)
|
2025-05-05 23:44:49 +02:00
|
|
|
pTitleTex = m_titleTexs.titleTexs
|
2025-04-30 23:45:20 +02:00
|
|
|
.emplace_back(makeUnique<CTitleTex>(m_dwGroupMembers[WINDOWINDEX].lock(),
|
2025-05-05 23:44:49 +02:00
|
|
|
Vector2D{m_barWidth * pMonitor->m_scale, (*PTITLEFONTSIZE + 2L * BAR_TEXT_PAD) * pMonitor->m_scale},
|
2025-04-30 23:45:20 +02:00
|
|
|
pMonitor->m_scale))
|
|
|
|
|
.get();
|
2025-04-24 14:48:08 -04:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
const auto titleTex = m_dwGroupMembers[WINDOWINDEX] == g_pCompositor->m_lastWindow ? pTitleTex->m_texActive : pTitleTex->m_texInactive;
|
|
|
|
|
rect.y += std::ceil(((rect.height - titleTex->m_size.y) / 2.0) - (*PTEXTOFFSET * pMonitor->m_scale));
|
|
|
|
|
rect.height = titleTex->m_size.y;
|
|
|
|
|
rect.width = titleTex->m_size.x;
|
|
|
|
|
rect.x += std::round(((m_barWidth * pMonitor->m_scale) / 2.0) - (titleTex->m_size.x / 2.0));
|
2025-02-09 17:58:09 +00:00
|
|
|
rect.round();
|
|
|
|
|
|
|
|
|
|
CTexPassElement::SRenderData data;
|
2025-04-24 14:48:08 -04:00
|
|
|
data.tex = titleTex;
|
2025-02-09 17:58:09 +00:00
|
|
|
data.box = rect;
|
2025-03-11 17:30:12 +00:00
|
|
|
data.a = a;
|
2025-05-05 23:44:49 +02:00
|
|
|
g_pHyprRenderer->m_renderPass.add(makeShared<CTexPassElement>(data));
|
2025-02-09 17:58:09 +00:00
|
|
|
}
|
2023-05-22 21:40:32 +02:00
|
|
|
}
|
|
|
|
|
|
2024-05-16 06:38:10 -04:00
|
|
|
if (*PSTACKED)
|
|
|
|
|
yoff += ONEBARHEIGHT;
|
|
|
|
|
else
|
2025-05-05 23:44:49 +02:00
|
|
|
xoff += *PINNERGAP + m_barWidth;
|
2022-05-28 20:46:20 +02:00
|
|
|
}
|
2023-05-22 21:40:32 +02:00
|
|
|
|
2024-03-03 18:39:20 +00:00
|
|
|
if (*PRENDERTITLES)
|
2023-07-11 20:57:33 +02:00
|
|
|
invalidateTextures();
|
2023-05-22 20:52:41 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 21:40:32 +02:00
|
|
|
CTitleTex* CHyprGroupBarDecoration::textureFromTitle(const std::string& title) {
|
2025-05-05 23:44:49 +02:00
|
|
|
for (auto const& tex : m_titleTexs.titleTexs) {
|
|
|
|
|
if (tex->m_content == title)
|
2023-05-22 21:40:32 +02:00
|
|
|
return tex.get();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void CHyprGroupBarDecoration::invalidateTextures() {
|
2025-05-05 23:44:49 +02:00
|
|
|
m_titleTexs.titleTexs.clear();
|
2023-05-22 21:40:32 +02:00
|
|
|
}
|
|
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
CTitleTex::CTitleTex(PHLWINDOW pWindow, const Vector2D& bufferSize, const float monitorScale) : m_content(pWindow->m_title), m_windowOwner(pWindow) {
|
2024-12-03 18:58:24 +00:00
|
|
|
static auto FALLBACKFONT = CConfigValue<std::string>("misc:font_family");
|
|
|
|
|
static auto PTITLEFONTFAMILY = CConfigValue<std::string>("group:groupbar:font_family");
|
|
|
|
|
static auto PTITLEFONTSIZE = CConfigValue<Hyprlang::INT>("group:groupbar:font_size");
|
|
|
|
|
static auto PTEXTCOLOR = CConfigValue<Hyprlang::INT>("group:groupbar:text_color");
|
|
|
|
|
|
2025-04-24 14:48:08 -04:00
|
|
|
static auto PTITLEFONTWEIGHTACTIVE = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:font_weight_active");
|
|
|
|
|
static auto PTITLEFONTWEIGHTINACTIVE = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:font_weight_inactive");
|
|
|
|
|
|
|
|
|
|
const auto FONTWEIGHTACTIVE = (CFontWeightConfigValueData*)(PTITLEFONTWEIGHTACTIVE.ptr())->getData();
|
|
|
|
|
const auto FONTWEIGHTINACTIVE = (CFontWeightConfigValueData*)(PTITLEFONTWEIGHTINACTIVE.ptr())->getData();
|
|
|
|
|
|
2024-12-03 18:58:24 +00:00
|
|
|
const CHyprColor COLOR = CHyprColor(*PTEXTCOLOR);
|
|
|
|
|
const auto FONTFAMILY = *PTITLEFONTFAMILY != STRVAL_EMPTY ? *PTITLEFONTFAMILY : *FALLBACKFONT;
|
2023-05-22 21:40:32 +02:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
m_texActive = g_pHyprOpenGL->renderText(pWindow->m_title, COLOR, *PTITLEFONTSIZE * monitorScale, false, FONTFAMILY, bufferSize.x - 2, FONTWEIGHTACTIVE->m_value);
|
|
|
|
|
m_texInactive = g_pHyprOpenGL->renderText(pWindow->m_title, COLOR, *PTITLEFONTSIZE * monitorScale, false, FONTFAMILY, bufferSize.x - 2, FONTWEIGHTINACTIVE->m_value);
|
2023-05-22 21:40:32 +02:00
|
|
|
}
|
|
|
|
|
|
2025-01-31 13:32:36 +00:00
|
|
|
static void renderGradientTo(SP<CTexture> tex, CGradientValueData* grad) {
|
2023-05-22 21:40:32 +02:00
|
|
|
|
2025-04-22 15:23:29 +02:00
|
|
|
if (!g_pCompositor->m_lastMonitor)
|
2023-11-29 13:36:37 +00:00
|
|
|
return;
|
|
|
|
|
|
2025-04-30 23:45:20 +02:00
|
|
|
const Vector2D& bufferSize = g_pCompositor->m_lastMonitor->m_pixelSize;
|
2023-05-22 21:40:32 +02:00
|
|
|
|
|
|
|
|
const auto CAIROSURFACE = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, bufferSize.x, bufferSize.y);
|
|
|
|
|
const auto CAIRO = cairo_create(CAIROSURFACE);
|
|
|
|
|
|
|
|
|
|
// clear the pixmap
|
|
|
|
|
cairo_save(CAIRO);
|
|
|
|
|
cairo_set_operator(CAIRO, CAIRO_OPERATOR_CLEAR);
|
|
|
|
|
cairo_paint(CAIRO);
|
|
|
|
|
cairo_restore(CAIRO);
|
|
|
|
|
|
|
|
|
|
cairo_pattern_t* pattern;
|
|
|
|
|
pattern = cairo_pattern_create_linear(0, 0, 0, bufferSize.y);
|
2024-01-08 18:38:22 +00:00
|
|
|
|
2025-04-20 20:39:33 +02:00
|
|
|
for (unsigned long i = 0; i < grad->m_colors.size(); i++) {
|
|
|
|
|
cairo_pattern_add_color_stop_rgba(pattern, 1 - (double)(i + 1) / (grad->m_colors.size() + 1), grad->m_colors[i].r, grad->m_colors[i].g, grad->m_colors[i].b,
|
|
|
|
|
grad->m_colors[i].a);
|
2024-01-08 18:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
2023-05-22 21:40:32 +02:00
|
|
|
cairo_rectangle(CAIRO, 0, 0, bufferSize.x, bufferSize.y);
|
|
|
|
|
cairo_set_source(CAIRO, pattern);
|
|
|
|
|
cairo_fill(CAIRO);
|
|
|
|
|
cairo_pattern_destroy(pattern);
|
|
|
|
|
|
|
|
|
|
cairo_surface_flush(CAIROSURFACE);
|
|
|
|
|
|
|
|
|
|
// copy the data to an OpenGL texture we have
|
|
|
|
|
const auto DATA = cairo_image_surface_get_data(CAIROSURFACE);
|
2024-06-08 10:07:59 +02:00
|
|
|
tex->allocate();
|
2025-05-05 23:44:49 +02:00
|
|
|
glBindTexture(GL_TEXTURE_2D, tex->m_texID);
|
2023-05-22 21:40:32 +02:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
|
|
|
|
|
|
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bufferSize.x, bufferSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
|
|
|
|
|
|
|
|
|
|
// delete cairo
|
|
|
|
|
cairo_destroy(CAIRO);
|
|
|
|
|
cairo_surface_destroy(CAIROSURFACE);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-26 17:59:49 +00:00
|
|
|
void refreshGroupBarGradients() {
|
2024-03-03 18:39:20 +00:00
|
|
|
static auto PGRADIENTS = CConfigValue<Hyprlang::INT>("group:groupbar:enabled");
|
|
|
|
|
static auto PENABLED = CConfigValue<Hyprlang::INT>("group:groupbar:gradients");
|
|
|
|
|
|
|
|
|
|
static auto PGROUPCOLACTIVE = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:col.active");
|
|
|
|
|
static auto PGROUPCOLINACTIVE = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:col.inactive");
|
|
|
|
|
static auto PGROUPCOLACTIVELOCKED = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:col.locked_active");
|
|
|
|
|
static auto PGROUPCOLINACTIVELOCKED = CConfigValue<Hyprlang::CUSTOMTYPE>("group:groupbar:col.locked_inactive");
|
|
|
|
|
auto* const GROUPCOLACTIVE = (CGradientValueData*)(PGROUPCOLACTIVE.ptr())->getData();
|
|
|
|
|
auto* const GROUPCOLINACTIVE = (CGradientValueData*)(PGROUPCOLINACTIVE.ptr())->getData();
|
|
|
|
|
auto* const GROUPCOLACTIVELOCKED = (CGradientValueData*)(PGROUPCOLACTIVELOCKED.ptr())->getData();
|
|
|
|
|
auto* const GROUPCOLINACTIVELOCKED = (CGradientValueData*)(PGROUPCOLINACTIVELOCKED.ptr())->getData();
|
2023-06-13 10:04:54 +00:00
|
|
|
|
2023-12-24 18:29:04 +00:00
|
|
|
g_pHyprRenderer->makeEGLCurrent();
|
|
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (m_tGradientActive->m_texID != 0) {
|
2024-06-08 10:07:59 +02:00
|
|
|
m_tGradientActive->destroyTexture();
|
|
|
|
|
m_tGradientInactive->destroyTexture();
|
|
|
|
|
m_tGradientLockedActive->destroyTexture();
|
|
|
|
|
m_tGradientLockedInactive->destroyTexture();
|
2023-11-26 17:59:49 +00:00
|
|
|
}
|
2023-06-13 10:04:54 +00:00
|
|
|
|
2024-03-03 18:39:20 +00:00
|
|
|
if (!*PENABLED || !*PGRADIENTS)
|
2023-12-30 14:18:53 +00:00
|
|
|
return;
|
|
|
|
|
|
2024-02-18 15:00:34 +00:00
|
|
|
renderGradientTo(m_tGradientActive, GROUPCOLACTIVE);
|
|
|
|
|
renderGradientTo(m_tGradientInactive, GROUPCOLINACTIVE);
|
|
|
|
|
renderGradientTo(m_tGradientLockedActive, GROUPCOLACTIVELOCKED);
|
|
|
|
|
renderGradientTo(m_tGradientLockedInactive, GROUPCOLINACTIVELOCKED);
|
2023-07-23 13:49:49 +00:00
|
|
|
}
|
2023-08-30 15:39:22 +00:00
|
|
|
|
2023-12-28 22:54:41 +00:00
|
|
|
bool CHyprGroupBarDecoration::onBeginWindowDragOnDeco(const Vector2D& pos) {
|
2025-03-12 10:09:09 -04:00
|
|
|
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
|
|
|
|
|
static auto POUTERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_out");
|
|
|
|
|
static auto PINNERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_in");
|
2025-05-05 23:44:49 +02:00
|
|
|
if (m_window.lock() == m_window->m_groupData.pNextWindow.lock())
|
2024-01-02 12:37:03 +00:00
|
|
|
return false;
|
|
|
|
|
|
2023-12-28 22:54:41 +00:00
|
|
|
const float BARRELATIVEX = pos.x - assignedBoxGlobal().x;
|
2024-05-16 06:38:10 -04:00
|
|
|
const float BARRELATIVEY = pos.y - assignedBoxGlobal().y;
|
2025-05-05 23:44:49 +02:00
|
|
|
const int WINDOWINDEX = *PSTACKED ? (BARRELATIVEY / (m_barHeight + *POUTERGAP)) : (BARRELATIVEX) / (m_barWidth + *PINNERGAP);
|
2024-05-16 06:38:10 -04:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (!*PSTACKED && (BARRELATIVEX - (m_barWidth + *PINNERGAP) * WINDOWINDEX > m_barWidth))
|
2024-05-16 06:38:10 -04:00
|
|
|
return false;
|
2023-12-28 22:54:41 +00:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (*PSTACKED && (BARRELATIVEY - (m_barHeight + *POUTERGAP) * WINDOWINDEX < *POUTERGAP))
|
2023-12-28 22:54:41 +00:00
|
|
|
return false;
|
|
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
PHLWINDOW pWindow = m_window->getGroupWindowByIndex(WINDOWINDEX);
|
2023-12-28 22:54:41 +00:00
|
|
|
|
|
|
|
|
// hack
|
|
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pWindow);
|
2025-04-28 22:25:22 +02:00
|
|
|
if (!pWindow->m_isFloating) {
|
2025-05-02 17:07:20 +02:00
|
|
|
const bool GROUPSLOCKEDPREV = g_pKeybindManager->m_groupsLocked;
|
|
|
|
|
g_pKeybindManager->m_groupsLocked = true;
|
2023-12-28 22:54:41 +00:00
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowCreated(pWindow);
|
2025-05-02 17:07:20 +02:00
|
|
|
g_pKeybindManager->m_groupsLocked = GROUPSLOCKEDPREV;
|
2023-12-28 22:54:41 +00:00
|
|
|
}
|
|
|
|
|
|
2025-05-01 23:57:11 +02:00
|
|
|
g_pInputManager->m_currentlyDraggedWindow = pWindow;
|
2023-12-28 22:54:41 +00:00
|
|
|
|
|
|
|
|
if (!g_pCompositor->isWindowActive(pWindow))
|
|
|
|
|
g_pCompositor->focusWindow(pWindow);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2024-04-27 12:43:12 +01:00
|
|
|
bool CHyprGroupBarDecoration::onEndWindowDragOnDeco(const Vector2D& pos, PHLWINDOW pDraggedWindow) {
|
2024-10-09 11:58:49 +02:00
|
|
|
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
|
|
|
|
|
static auto PDRAGINTOGROUP = CConfigValue<Hyprlang::INT>("group:drag_into_group");
|
|
|
|
|
static auto PMERGEFLOATEDINTOTILEDONGROUPBAR = CConfigValue<Hyprlang::INT>("group:merge_floated_into_tiled_on_groupbar");
|
2024-11-06 17:52:10 +01:00
|
|
|
static auto PMERGEGROUPSONGROUPBAR = CConfigValue<Hyprlang::INT>("group:merge_groups_on_groupbar");
|
2025-03-12 10:09:09 -04:00
|
|
|
static auto POUTERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_out");
|
|
|
|
|
static auto PINNERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_in");
|
2025-05-05 23:44:49 +02:00
|
|
|
const bool FLOATEDINTOTILED = !m_window->m_isFloating && !pDraggedWindow->m_draggingTiled;
|
2024-10-09 11:58:49 +02:00
|
|
|
|
2025-05-01 23:57:11 +02:00
|
|
|
g_pInputManager->m_wasDraggingWindow = false;
|
2024-11-06 17:52:10 +01:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (!pDraggedWindow->canBeGroupedInto(m_window.lock()) || (*PDRAGINTOGROUP != 1 && *PDRAGINTOGROUP != 2) || (FLOATEDINTOTILED && !*PMERGEFLOATEDINTOTILEDONGROUPBAR) ||
|
|
|
|
|
(!*PMERGEGROUPSONGROUPBAR && pDraggedWindow->m_groupData.pNextWindow.lock() && m_window->m_groupData.pNextWindow.lock())) {
|
2025-05-01 23:57:11 +02:00
|
|
|
g_pInputManager->m_wasDraggingWindow = true;
|
2023-12-28 22:54:41 +00:00
|
|
|
return false;
|
2024-11-06 17:52:10 +01:00
|
|
|
}
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
const float BARRELATIVE = *PSTACKED ? pos.y - assignedBoxGlobal().y - (m_barHeight + *POUTERGAP) / 2 : pos.x - assignedBoxGlobal().x - m_barWidth / 2;
|
|
|
|
|
const float BARSIZE = *PSTACKED ? m_barHeight + *POUTERGAP : m_barWidth + *PINNERGAP;
|
2024-05-16 06:38:10 -04:00
|
|
|
const int WINDOWINDEX = BARRELATIVE < 0 ? -1 : BARRELATIVE / BARSIZE;
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
PHLWINDOW pWindowInsertAfter = m_window->getGroupWindowByIndex(WINDOWINDEX);
|
2025-04-28 22:25:22 +02:00
|
|
|
PHLWINDOW pWindowInsertEnd = pWindowInsertAfter->m_groupData.pNextWindow.lock();
|
|
|
|
|
PHLWINDOW pDraggedHead = pDraggedWindow->m_groupData.pNextWindow.lock() ? pDraggedWindow->getGroupHead() : pDraggedWindow;
|
2023-11-01 19:13:39 +00:00
|
|
|
|
2025-04-28 22:25:22 +02:00
|
|
|
if (!pDraggedWindow->m_groupData.pNextWindow.expired()) {
|
2023-11-01 19:13:39 +00:00
|
|
|
|
|
|
|
|
// stores group data
|
2024-04-27 12:43:12 +01:00
|
|
|
std::vector<PHLWINDOW> members;
|
|
|
|
|
PHLWINDOW curr = pDraggedHead;
|
2025-04-28 22:25:22 +02:00
|
|
|
const bool WASLOCKED = pDraggedHead->m_groupData.locked;
|
2023-11-01 19:13:39 +00:00
|
|
|
do {
|
|
|
|
|
members.push_back(curr);
|
2025-04-28 22:25:22 +02:00
|
|
|
curr = curr->m_groupData.pNextWindow.lock();
|
2023-11-01 19:13:39 +00:00
|
|
|
} while (curr != members[0]);
|
|
|
|
|
|
|
|
|
|
// removes all windows
|
2024-12-22 17:12:09 +01:00
|
|
|
for (const PHLWINDOW& w : members) {
|
2025-04-28 22:25:22 +02:00
|
|
|
w->m_groupData.pNextWindow.reset();
|
|
|
|
|
w->m_groupData.head = false;
|
|
|
|
|
w->m_groupData.locked = false;
|
2023-11-01 19:13:39 +00:00
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(w);
|
|
|
|
|
}
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2023-11-01 19:13:39 +00:00
|
|
|
// restores the group
|
|
|
|
|
for (auto it = members.begin(); it != members.end(); ++it) {
|
2025-04-28 22:25:22 +02:00
|
|
|
(*it)->m_isFloating = pWindowInsertAfter->m_isFloating; // match the floating state of group members
|
|
|
|
|
*(*it)->m_realSize = pWindowInsertAfter->m_realSize->goal(); // match the size of group members
|
|
|
|
|
*(*it)->m_realPosition = pWindowInsertAfter->m_realPosition->goal(); // match the position of group members
|
2023-11-01 19:13:39 +00:00
|
|
|
if (std::next(it) != members.end())
|
2025-04-28 22:25:22 +02:00
|
|
|
(*it)->m_groupData.pNextWindow = *std::next(it);
|
2023-11-01 19:13:39 +00:00
|
|
|
else
|
2025-04-28 22:25:22 +02:00
|
|
|
(*it)->m_groupData.pNextWindow = members[0];
|
2023-11-01 19:13:39 +00:00
|
|
|
}
|
2025-04-28 22:25:22 +02:00
|
|
|
members[0]->m_groupData.head = true;
|
|
|
|
|
members[0]->m_groupData.locked = WASLOCKED;
|
2024-10-08 12:20:41 +02:00
|
|
|
} else
|
2023-11-01 19:13:39 +00:00
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(pDraggedWindow);
|
2024-10-08 12:20:41 +02:00
|
|
|
|
2025-04-28 22:25:22 +02:00
|
|
|
pDraggedWindow->m_isFloating = pWindowInsertAfter->m_isFloating; // match the floating state of the window
|
2024-10-08 12:20:41 +02:00
|
|
|
|
2023-10-29 20:14:47 +00:00
|
|
|
pWindowInsertAfter->insertWindowToGroup(pDraggedWindow);
|
|
|
|
|
|
|
|
|
|
if (WINDOWINDEX == -1)
|
2025-04-28 22:25:22 +02:00
|
|
|
std::swap(pDraggedHead->m_groupData.head, pWindowInsertEnd->m_groupData.head);
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
m_window->setGroupCurrent(pDraggedWindow);
|
2024-12-21 16:35:47 +00:00
|
|
|
pDraggedWindow->applyGroupRules();
|
2023-10-29 20:14:47 +00:00
|
|
|
pDraggedWindow->updateWindowDecos();
|
|
|
|
|
g_pLayoutManager->getCurrentLayout()->recalculateWindow(pDraggedWindow);
|
|
|
|
|
|
2023-11-19 12:29:01 +00:00
|
|
|
if (!pDraggedWindow->getDecorationByType(DECORATION_GROUPBAR))
|
2025-01-23 21:55:41 +01:00
|
|
|
pDraggedWindow->addWindowDeco(makeUnique<CHyprGroupBarDecoration>(pDraggedWindow));
|
2023-11-19 12:29:01 +00:00
|
|
|
|
2023-12-28 22:54:41 +00:00
|
|
|
return true;
|
2023-10-29 20:14:47 +00:00
|
|
|
}
|
|
|
|
|
|
2024-05-09 18:19:32 +00:00
|
|
|
bool CHyprGroupBarDecoration::onMouseButtonOnDeco(const Vector2D& pos, const IPointer::SButtonEvent& e) {
|
2025-03-12 10:09:09 -04:00
|
|
|
static auto PSTACKED = CConfigValue<Hyprlang::INT>("group:groupbar:stacked");
|
|
|
|
|
static auto POUTERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_out");
|
|
|
|
|
static auto PINNERGAP = CConfigValue<Hyprlang::INT>("group:groupbar:gaps_in");
|
2025-05-05 23:44:49 +02:00
|
|
|
if (m_window->isEffectiveInternalFSMode(FSMODE_FULLSCREEN))
|
2023-12-29 23:38:12 +00:00
|
|
|
return true;
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2023-11-11 14:37:17 +00:00
|
|
|
const float BARRELATIVEX = pos.x - assignedBoxGlobal().x;
|
2024-05-16 06:38:10 -04:00
|
|
|
const float BARRELATIVEY = pos.y - assignedBoxGlobal().y;
|
2025-05-05 23:44:49 +02:00
|
|
|
const int WINDOWINDEX = *PSTACKED ? (BARRELATIVEY / (m_barHeight + *POUTERGAP)) : (BARRELATIVEX) / (m_barWidth + *PINNERGAP);
|
2024-03-22 17:41:20 +00:00
|
|
|
static auto PFOLLOWMOUSE = CConfigValue<Hyprlang::INT>("input:follow_mouse");
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2023-12-29 23:38:12 +00:00
|
|
|
// close window on middle click
|
2024-05-09 18:19:32 +00:00
|
|
|
if (e.button == 274) {
|
2023-12-29 23:38:12 +00:00
|
|
|
static Vector2D pressedCursorPos;
|
|
|
|
|
|
2024-05-09 18:19:32 +00:00
|
|
|
if (e.state == WL_POINTER_BUTTON_STATE_PRESSED)
|
2023-12-29 23:38:12 +00:00
|
|
|
pressedCursorPos = pos;
|
2024-05-09 18:19:32 +00:00
|
|
|
else if (e.state == WL_POINTER_BUTTON_STATE_RELEASED && pressedCursorPos == pos)
|
2025-05-05 23:44:49 +02:00
|
|
|
g_pXWaylandManager->sendCloseWindow(m_window->getGroupWindowByIndex(WINDOWINDEX));
|
2023-12-29 23:38:12 +00:00
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 18:19:32 +00:00
|
|
|
if (e.state != WL_POINTER_BUTTON_STATE_PRESSED)
|
2023-12-29 23:38:12 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// click on padding
|
2025-05-05 23:44:49 +02:00
|
|
|
const auto TABPAD = !*PSTACKED && (BARRELATIVEX - (m_barWidth + *PINNERGAP) * WINDOWINDEX > m_barWidth);
|
|
|
|
|
const auto STACKPAD = *PSTACKED && (BARRELATIVEY - (m_barHeight + *POUTERGAP) * WINDOWINDEX < *POUTERGAP);
|
2024-05-16 06:38:10 -04:00
|
|
|
if (TABPAD || STACKPAD) {
|
2025-05-05 23:44:49 +02:00
|
|
|
if (!g_pCompositor->isWindowActive(m_window.lock()))
|
|
|
|
|
g_pCompositor->focusWindow(m_window.lock());
|
2023-12-28 22:54:41 +00:00
|
|
|
return true;
|
2023-10-29 20:14:47 +00:00
|
|
|
}
|
|
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
PHLWINDOW pWindow = m_window->getGroupWindowByIndex(WINDOWINDEX);
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (pWindow != m_window)
|
2023-10-29 20:14:47 +00:00
|
|
|
pWindow->setGroupCurrent(pWindow);
|
|
|
|
|
|
2024-03-22 17:41:20 +00:00
|
|
|
if (!g_pCompositor->isWindowActive(pWindow) && *PFOLLOWMOUSE != 3)
|
|
|
|
|
g_pCompositor->focusWindow(pWindow);
|
|
|
|
|
|
2025-04-28 22:25:22 +02:00
|
|
|
if (pWindow->m_isFloating)
|
2024-12-22 17:12:09 +01:00
|
|
|
g_pCompositor->changeWindowZOrder(pWindow, true);
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2023-12-28 22:54:41 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2024-05-09 18:19:32 +00:00
|
|
|
bool CHyprGroupBarDecoration::onScrollOnDeco(const Vector2D& pos, const IPointer::SAxisEvent e) {
|
2024-03-03 18:39:20 +00:00
|
|
|
static auto PGROUPBARSCROLLING = CConfigValue<Hyprlang::INT>("group:groupbar:scrolling");
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (!*PGROUPBARSCROLLING || m_window->m_groupData.pNextWindow.expired())
|
2023-12-28 22:54:41 +00:00
|
|
|
return false;
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2024-05-09 18:19:32 +00:00
|
|
|
if (e.delta > 0)
|
2025-05-05 23:44:49 +02:00
|
|
|
m_window->setGroupCurrent(m_window->m_groupData.pNextWindow.lock());
|
2023-12-28 22:54:41 +00:00
|
|
|
else
|
2025-05-05 23:44:49 +02:00
|
|
|
m_window->setGroupCurrent(m_window->getGroupPrevious());
|
2023-10-29 20:14:47 +00:00
|
|
|
|
2023-12-28 22:54:41 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool CHyprGroupBarDecoration::onInputOnDeco(const eInputType type, const Vector2D& mouseCoords, std::any data) {
|
|
|
|
|
switch (type) {
|
2024-05-09 18:19:32 +00:00
|
|
|
case INPUT_TYPE_AXIS: return onScrollOnDeco(mouseCoords, std::any_cast<const IPointer::SAxisEvent>(data));
|
|
|
|
|
case INPUT_TYPE_BUTTON: return onMouseButtonOnDeco(mouseCoords, std::any_cast<const IPointer::SButtonEvent&>(data));
|
2023-12-28 22:54:41 +00:00
|
|
|
case INPUT_TYPE_DRAG_START: return onBeginWindowDragOnDeco(mouseCoords);
|
2024-04-27 12:43:12 +01:00
|
|
|
case INPUT_TYPE_DRAG_END: return onEndWindowDragOnDeco(mouseCoords, std::any_cast<PHLWINDOW>(data));
|
2023-12-28 22:54:41 +00:00
|
|
|
default: return false;
|
|
|
|
|
}
|
2023-10-29 20:14:47 +00:00
|
|
|
}
|
2023-11-04 13:10:52 +00:00
|
|
|
|
|
|
|
|
eDecorationLayer CHyprGroupBarDecoration::getDecorationLayer() {
|
|
|
|
|
return DECORATION_LAYER_OVER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t CHyprGroupBarDecoration::getDecorationFlags() {
|
|
|
|
|
return DECORATION_ALLOWS_MOUSE_INPUT;
|
2023-11-11 14:37:17 +00:00
|
|
|
}
|
|
|
|
|
|
2023-12-28 15:38:16 +00:00
|
|
|
std::string CHyprGroupBarDecoration::getDisplayName() {
|
|
|
|
|
return "GroupBar";
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-11 14:37:17 +00:00
|
|
|
CBox CHyprGroupBarDecoration::assignedBoxGlobal() {
|
2025-05-05 23:44:49 +02:00
|
|
|
CBox box = m_assignedBox;
|
|
|
|
|
box.translate(g_pDecorationPositioner->getEdgeDefinedPoint(DECORATION_EDGE_TOP, m_window.lock()));
|
2023-11-12 22:40:21 +00:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
const auto PWORKSPACE = m_window->m_workspace;
|
2023-11-12 22:40:21 +00:00
|
|
|
|
2025-05-05 23:44:49 +02:00
|
|
|
if (PWORKSPACE && !m_window->m_pinned)
|
2025-04-25 02:37:12 +02:00
|
|
|
box.translate(PWORKSPACE->m_renderOffset->value());
|
2023-11-12 22:40:21 +00:00
|
|
|
|
2025-03-26 11:44:38 +00:00
|
|
|
return box.round();
|
2023-11-15 21:32:44 +01:00
|
|
|
}
|