mirror of
https://github.com/hyprwm/Hyprland
synced 2024-11-25 21:25:59 +01:00
Group/Tab Rework (#1580)
This commit is contained in:
parent
2363cc2572
commit
e5a4c0c986
12 changed files with 268 additions and 495 deletions
|
@ -1583,6 +1583,8 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||||
// optimization
|
// optimization
|
||||||
static auto* const ACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.active_border")->data.get();
|
static auto* const ACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.active_border")->data.get();
|
||||||
static auto* const INACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->data.get();
|
static auto* const INACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.inactive_border")->data.get();
|
||||||
|
static auto* const GROUPACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border_active")->data.get();
|
||||||
|
static auto* const GROUPINACTIVECOL = (CGradientValueData*)g_pConfigManager->getConfigValuePtr("general:col.group_border")->data.get();
|
||||||
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
static auto* const PINACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:inactive_opacity")->floatValue;
|
||||||
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
static auto* const PACTIVEALPHA = &g_pConfigManager->getConfigValuePtr("decoration:active_opacity")->floatValue;
|
||||||
static auto* const PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue;
|
static auto* const PFULLSCREENALPHA = &g_pConfigManager->getConfigValuePtr("decoration:fullscreen_opacity")->floatValue;
|
||||||
|
@ -1604,13 +1606,19 @@ void CCompositor::updateWindowAnimatedDecorationValues(CWindow* pWindow) {
|
||||||
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow);
|
const auto RENDERDATA = g_pLayoutManager->getCurrentLayout()->requestRenderHints(pWindow);
|
||||||
if (RENDERDATA.isBorderGradient)
|
if (RENDERDATA.isBorderGradient)
|
||||||
setBorderColor(*RENDERDATA.borderGradient);
|
setBorderColor(*RENDERDATA.borderGradient);
|
||||||
else
|
else {
|
||||||
setBorderColor(pWindow == m_pLastWindow ? (pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying() >= 0 ?
|
if (pWindow == m_pLastWindow) {
|
||||||
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying())) :
|
const auto* const ACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow ? ACTIVECOL : GROUPACTIVECOL;
|
||||||
*ACTIVECOL) :
|
setBorderColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying() >= 0 ?
|
||||||
(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying() >= 0 ?
|
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.activeBorderColor.toUnderlying())) :
|
||||||
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying())) :
|
*ACTIVECOLOR);
|
||||||
*INACTIVECOL));
|
} else {
|
||||||
|
const auto* const INACTIVECOLOR = !pWindow->m_sGroupData.pNextWindow ? INACTIVECOL : GROUPINACTIVECOL;
|
||||||
|
setBorderColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying() >= 0 ?
|
||||||
|
CGradientValueData(CColor(pWindow->m_sSpecialRenderData.inactiveBorderColor.toUnderlying())) :
|
||||||
|
*INACTIVECOLOR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// tick angle if it's not running (aka dead)
|
// tick angle if it's not running (aka dead)
|
||||||
if (!pWindow->m_fBorderAngleAnimationProgress.isBeingAnimated())
|
if (!pWindow->m_fBorderAngleAnimationProgress.isBeingAnimated())
|
||||||
|
|
|
@ -468,3 +468,71 @@ bool CWindow::hasPopupAt(const Vector2D& pos) {
|
||||||
|
|
||||||
return resultSurf;
|
return resultSurf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CWindow* CWindow::getGroupHead() {
|
||||||
|
CWindow* curr = this;
|
||||||
|
while (!curr->m_sGroupData.head)
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindow* CWindow::getGroupTail() {
|
||||||
|
CWindow* curr = this;
|
||||||
|
while (!curr->m_sGroupData.pNextWindow->m_sGroupData.head)
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CWindow* CWindow::getGroupCurrent() {
|
||||||
|
CWindow* curr = this;
|
||||||
|
while (curr->isHidden())
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
return curr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::setGroupCurrent(CWindow* pWindow) {
|
||||||
|
CWindow* curr = this->m_sGroupData.pNextWindow;
|
||||||
|
bool isMember = false;
|
||||||
|
while (curr != this) {
|
||||||
|
if (curr == pWindow) {
|
||||||
|
isMember = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isMember && pWindow != this)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto PCURRENT = getGroupCurrent();
|
||||||
|
|
||||||
|
const auto PWINDOWSIZE = PCURRENT->m_vRealSize.goalv();
|
||||||
|
const auto PWINDOWPOS = PCURRENT->m_vRealPosition.goalv();
|
||||||
|
|
||||||
|
const auto CURRENTISFOCUS = PCURRENT == g_pCompositor->m_pLastWindow;
|
||||||
|
|
||||||
|
PCURRENT->setHidden(true);
|
||||||
|
pWindow->setHidden(false);
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->replaceWindowDataWith(PCURRENT, pWindow);
|
||||||
|
|
||||||
|
if (PCURRENT->m_bIsFloating) {
|
||||||
|
pWindow->m_vRealPosition.setValueAndWarp(PWINDOWPOS);
|
||||||
|
pWindow->m_vRealSize.setValueAndWarp(PWINDOWSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||||
|
|
||||||
|
if (CURRENTISFOCUS)
|
||||||
|
g_pCompositor->focusWindow(pWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CWindow::insertWindowToGroup(CWindow* pWindow) {
|
||||||
|
const auto PHEAD = getGroupHead();
|
||||||
|
const auto PTAIL = getGroupTail();
|
||||||
|
|
||||||
|
PTAIL->m_sGroupData.pNextWindow = pWindow;
|
||||||
|
pWindow->m_sGroupData.pNextWindow = PHEAD;
|
||||||
|
|
||||||
|
setGroupCurrent(pWindow);
|
||||||
|
}
|
|
@ -273,6 +273,12 @@ class CWindow {
|
||||||
// for idle inhibiting windows
|
// for idle inhibiting windows
|
||||||
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
eIdleInhibitMode m_eIdleInhibitMode = IDLEINHIBIT_NONE;
|
||||||
|
|
||||||
|
// for groups
|
||||||
|
struct SGroupData {
|
||||||
|
CWindow* pNextWindow = nullptr; // nullptr means no grouping. Self means single group.
|
||||||
|
bool head = false;
|
||||||
|
} m_sGroupData;
|
||||||
|
|
||||||
// For the list lookup
|
// For the list lookup
|
||||||
bool operator==(const CWindow& rhs) {
|
bool operator==(const CWindow& rhs) {
|
||||||
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize &&
|
return m_uSurface.xdg == rhs.m_uSurface.xdg && m_uSurface.xwayland == rhs.m_uSurface.xwayland && m_vPosition == rhs.m_vPosition && m_vSize == rhs.m_vSize &&
|
||||||
|
@ -303,6 +309,12 @@ class CWindow {
|
||||||
bool isInCurvedCorner(double x, double y);
|
bool isInCurvedCorner(double x, double y);
|
||||||
bool hasPopupAt(const Vector2D& pos);
|
bool hasPopupAt(const Vector2D& pos);
|
||||||
|
|
||||||
|
CWindow* getGroupHead();
|
||||||
|
CWindow* getGroupTail();
|
||||||
|
CWindow* getGroupCurrent();
|
||||||
|
void setGroupCurrent(CWindow* pWindow);
|
||||||
|
void insertWindowToGroup(CWindow* pWindow);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// For hidden windows and stuff
|
// For hidden windows and stuff
|
||||||
bool m_bHidden = false;
|
bool m_bHidden = false;
|
||||||
|
|
|
@ -13,8 +13,8 @@
|
||||||
CConfigManager::CConfigManager() {
|
CConfigManager::CConfigManager() {
|
||||||
configValues["general:col.active_border"].data = std::make_shared<CGradientValueData>(0xffffffff);
|
configValues["general:col.active_border"].data = std::make_shared<CGradientValueData>(0xffffffff);
|
||||||
configValues["general:col.inactive_border"].data = std::make_shared<CGradientValueData>(0xff444444);
|
configValues["general:col.inactive_border"].data = std::make_shared<CGradientValueData>(0xff444444);
|
||||||
configValues["dwindle:col.group_border"].data = std::make_shared<CGradientValueData>(0x66777700);
|
configValues["general:col.group_border"].data = std::make_shared<CGradientValueData>(0x66777700);
|
||||||
configValues["dwindle:col.group_border_active"].data = std::make_shared<CGradientValueData>(0x66ffff00);
|
configValues["general:col.group_border_active"].data = std::make_shared<CGradientValueData>(0x66ffff00);
|
||||||
|
|
||||||
setDefaultVars();
|
setDefaultVars();
|
||||||
setDefaultAnimationVars();
|
setDefaultAnimationVars();
|
||||||
|
@ -44,6 +44,8 @@ void CConfigManager::setDefaultVars() {
|
||||||
configValues["general:gaps_out"].intValue = 20;
|
configValues["general:gaps_out"].intValue = 20;
|
||||||
((CGradientValueData*)configValues["general:col.active_border"].data.get())->reset(0xffffffff);
|
((CGradientValueData*)configValues["general:col.active_border"].data.get())->reset(0xffffffff);
|
||||||
((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444);
|
((CGradientValueData*)configValues["general:col.inactive_border"].data.get())->reset(0xff444444);
|
||||||
|
((CGradientValueData*)configValues["general:col.group_border"].data.get())->reset(0x66777700);
|
||||||
|
((CGradientValueData*)configValues["general:col.group_border_active"].data.get())->reset(0x66ffff00);
|
||||||
configValues["general:cursor_inactive_timeout"].intValue = 0;
|
configValues["general:cursor_inactive_timeout"].intValue = 0;
|
||||||
configValues["general:no_cursor_warps"].intValue = 0;
|
configValues["general:no_cursor_warps"].intValue = 0;
|
||||||
configValues["general:resize_on_border"].intValue = 0;
|
configValues["general:resize_on_border"].intValue = 0;
|
||||||
|
@ -102,8 +104,6 @@ void CConfigManager::setDefaultVars() {
|
||||||
configValues["decoration:dim_around"].floatValue = 0.4f;
|
configValues["decoration:dim_around"].floatValue = 0.4f;
|
||||||
configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY;
|
configValues["decoration:screen_shader"].strValue = STRVAL_EMPTY;
|
||||||
|
|
||||||
((CGradientValueData*)configValues["dwindle:col.group_border"].data.get())->reset(0x66777700);
|
|
||||||
((CGradientValueData*)configValues["dwindle:col.group_border_active"].data.get())->reset(0x66ffff00);
|
|
||||||
configValues["dwindle:pseudotile"].intValue = 0;
|
configValues["dwindle:pseudotile"].intValue = 0;
|
||||||
configValues["dwindle:force_split"].intValue = 0;
|
configValues["dwindle:force_split"].intValue = 0;
|
||||||
configValues["dwindle:preserve_split"].intValue = 0;
|
configValues["dwindle:preserve_split"].intValue = 0;
|
||||||
|
|
|
@ -45,64 +45,6 @@ void SDwindleNodeData::getAllChildrenRecursive(std::deque<SDwindleNodeData*>* pD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDwindleNodeData::isGroupMember() {
|
|
||||||
return pNextGroupMember && pNextGroupMember != this;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDwindleNodeData* SDwindleNodeData::getGroupHead() {
|
|
||||||
SDwindleNodeData* current = this->pNextGroupMember;
|
|
||||||
|
|
||||||
while (current != this) {
|
|
||||||
if (current->groupHead) {
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
current = current->pNextGroupMember;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->groupHead = true;
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDwindleNodeData* SDwindleNodeData::getGroupVisible() {
|
|
||||||
SDwindleNodeData* current = this->pNextGroupMember;
|
|
||||||
|
|
||||||
while (current != this) {
|
|
||||||
if (!current->pWindow->isHidden()) {
|
|
||||||
return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
current = current->pNextGroupMember;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SDwindleNodeData::setGroupFocusedNode(SDwindleNodeData* pMember) {
|
|
||||||
SDwindleNodeData* current = this->pNextGroupMember;
|
|
||||||
|
|
||||||
while (current != this) {
|
|
||||||
current->pWindow->setHidden(current != pMember);
|
|
||||||
current = current->pNextGroupMember;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->pWindow->setHidden(pMember != this);
|
|
||||||
}
|
|
||||||
|
|
||||||
int SDwindleNodeData::getGroupMemberCount() {
|
|
||||||
SDwindleNodeData* current = this->pNextGroupMember;
|
|
||||||
|
|
||||||
int no = 1;
|
|
||||||
|
|
||||||
while (current != this) {
|
|
||||||
current = current->pNextGroupMember;
|
|
||||||
no++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return no;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) {
|
int CHyprDwindleLayout::getNodesOnWorkspace(const int& id) {
|
||||||
int no = 0;
|
int no = 0;
|
||||||
for (auto& n : m_lDwindleNodesData) {
|
for (auto& n : m_lDwindleNodesData) {
|
||||||
|
@ -189,8 +131,7 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
|
const auto NODESONWORKSPACE = getNodesOnWorkspace(PWINDOW->m_iWorkspaceID);
|
||||||
|
|
||||||
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
|
if (*PNOGAPSWHENONLY && !g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID) &&
|
||||||
(NODESONWORKSPACE == 1 || (pNode->isGroupMember() && pNode->getGroupMemberCount() == NODESONWORKSPACE) ||
|
(NODESONWORKSPACE == 1 || (PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
|
||||||
(PWINDOW->m_bIsFullscreen && g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
|
|
||||||
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
|
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
|
||||||
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
|
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
|
||||||
|
|
||||||
|
@ -262,14 +203,6 @@ void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode, bool for
|
||||||
g_pHyprRenderer->damageWindow(PWINDOW);
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pNode->isGroupMember() && pNode->groupHead) {
|
|
||||||
// update visible node
|
|
||||||
const auto PVISNODE = pNode->getGroupVisible();
|
|
||||||
|
|
||||||
PVISNODE->pWindow->m_vRealSize = PWINDOW->m_vRealSize.goalv();
|
|
||||||
PVISNODE->pWindow->m_vRealPosition = PWINDOW->m_vRealPosition.goalv();
|
|
||||||
}
|
|
||||||
|
|
||||||
PWINDOW->updateWindowDecos();
|
PWINDOW->updateWindowDecos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,23 +292,10 @@ void CHyprDwindleLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// if it's a group, add the window
|
// if it's a group, add the window
|
||||||
if (OPENINGON->isGroupMember()) {
|
if (OPENINGON->pWindow->m_sGroupData.pNextWindow) {
|
||||||
const auto PHEAD = OPENINGON->getGroupHead();
|
m_lDwindleNodesData.remove(*PNODE);
|
||||||
|
|
||||||
const auto PTAIL = PHEAD->pPreviousGroupMember;
|
OPENINGON->pWindow->insertWindowToGroup(pWindow);
|
||||||
|
|
||||||
PHEAD->pPreviousGroupMember = PNODE;
|
|
||||||
PTAIL->pNextGroupMember = PNODE;
|
|
||||||
|
|
||||||
PNODE->pNextGroupMember = PHEAD;
|
|
||||||
PNODE->pPreviousGroupMember = PTAIL;
|
|
||||||
|
|
||||||
PHEAD->setGroupFocusedNode(PNODE);
|
|
||||||
|
|
||||||
PNODE->position = PHEAD->position;
|
|
||||||
PNODE->size = PHEAD->size;
|
|
||||||
|
|
||||||
applyNodeDataToWindow(PNODE);
|
|
||||||
|
|
||||||
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||||
|
|
||||||
|
@ -479,51 +399,6 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||||
if (pWindow->m_bIsFullscreen)
|
if (pWindow->m_bIsFullscreen)
|
||||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||||
|
|
||||||
// check if it was grouped
|
|
||||||
if (PNODE->isGroupMember()) {
|
|
||||||
// get shit
|
|
||||||
const auto PPREV = PNODE->pPreviousGroupMember;
|
|
||||||
const auto PNEXT = PNODE->pNextGroupMember;
|
|
||||||
|
|
||||||
PPREV->pNextGroupMember = PNEXT;
|
|
||||||
PNEXT->pPreviousGroupMember = PPREV;
|
|
||||||
|
|
||||||
if (PNODE->groupHead) {
|
|
||||||
PNEXT->groupHead = true;
|
|
||||||
PNEXT->pParent = PNODE->pParent;
|
|
||||||
|
|
||||||
if (PNODE->pParent) {
|
|
||||||
if (PNODE->pParent->children[0] == PNODE) {
|
|
||||||
PNODE->pParent->children[0] = PNEXT;
|
|
||||||
} else {
|
|
||||||
PNODE->pParent->children[1] = PNEXT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PNEXT->position = PNODE->position;
|
|
||||||
PNEXT->size = PNODE->size;
|
|
||||||
} else {
|
|
||||||
const auto PHEAD = PNODE->getGroupHead();
|
|
||||||
|
|
||||||
PNEXT->position = PHEAD->position;
|
|
||||||
PNEXT->size = PHEAD->size;
|
|
||||||
}
|
|
||||||
|
|
||||||
PNEXT->setGroupFocusedNode(PNEXT);
|
|
||||||
PNEXT->pWindow->setHidden(false);
|
|
||||||
|
|
||||||
m_lDwindleNodesData.remove(*PNODE);
|
|
||||||
|
|
||||||
applyNodeDataToWindow(PNEXT);
|
|
||||||
|
|
||||||
if (!PNEXT->isGroupMember()) {
|
|
||||||
// means we dissolved the group
|
|
||||||
recalculateMonitor(PNEXT->pWindow->m_iMonitorID);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto PPARENT = PNODE->pParent;
|
const auto PPARENT = PNODE->pParent;
|
||||||
|
|
||||||
if (!PPARENT) {
|
if (!PPARENT) {
|
||||||
|
@ -538,17 +413,6 @@ void CHyprDwindleLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
||||||
PSIBLING->size = PPARENT->size;
|
PSIBLING->size = PPARENT->size;
|
||||||
PSIBLING->pParent = PPARENT->pParent;
|
PSIBLING->pParent = PPARENT->pParent;
|
||||||
|
|
||||||
if (PSIBLING->isGroupMember()) {
|
|
||||||
// apply to all group members
|
|
||||||
SDwindleNodeData* current = PSIBLING->pNextGroupMember;
|
|
||||||
|
|
||||||
while (current != PSIBLING) {
|
|
||||||
current->position = PPARENT->position;
|
|
||||||
current->size = PPARENT->size;
|
|
||||||
current = current->pNextGroupMember;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PPARENT->pParent != nullptr) {
|
if (PPARENT->pParent != nullptr) {
|
||||||
if (PPARENT->pParent->children[0] == PPARENT) {
|
if (PPARENT->pParent->children[0] == PPARENT) {
|
||||||
PPARENT->pParent->children[0] = PSIBLING;
|
PPARENT->pParent->children[0] = PSIBLING;
|
||||||
|
@ -819,252 +683,14 @@ void addToDequeRecursive(std::deque<SDwindleNodeData*>* pDeque, std::deque<SDwin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprDwindleLayout::toggleWindowGroup(CWindow* pWindow) {
|
|
||||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// get the node
|
|
||||||
const auto PNODE = getNodeFromWindow(pWindow);
|
|
||||||
|
|
||||||
if (!PNODE) {
|
|
||||||
Debug::log(LOG, "Rejecting to group a floating window");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
|
|
||||||
|
|
||||||
if (PWORKSPACE->m_bHasFullscreenWindow && !PNODE->isGroupMember()) {
|
|
||||||
Debug::log(ERR, "Cannot enable group on a fullscreen window");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PNODE->isGroupMember()) {
|
|
||||||
// dissolve group
|
|
||||||
const auto PHEAD = PNODE->getGroupHead();
|
|
||||||
|
|
||||||
SDwindleNodeData* current = PNODE->pNextGroupMember;
|
|
||||||
|
|
||||||
PNODE->pWindow->m_bIsFloating = PHEAD->pWindow->m_bIsFloating;
|
|
||||||
|
|
||||||
std::deque<CWindow*> toAddWindows;
|
|
||||||
|
|
||||||
const auto PWINDOWNODE = PNODE->pWindow;
|
|
||||||
toAddWindows.push_back(PWINDOWNODE);
|
|
||||||
|
|
||||||
while (current != PNODE) {
|
|
||||||
const auto PWINDOW = current->pWindow;
|
|
||||||
current = current->pNextGroupMember;
|
|
||||||
|
|
||||||
toAddWindows.push_back(PWINDOW);
|
|
||||||
|
|
||||||
PWINDOW->setHidden(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PHEAD->pPreviousGroupMember)
|
|
||||||
PHEAD->pPreviousGroupMember->pNextGroupMember = PHEAD->pNextGroupMember;
|
|
||||||
|
|
||||||
if (PHEAD->pNextGroupMember)
|
|
||||||
PHEAD->pNextGroupMember->pPreviousGroupMember = PHEAD->pPreviousGroupMember;
|
|
||||||
|
|
||||||
PHEAD->pPreviousGroupMember = nullptr;
|
|
||||||
PHEAD->pNextGroupMember = nullptr;
|
|
||||||
|
|
||||||
onWindowRemoved(PHEAD->pWindow);
|
|
||||||
|
|
||||||
for (auto& pw : toAddWindows) {
|
|
||||||
const auto PNODE = getNodeFromWindow(pw);
|
|
||||||
if (PNODE)
|
|
||||||
m_lDwindleNodesData.remove(*PNODE);
|
|
||||||
|
|
||||||
pw->m_vPosition = Vector2D(-1000000, -1000000);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& pw : toAddWindows) {
|
|
||||||
onWindowCreated(pw);
|
|
||||||
pw->removeDecorationByType(DECORATION_GROUPBAR);
|
|
||||||
}
|
|
||||||
|
|
||||||
recalculateMonitor(PWORKSPACE->m_iMonitorID);
|
|
||||||
} else {
|
|
||||||
// create group
|
|
||||||
|
|
||||||
if (!PNODE->pParent) {
|
|
||||||
Debug::log(LOG, "Rejecting to group a solitary window");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PNODE->groupHead = true;
|
|
||||||
|
|
||||||
std::deque<SDwindleNodeData*> newGroupMembers;
|
|
||||||
std::deque<SDwindleNodeData*> nodesToRemove;
|
|
||||||
|
|
||||||
newGroupMembers.emplace_back(PNODE);
|
|
||||||
|
|
||||||
addToDequeRecursive(&newGroupMembers, &nodesToRemove, PNODE->pParent->children[0] == PNODE ? PNODE->pParent->children[1] : PNODE->pParent->children[0]);
|
|
||||||
|
|
||||||
for (auto& n : newGroupMembers) {
|
|
||||||
if (n->isGroupMember()) {
|
|
||||||
Debug::log(LOG, "Rejecting to nest groups");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& nd : nodesToRemove) {
|
|
||||||
m_lDwindleNodesData.remove(*nd);
|
|
||||||
}
|
|
||||||
|
|
||||||
PNODE->position = PNODE->pParent->position;
|
|
||||||
PNODE->size = PNODE->pParent->size;
|
|
||||||
|
|
||||||
applyNodeDataToWindow(PNODE);
|
|
||||||
|
|
||||||
if (PNODE->pParent->pParent) {
|
|
||||||
if (PNODE->pParent->pParent->children[0] == PNODE->pParent) {
|
|
||||||
PNODE->pParent->pParent->children[0] = PNODE;
|
|
||||||
} else {
|
|
||||||
PNODE->pParent->pParent->children[1] = PNODE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto PPARENT2 = PNODE->pParent->pParent;
|
|
||||||
|
|
||||||
m_lDwindleNodesData.remove(*PNODE->pParent);
|
|
||||||
|
|
||||||
PNODE->pParent = PPARENT2;
|
|
||||||
|
|
||||||
// now remove everyone but head from tree
|
|
||||||
// and set order
|
|
||||||
for (int i = 0; i < (int)newGroupMembers.size(); ++i) {
|
|
||||||
if (i != 0) {
|
|
||||||
newGroupMembers[i]->groupHead = false;
|
|
||||||
newGroupMembers[i]->pParent = PNODE->pParent;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto PREVMEMBER = i == 0 ? newGroupMembers[newGroupMembers.size() - 1] : newGroupMembers[i - 1];
|
|
||||||
const auto NEXTMEMBER = i == (int)newGroupMembers.size() - 1 ? newGroupMembers[0] : newGroupMembers[i + 1];
|
|
||||||
|
|
||||||
newGroupMembers[i]->pPreviousGroupMember = PREVMEMBER;
|
|
||||||
newGroupMembers[i]->pNextGroupMember = NEXTMEMBER;
|
|
||||||
|
|
||||||
// add the deco
|
|
||||||
newGroupMembers[i]->pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(newGroupMembers[i]->pWindow));
|
|
||||||
}
|
|
||||||
|
|
||||||
// focus
|
|
||||||
PNODE->setGroupFocusedNode(PNODE);
|
|
||||||
|
|
||||||
// required for no_gaps_when_only to work
|
|
||||||
applyNodeDataToWindow(PNODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
|
||||||
|
|
||||||
g_pInputManager->refocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::deque<CWindow*> CHyprDwindleLayout::getGroupMembers(CWindow* pWindow) {
|
|
||||||
|
|
||||||
std::deque<CWindow*> result;
|
|
||||||
|
|
||||||
if (!g_pCompositor->windowExists(pWindow))
|
|
||||||
return result; // reject with empty
|
|
||||||
|
|
||||||
// get the node
|
|
||||||
const auto PNODE = getNodeFromWindow(pWindow);
|
|
||||||
|
|
||||||
if (!PNODE || !PNODE->isGroupMember())
|
|
||||||
return result; // reject with empty
|
|
||||||
|
|
||||||
const auto HEAD = PNODE->getGroupHead();
|
|
||||||
SDwindleNodeData* current = HEAD->pNextGroupMember;
|
|
||||||
|
|
||||||
result.push_back(HEAD->pWindow);
|
|
||||||
|
|
||||||
while (current != HEAD) {
|
|
||||||
result.push_back(current->pWindow);
|
|
||||||
current = current->pNextGroupMember;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHyprDwindleLayout::switchGroupWindow(CWindow* pWindow, bool forward, CWindow* forceTo) {
|
|
||||||
if (!g_pCompositor->windowValidMapped(pWindow))
|
|
||||||
return; // reject
|
|
||||||
|
|
||||||
const auto PNODE = getNodeFromWindow(pWindow);
|
|
||||||
|
|
||||||
if (!PNODE || !PNODE->isGroupMember())
|
|
||||||
return; // reject
|
|
||||||
|
|
||||||
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PNODE->workspaceID);
|
|
||||||
|
|
||||||
SDwindleNodeData* pNewNode;
|
|
||||||
|
|
||||||
if (forward)
|
|
||||||
pNewNode = PNODE->pNextGroupMember;
|
|
||||||
else
|
|
||||||
pNewNode = PNODE->pPreviousGroupMember;
|
|
||||||
|
|
||||||
if (forceTo) {
|
|
||||||
const auto NODETO = getNodeFromWindow(forceTo);
|
|
||||||
|
|
||||||
if (NODETO)
|
|
||||||
pNewNode = NODETO;
|
|
||||||
}
|
|
||||||
|
|
||||||
PNODE->setGroupFocusedNode(pNewNode);
|
|
||||||
|
|
||||||
pNewNode->position = PNODE->position;
|
|
||||||
pNewNode->size = PNODE->size;
|
|
||||||
pNewNode->workspaceID = PNODE->workspaceID;
|
|
||||||
|
|
||||||
applyNodeDataToWindow(pNewNode);
|
|
||||||
|
|
||||||
pNewNode->pWindow->m_vRealSize.warp();
|
|
||||||
pNewNode->pWindow->m_vRealPosition.warp();
|
|
||||||
|
|
||||||
g_pCompositor->focusWindow(pNewNode->pWindow);
|
|
||||||
|
|
||||||
pNewNode->pWindow->m_bIsFloating = PNODE->pWindow->m_bIsFloating;
|
|
||||||
|
|
||||||
if (PNODE->pWindow->m_bIsFullscreen) {
|
|
||||||
PNODE->pWindow->setHidden(false);
|
|
||||||
g_pCompositor->setWindowFullscreen(PNODE->pWindow, false, PWORKSPACE->m_efFullscreenMode);
|
|
||||||
PNODE->pWindow->setHidden(true);
|
|
||||||
g_pCompositor->setWindowFullscreen(pNewNode->pWindow, true, PWORKSPACE->m_efFullscreenMode);
|
|
||||||
|
|
||||||
pNewNode->pWindow->m_vRealSize.warp();
|
|
||||||
pNewNode->pWindow->m_vRealPosition.warp();
|
|
||||||
}
|
|
||||||
|
|
||||||
pNewNode->pWindow->updateWindowDecos();
|
|
||||||
PNODE->pWindow->updateWindowDecos();
|
|
||||||
|
|
||||||
g_pHyprRenderer->damageMonitor(g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID));
|
|
||||||
}
|
|
||||||
|
|
||||||
SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow) {
|
SWindowRenderLayoutHints CHyprDwindleLayout::requestRenderHints(CWindow* pWindow) {
|
||||||
// window should be valid, insallah
|
// window should be valid, insallah
|
||||||
|
|
||||||
SWindowRenderLayoutHints hints;
|
SWindowRenderLayoutHints hints;
|
||||||
|
|
||||||
static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border_active")->data;
|
|
||||||
static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border")->data;
|
|
||||||
|
|
||||||
const auto PNODE = getNodeFromWindow(pWindow);
|
const auto PNODE = getNodeFromWindow(pWindow);
|
||||||
if (!PNODE)
|
if (!PNODE)
|
||||||
return hints; // left for the future, maybe floating funkiness
|
return hints; // left for the future, maybe floating funkiness
|
||||||
|
|
||||||
if (PNODE->isGroupMember()) {
|
|
||||||
hints.isBorderGradient = true;
|
|
||||||
|
|
||||||
if (pWindow == g_pCompositor->m_pLastWindow)
|
|
||||||
hints.borderGradient = (CGradientValueData*)PGROUPCOLACTIVE->get();
|
|
||||||
else
|
|
||||||
hints.borderGradient = (CGradientValueData*)PGROUPCOLINACTIVE->get();
|
|
||||||
}
|
|
||||||
|
|
||||||
return hints;
|
return hints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1081,65 +707,9 @@ void CHyprDwindleLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
||||||
SDwindleNodeData* ACTIVE1 = nullptr;
|
SDwindleNodeData* ACTIVE1 = nullptr;
|
||||||
SDwindleNodeData* ACTIVE2 = nullptr;
|
SDwindleNodeData* ACTIVE2 = nullptr;
|
||||||
|
|
||||||
if (PNODE2->isGroupMember() || PNODE->isGroupMember()) {
|
// swap the windows and recalc
|
||||||
|
PNODE2->pWindow = pWindow;
|
||||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
PNODE->pWindow = pWindow2;
|
||||||
Debug::log(ERR, "Groups are confined to a monitor");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PNODE->isGroupMember()) {
|
|
||||||
ACTIVE1 = PNODE;
|
|
||||||
PNODE = PNODE->getGroupHead();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PNODE2->isGroupMember()) {
|
|
||||||
ACTIVE2 = PNODE2;
|
|
||||||
PNODE2 = PNODE2->getGroupHead();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PNODE2->pParent == PNODE->pParent) {
|
|
||||||
const auto PPARENT = PNODE->pParent;
|
|
||||||
|
|
||||||
if (PPARENT->children[0] == PNODE) {
|
|
||||||
PPARENT->children[0] = PNODE2;
|
|
||||||
PPARENT->children[1] = PNODE;
|
|
||||||
} else {
|
|
||||||
PPARENT->children[0] = PNODE;
|
|
||||||
PPARENT->children[1] = PNODE2;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (PNODE->pParent) {
|
|
||||||
const auto PPARENT = PNODE->pParent;
|
|
||||||
|
|
||||||
if (PPARENT->children[0] == PNODE) {
|
|
||||||
PPARENT->children[0] = PNODE2;
|
|
||||||
} else {
|
|
||||||
PPARENT->children[1] = PNODE2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PNODE2->pParent) {
|
|
||||||
const auto PPARENT = PNODE2->pParent;
|
|
||||||
|
|
||||||
if (PPARENT->children[0] == PNODE2) {
|
|
||||||
PPARENT->children[0] = PNODE;
|
|
||||||
} else {
|
|
||||||
PPARENT->children[1] = PNODE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto PPARENTNODE2 = PNODE2->pParent;
|
|
||||||
PNODE2->pParent = PNODE->pParent;
|
|
||||||
PNODE->pParent = PPARENTNODE2;
|
|
||||||
|
|
||||||
std::swap(PNODE2->workspaceID, PNODE->workspaceID);
|
|
||||||
} else {
|
|
||||||
// swap the windows and recalc
|
|
||||||
PNODE2->pWindow = pWindow;
|
|
||||||
PNODE->pWindow = pWindow2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
||||||
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
|
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
|
||||||
|
@ -1176,7 +746,7 @@ void CHyprDwindleLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exa
|
||||||
|
|
||||||
const auto PNODE = getNodeFromWindow(pWindow);
|
const auto PNODE = getNodeFromWindow(pWindow);
|
||||||
|
|
||||||
if (!PNODE || !PNODE->pParent || (PNODE->isGroupMember() && PNODE->getGroupMemberCount() == g_pCompositor->getWindowsOnWorkspace(PNODE->workspaceID)))
|
if (!PNODE || !PNODE->pParent)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
float newRatio = exact ? ratio : PNODE->pParent->splitRatio + ratio;
|
float newRatio = exact ? ratio : PNODE->pParent->splitRatio + ratio;
|
||||||
|
@ -1186,18 +756,8 @@ void CHyprDwindleLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exa
|
||||||
}
|
}
|
||||||
|
|
||||||
std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
std::any CHyprDwindleLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
||||||
if (message == "togglegroup")
|
if (message == "togglesplit")
|
||||||
toggleWindowGroup(header.pWindow);
|
|
||||||
else if (message == "changegroupactivef")
|
|
||||||
switchGroupWindow(header.pWindow, true);
|
|
||||||
else if (message == "changegroupactiveb")
|
|
||||||
switchGroupWindow(header.pWindow, false);
|
|
||||||
else if (message == "togglesplit")
|
|
||||||
toggleSplit(header.pWindow);
|
toggleSplit(header.pWindow);
|
||||||
else if (message == "groupinfo") {
|
|
||||||
auto res = getGroupMembers(header.pWindow ? header.pWindow : g_pCompositor->m_pLastWindow);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -1213,6 +773,17 @@ void CHyprDwindleLayout::toggleSplit(CWindow* pWindow) {
|
||||||
PNODE->pParent->recalcSizePosRecursive();
|
PNODE->pParent->recalcSizePosRecursive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprDwindleLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
|
||||||
|
const auto PNODE = getNodeFromWindow(from);
|
||||||
|
|
||||||
|
if (!PNODE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PNODE->pWindow = to;
|
||||||
|
|
||||||
|
applyNodeDataToWindow(PNODE, true);
|
||||||
|
}
|
||||||
|
|
||||||
std::string CHyprDwindleLayout::getLayoutName() {
|
std::string CHyprDwindleLayout::getLayoutName() {
|
||||||
return "dwindle";
|
return "dwindle";
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,6 @@ struct SDwindleNodeData {
|
||||||
|
|
||||||
bool splitTop = false; // for preserve_split
|
bool splitTop = false; // for preserve_split
|
||||||
|
|
||||||
bool groupHead = false;
|
|
||||||
SDwindleNodeData* pNextGroupMember = nullptr;
|
|
||||||
SDwindleNodeData* pPreviousGroupMember = nullptr;
|
|
||||||
|
|
||||||
Vector2D position;
|
Vector2D position;
|
||||||
Vector2D size;
|
Vector2D size;
|
||||||
|
|
||||||
|
@ -40,11 +36,6 @@ struct SDwindleNodeData {
|
||||||
|
|
||||||
void recalcSizePosRecursive(bool force = false);
|
void recalcSizePosRecursive(bool force = false);
|
||||||
void getAllChildrenRecursive(std::deque<SDwindleNodeData*>*);
|
void getAllChildrenRecursive(std::deque<SDwindleNodeData*>*);
|
||||||
bool isGroupMember();
|
|
||||||
SDwindleNodeData* getGroupHead();
|
|
||||||
SDwindleNodeData* getGroupVisible();
|
|
||||||
int getGroupMemberCount();
|
|
||||||
void setGroupFocusedNode(SDwindleNodeData*);
|
|
||||||
CHyprDwindleLayout* layout = nullptr;
|
CHyprDwindleLayout* layout = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -62,6 +53,7 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||||
virtual void switchWindows(CWindow*, CWindow*);
|
virtual void switchWindows(CWindow*, CWindow*);
|
||||||
virtual void alterSplitRatio(CWindow*, float, bool);
|
virtual void alterSplitRatio(CWindow*, float, bool);
|
||||||
virtual std::string getLayoutName();
|
virtual std::string getLayoutName();
|
||||||
|
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
|
||||||
|
|
||||||
virtual void onEnable();
|
virtual void onEnable();
|
||||||
virtual void onDisable();
|
virtual void onDisable();
|
||||||
|
@ -75,10 +67,7 @@ class CHyprDwindleLayout : public IHyprLayout {
|
||||||
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
SDwindleNodeData* getFirstNodeOnWorkspace(const int&);
|
||||||
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
SDwindleNodeData* getMasterNodeOnWorkspace(const int&);
|
||||||
|
|
||||||
void toggleWindowGroup(CWindow*);
|
|
||||||
void switchGroupWindow(CWindow*, bool forward, CWindow* to = nullptr);
|
|
||||||
void toggleSplit(CWindow*);
|
void toggleSplit(CWindow*);
|
||||||
std::deque<CWindow*> getGroupMembers(CWindow*);
|
|
||||||
|
|
||||||
friend struct SDwindleNodeData;
|
friend struct SDwindleNodeData;
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,6 +24,36 @@ void IHyprLayout::onWindowRemoved(CWindow* pWindow) {
|
||||||
if (pWindow->m_bIsFullscreen)
|
if (pWindow->m_bIsFullscreen)
|
||||||
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
||||||
|
|
||||||
|
if (pWindow->m_sGroupData.pNextWindow) {
|
||||||
|
if (pWindow->m_sGroupData.pNextWindow == pWindow)
|
||||||
|
pWindow->m_sGroupData.pNextWindow = nullptr;
|
||||||
|
else {
|
||||||
|
// find last window and update
|
||||||
|
CWindow* curr = pWindow;
|
||||||
|
const auto CURRWASVISIBLE = curr->getGroupCurrent() == curr;
|
||||||
|
|
||||||
|
while (curr->m_sGroupData.pNextWindow != pWindow)
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
|
||||||
|
if (CURRWASVISIBLE)
|
||||||
|
curr->setGroupCurrent(curr);
|
||||||
|
|
||||||
|
curr->m_sGroupData.pNextWindow = pWindow->m_sGroupData.pNextWindow;
|
||||||
|
|
||||||
|
pWindow->m_sGroupData.pNextWindow = nullptr;
|
||||||
|
|
||||||
|
if (pWindow->m_sGroupData.head) {
|
||||||
|
pWindow->m_sGroupData.head = false;
|
||||||
|
curr->m_sGroupData.head = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pWindow == m_pLastTiledWindow)
|
||||||
|
m_pLastTiledWindow = nullptr;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pWindow->m_bIsFloating) {
|
if (pWindow->m_bIsFloating) {
|
||||||
onWindowRemovedFloating(pWindow);
|
onWindowRemovedFloating(pWindow);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -143,6 +143,11 @@ interface IHyprLayout {
|
||||||
*/
|
*/
|
||||||
virtual void onWindowFocusChange(CWindow*);
|
virtual void onWindowFocusChange(CWindow*);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Called for replacing any data a layout has for a new window
|
||||||
|
*/
|
||||||
|
virtual void replaceWindowDataWith(CWindow * from, CWindow * to) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector2D m_vBeginDragXY;
|
Vector2D m_vBeginDragXY;
|
||||||
Vector2D m_vLastDragXY;
|
Vector2D m_vLastDragXY;
|
||||||
|
|
|
@ -83,6 +83,20 @@ void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
||||||
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
|
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
|
||||||
float lastSplitPercent = 0.5f;
|
float lastSplitPercent = 0.5f;
|
||||||
|
|
||||||
|
auto OPENINGON = isWindowTiled(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_iWorkspaceID == pWindow->m_iWorkspaceID ?
|
||||||
|
getNodeFromWindow(g_pCompositor->m_pLastWindow) :
|
||||||
|
getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
||||||
|
|
||||||
|
if (OPENINGON && OPENINGON->pWindow->m_sGroupData.pNextWindow && OPENINGON != PNODE) {
|
||||||
|
m_lMasterNodesData.remove(*PNODE);
|
||||||
|
|
||||||
|
OPENINGON->pWindow->insertWindowToGroup(pWindow);
|
||||||
|
|
||||||
|
pWindow->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1) {
|
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1) {
|
||||||
for (auto& nd : m_lMasterNodesData) {
|
for (auto& nd : m_lMasterNodesData) {
|
||||||
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
||||||
|
@ -1011,6 +1025,17 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CHyprMasterLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
|
||||||
|
const auto PNODE = getNodeFromWindow(from);
|
||||||
|
|
||||||
|
if (!PNODE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PNODE->pWindow = to;
|
||||||
|
|
||||||
|
applyNodeDataToWindow(PNODE);
|
||||||
|
}
|
||||||
|
|
||||||
void CHyprMasterLayout::onEnable() {
|
void CHyprMasterLayout::onEnable() {
|
||||||
for (auto& w : g_pCompositor->m_vWindows) {
|
for (auto& w : g_pCompositor->m_vWindows) {
|
||||||
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->isHidden())
|
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->isHidden())
|
||||||
|
|
|
@ -58,6 +58,7 @@ class CHyprMasterLayout : public IHyprLayout {
|
||||||
virtual void switchWindows(CWindow*, CWindow*);
|
virtual void switchWindows(CWindow*, CWindow*);
|
||||||
virtual void alterSplitRatio(CWindow*, float, bool);
|
virtual void alterSplitRatio(CWindow*, float, bool);
|
||||||
virtual std::string getLayoutName();
|
virtual std::string getLayoutName();
|
||||||
|
virtual void replaceWindowDataWith(CWindow* from, CWindow* to);
|
||||||
|
|
||||||
virtual void onEnable();
|
virtual void onEnable();
|
||||||
virtual void onDisable();
|
virtual void onDisable();
|
||||||
|
|
|
@ -635,11 +635,25 @@ void CKeybindManager::toggleActiveFloating(std::string args) {
|
||||||
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID))
|
if (g_pCompositor->isWorkspaceSpecial(PWINDOW->m_iWorkspaceID))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PWINDOW->m_bIsFloating = !PWINDOW->m_bIsFloating;
|
if (PWINDOW->m_sGroupData.pNextWindow && PWINDOW->m_sGroupData.pNextWindow != PWINDOW) {
|
||||||
|
|
||||||
PWINDOW->updateDynamicRules();
|
const auto PCURRENT = PWINDOW->getGroupCurrent();
|
||||||
|
PCURRENT->m_bIsFloating = !PCURRENT->m_bIsFloating;
|
||||||
|
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PCURRENT);
|
||||||
|
|
||||||
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PWINDOW);
|
CWindow* curr = PCURRENT->m_sGroupData.pNextWindow;
|
||||||
|
while (curr != PCURRENT) {
|
||||||
|
curr->m_bIsFloating = PCURRENT->m_bIsFloating;
|
||||||
|
curr->updateDynamicRules();
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PWINDOW->m_bIsFloating = !PWINDOW->m_bIsFloating;
|
||||||
|
|
||||||
|
PWINDOW->updateDynamicRules();
|
||||||
|
|
||||||
|
g_pLayoutManager->getCurrentLayout()->changeWindowFloatingMode(PWINDOW);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::centerWindow(std::string args) {
|
void CKeybindManager::centerWindow(std::string args) {
|
||||||
|
@ -1246,18 +1260,63 @@ void CKeybindManager::moveActiveTo(std::string args) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::toggleGroup(std::string args) {
|
void CKeybindManager::toggleGroup(std::string args) {
|
||||||
SLayoutMessageHeader header;
|
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||||
header.pWindow = g_pCompositor->m_pLastWindow;
|
|
||||||
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "togglegroup");
|
if (!PWINDOW)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!PWINDOW->m_sGroupData.pNextWindow) {
|
||||||
|
PWINDOW->m_sGroupData.pNextWindow = PWINDOW;
|
||||||
|
PWINDOW->m_sGroupData.head = true;
|
||||||
|
|
||||||
|
PWINDOW->m_dWindowDecorations.emplace_back(std::make_unique<CHyprGroupBarDecoration>(PWINDOW));
|
||||||
|
|
||||||
|
PWINDOW->updateWindowDecos();
|
||||||
|
} else {
|
||||||
|
if (PWINDOW->m_sGroupData.pNextWindow == PWINDOW) {
|
||||||
|
PWINDOW->m_sGroupData.pNextWindow = nullptr;
|
||||||
|
PWINDOW->updateWindowDecos();
|
||||||
|
} else {
|
||||||
|
// enum all windows, remove their group state, readd to layout.
|
||||||
|
CWindow* curr = PWINDOW;
|
||||||
|
std::vector<CWindow*> members;
|
||||||
|
do {
|
||||||
|
const auto PLASTWIN = curr;
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
PLASTWIN->m_sGroupData.pNextWindow = nullptr;
|
||||||
|
curr->setHidden(false);
|
||||||
|
members.push_back(curr);
|
||||||
|
} while (curr != PWINDOW);
|
||||||
|
|
||||||
|
for (auto& w : members) {
|
||||||
|
if (w->m_sGroupData.head)
|
||||||
|
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(curr);
|
||||||
|
w->m_sGroupData.head = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& w : members) {
|
||||||
|
g_pLayoutManager->getCurrentLayout()->onWindowCreated(w);
|
||||||
|
w->updateWindowDecos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_pCompositor->updateAllWindowsAnimatedDecorationValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::changeGroupActive(std::string args) {
|
void CKeybindManager::changeGroupActive(std::string args) {
|
||||||
SLayoutMessageHeader header;
|
const auto PWINDOW = g_pCompositor->m_pLastWindow;
|
||||||
header.pWindow = g_pCompositor->m_pLastWindow;
|
|
||||||
if (args == "b")
|
if (!PWINDOW)
|
||||||
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactiveb");
|
return;
|
||||||
else
|
|
||||||
g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "changegroupactivef");
|
if (!PWINDOW->m_sGroupData.pNextWindow)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (PWINDOW->m_sGroupData.pNextWindow == PWINDOW)
|
||||||
|
return;
|
||||||
|
|
||||||
|
PWINDOW->setGroupCurrent(PWINDOW->m_sGroupData.pNextWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKeybindManager::toggleSplit(std::string args) {
|
void CKeybindManager::toggleSplit(std::string args) {
|
||||||
|
|
|
@ -33,24 +33,29 @@ void CHyprGroupBarDecoration::updateWindow(CWindow* pWindow) {
|
||||||
m_vLastWindowSize = pWindow->m_vRealSize.vec();
|
m_vLastWindowSize = pWindow->m_vRealSize.vec();
|
||||||
}
|
}
|
||||||
|
|
||||||
// let's check if the window group is different.
|
if (!m_pWindow->m_sGroupData.pNextWindow) {
|
||||||
|
|
||||||
if (g_pLayoutManager->getCurrentLayout()->getLayoutName() != "dwindle") {
|
|
||||||
// ????
|
|
||||||
m_pWindow->m_vDecosToRemove.push_back(this);
|
m_pWindow->m_vDecosToRemove.push_back(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the group info
|
m_dwGroupMembers.clear();
|
||||||
SLayoutMessageHeader header;
|
CWindow* curr = pWindow;
|
||||||
header.pWindow = m_pWindow;
|
CWindow* head = nullptr;
|
||||||
|
while (!curr->m_sGroupData.head) {
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
}
|
||||||
|
|
||||||
m_dwGroupMembers = std::any_cast<std::deque<CWindow*>>(g_pLayoutManager->getCurrentLayout()->layoutMessage(header, "groupinfo"));
|
head = curr;
|
||||||
|
m_dwGroupMembers.push_back(curr);
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
while (curr != head) {
|
||||||
|
m_dwGroupMembers.push_back(curr);
|
||||||
|
curr = curr->m_sGroupData.pNextWindow;
|
||||||
|
}
|
||||||
|
|
||||||
damageEntire();
|
damageEntire();
|
||||||
|
|
||||||
if (m_dwGroupMembers.size() == 0) {
|
if (m_dwGroupMembers.size() == 0) {
|
||||||
// remove
|
|
||||||
m_pWindow->m_vDecosToRemove.push_back(this);
|
m_pWindow->m_vDecosToRemove.push_back(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -86,8 +91,8 @@ void CHyprGroupBarDecoration::draw(CMonitor* pMonitor, float a, const Vector2D&
|
||||||
|
|
||||||
scaleBox(&rect, pMonitor->scale);
|
scaleBox(&rect, pMonitor->scale);
|
||||||
|
|
||||||
static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border_active")->data;
|
static auto* const PGROUPCOLACTIVE = &g_pConfigManager->getConfigValuePtr("general:col.group_border_active")->data;
|
||||||
static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("dwindle:col.group_border")->data;
|
static auto* const PGROUPCOLINACTIVE = &g_pConfigManager->getConfigValuePtr("general:col.group_border")->data;
|
||||||
|
|
||||||
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? ((CGradientValueData*)PGROUPCOLACTIVE->get())->m_vColors[0] :
|
CColor color = m_dwGroupMembers[i] == g_pCompositor->m_pLastWindow ? ((CGradientValueData*)PGROUPCOLACTIVE->get())->m_vColors[0] :
|
||||||
((CGradientValueData*)PGROUPCOLINACTIVE->get())->m_vColors[0];
|
((CGradientValueData*)PGROUPCOLINACTIVE->get())->m_vColors[0];
|
||||||
|
|
Loading…
Reference in a new issue