2022-07-16 15:57:31 +02:00
|
|
|
#include "MasterLayout.hpp"
|
|
|
|
#include "../Compositor.hpp"
|
|
|
|
|
|
|
|
SMasterNodeData* CHyprMasterLayout::getNodeFromWindow(CWindow* pWindow) {
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
|
|
|
if (nd.pWindow == pWindow)
|
|
|
|
return &nd;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CHyprMasterLayout::getNodesOnWorkspace(const int& ws) {
|
|
|
|
int no = 0;
|
|
|
|
for (auto& n : m_lMasterNodesData) {
|
|
|
|
if (n.workspaceID == ws)
|
|
|
|
no++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
2022-11-08 13:39:52 +01:00
|
|
|
int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) {
|
|
|
|
int no = 0;
|
|
|
|
for (auto& n : m_lMasterNodesData) {
|
|
|
|
if (n.workspaceID == ws && n.isMaster)
|
|
|
|
no++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return no;
|
|
|
|
}
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
std::string CHyprMasterLayout::getLayoutName() {
|
|
|
|
return "Master";
|
|
|
|
}
|
|
|
|
|
|
|
|
SMasterNodeData* CHyprMasterLayout::getMasterNodeOnWorkspace(const int& ws) {
|
|
|
|
for (auto& n : m_lMasterNodesData) {
|
|
|
|
if (n.isMaster && n.workspaceID == ws)
|
|
|
|
return &n;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow) {
|
|
|
|
if (pWindow->m_bIsFloating)
|
|
|
|
return;
|
|
|
|
|
2022-07-16 23:24:42 +02:00
|
|
|
static auto *const PNEWTOP = &g_pConfigManager->getConfigValuePtr("master:new_on_top")->intValue;
|
|
|
|
|
2022-08-05 18:10:59 +02:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
|
|
|
|
2022-07-16 23:24:42 +02:00
|
|
|
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
PNODE->workspaceID = pWindow->m_iWorkspaceID;
|
|
|
|
PNODE->pWindow = pWindow;
|
|
|
|
|
|
|
|
static auto *const PNEWISMASTER = &g_pConfigManager->getConfigValuePtr("master:new_is_master")->intValue;
|
|
|
|
|
|
|
|
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
|
|
|
|
float lastSplitPercent = 0.5f;
|
|
|
|
|
|
|
|
if (*PNEWISMASTER || WINDOWSONWORKSPACE == 1) {
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
|
|
|
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
|
|
|
nd.isMaster = false;
|
|
|
|
lastSplitPercent = nd.percMaster;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
PNODE->isMaster = true;
|
|
|
|
PNODE->percMaster = lastSplitPercent;
|
2022-08-05 18:10:59 +02:00
|
|
|
|
|
|
|
// first, check if it isn't too big.
|
|
|
|
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PMONITOR->vecSize.x * lastSplitPercent || MAXSIZE.y < PMONITOR->vecSize.y) {
|
|
|
|
// we can't continue. make it floating.
|
|
|
|
pWindow->m_bIsFloating = true;
|
|
|
|
m_lMasterNodesData.remove(*PNODE);
|
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(pWindow);
|
|
|
|
return;
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
} else {
|
|
|
|
PNODE->isMaster = false;
|
2022-08-05 18:10:59 +02:00
|
|
|
|
|
|
|
// first, check if it isn't too big.
|
|
|
|
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow); MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) {
|
|
|
|
// we can't continue. make it floating.
|
|
|
|
pWindow->m_bIsFloating = true;
|
|
|
|
m_lMasterNodesData.remove(*PNODE);
|
|
|
|
g_pLayoutManager->getCurrentLayout()->onWindowCreatedFloating(pWindow);
|
|
|
|
return;
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
2022-09-20 10:55:25 +02:00
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
|
|
|
|
|
|
|
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
|
|
|
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
|
|
|
g_pCompositor->setWindowFullscreen(PFULLWINDOW, false, FULLSCREEN_FULL);
|
|
|
|
}
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
// recalc
|
|
|
|
recalculateMonitor(pWindow->m_iMonitorID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
|
|
|
const auto PNODE = getNodeFromWindow(pWindow);
|
|
|
|
|
|
|
|
if (!PNODE)
|
|
|
|
return;
|
|
|
|
|
2022-09-20 10:55:25 +02:00
|
|
|
if (pWindow->m_bIsFullscreen)
|
|
|
|
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
|
|
|
|
2022-11-08 13:39:52 +01:00
|
|
|
const auto MASTERSLEFT = getMastersOnWorkspace(PNODE->workspaceID);
|
|
|
|
|
|
|
|
if (PNODE->isMaster && MASTERSLEFT < 2) {
|
2022-07-16 15:57:31 +02:00
|
|
|
// find new one
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
|
|
|
if (!nd.isMaster) {
|
|
|
|
nd.isMaster = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_lMasterNodesData.remove(*PNODE);
|
|
|
|
|
2022-11-08 13:39:52 +01:00
|
|
|
if (getMastersOnWorkspace(PNODE->workspaceID) == getNodesOnWorkspace(PNODE->workspaceID) && MASTERSLEFT > 1) {
|
|
|
|
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
|
|
|
|
if (it->workspaceID == PNODE->workspaceID) {
|
|
|
|
it->isMaster = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
recalculateMonitor(pWindow->m_iMonitorID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::recalculateMonitor(const int& monid) {
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(PMONITOR->activeWorkspace);
|
|
|
|
|
|
|
|
if (!PWORKSPACE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_pHyprRenderer->damageMonitor(PMONITOR);
|
|
|
|
|
|
|
|
if (PMONITOR->specialWorkspaceOpen) {
|
|
|
|
calculateWorkspace(SPECIAL_WORKSPACE_ID);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PWORKSPACE->m_bHasFullscreenWindow) {
|
2022-09-25 12:42:39 +02:00
|
|
|
if (PWORKSPACE->m_efFullscreenMode == FULLSCREEN_FULL)
|
2022-07-16 15:57:31 +02:00
|
|
|
return;
|
|
|
|
|
|
|
|
// massive hack from the fullscreen func
|
|
|
|
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(PWORKSPACE->m_iID);
|
|
|
|
|
|
|
|
SMasterNodeData fakeNode;
|
|
|
|
fakeNode.pWindow = PFULLWINDOW;
|
|
|
|
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
|
|
|
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
|
|
|
fakeNode.workspaceID = PWORKSPACE->m_iID;
|
|
|
|
PFULLWINDOW->m_vPosition = fakeNode.position;
|
|
|
|
PFULLWINDOW->m_vSize = fakeNode.size;
|
|
|
|
|
|
|
|
applyNodeDataToWindow(&fakeNode);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// calc the WS
|
|
|
|
calculateWorkspace(PWORKSPACE->m_iID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::calculateWorkspace(const int& ws) {
|
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(ws);
|
|
|
|
|
|
|
|
if (!PWORKSPACE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID);
|
|
|
|
|
|
|
|
const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID);
|
|
|
|
|
|
|
|
if (!PMASTERNODE)
|
|
|
|
return;
|
|
|
|
|
2022-11-08 13:39:52 +01:00
|
|
|
const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID);
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
if (getNodesOnWorkspace(PWORKSPACE->m_iID) < 2) {
|
|
|
|
PMASTERNODE->position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition;
|
|
|
|
PMASTERNODE->size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x, PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y);
|
|
|
|
applyNodeDataToWindow(PMASTERNODE);
|
|
|
|
return;
|
|
|
|
} else {
|
2022-11-10 13:05:22 +01:00
|
|
|
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
|
|
|
|
int nodesLeft = MASTERS;
|
|
|
|
float nextY = 0;
|
2022-11-08 13:39:52 +01:00
|
|
|
|
|
|
|
for (auto& n : m_lMasterNodesData) {
|
|
|
|
if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) {
|
2022-11-10 13:05:22 +01:00
|
|
|
n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY);
|
|
|
|
float HEIGHT = nodesLeft > 1 ? heightLeft / nodesLeft * n.percSize : heightLeft;
|
|
|
|
if (HEIGHT > heightLeft * 0.9f && nodesLeft > 1)
|
|
|
|
HEIGHT = heightLeft * 0.9f;
|
|
|
|
n.size = Vector2D((PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster, HEIGHT);
|
2022-11-08 13:39:52 +01:00
|
|
|
|
2022-11-10 13:05:22 +01:00
|
|
|
nodesLeft--;
|
|
|
|
heightLeft -= HEIGHT;
|
|
|
|
nextY += HEIGHT;
|
2022-11-08 13:39:52 +01:00
|
|
|
|
|
|
|
applyNodeDataToWindow(&n);
|
|
|
|
}
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
2022-11-10 13:05:22 +01:00
|
|
|
float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y;
|
|
|
|
int slavesLeft = getNodesOnWorkspace(PWORKSPACE->m_iID) - MASTERS;
|
|
|
|
float nextY = 0;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
2022-11-08 13:39:52 +01:00
|
|
|
if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster)
|
2022-07-16 15:57:31 +02:00
|
|
|
continue;
|
|
|
|
|
2022-11-10 20:39:16 +01:00
|
|
|
nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMASTERNODE->percMaster * PMONITOR->vecSize.x, nextY);
|
2022-11-10 13:05:22 +01:00
|
|
|
float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft;
|
|
|
|
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
|
|
|
HEIGHT = heightLeft * 0.9f;
|
|
|
|
nd.size = Vector2D(PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x, HEIGHT);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-11-10 13:05:22 +01:00
|
|
|
slavesLeft--;
|
|
|
|
heightLeft -= HEIGHT;
|
|
|
|
nextY += HEIGHT;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
applyNodeDataToWindow(&nd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
2022-07-27 12:32:00 +02:00
|
|
|
CMonitor* PMONITOR = nullptr;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
if (pNode->workspaceID == SPECIAL_WORKSPACE_ID) {
|
|
|
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
|
|
|
if (m->specialWorkspaceOpen) {
|
|
|
|
PMONITOR = m.get();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PMONITOR) {
|
|
|
|
Debug::log(ERR, "Orphaned Node %x (workspace ID: %i)!!", pNode, pNode->workspaceID);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// for gaps outer
|
|
|
|
const bool DISPLAYLEFT = STICKS(pNode->position.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
|
|
|
const bool DISPLAYRIGHT = STICKS(pNode->position.x + pNode->size.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
|
|
|
|
const bool DISPLAYTOP = STICKS(pNode->position.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
|
|
|
const bool DISPLAYBOTTOM = STICKS(pNode->position.y + pNode->size.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
|
|
|
|
2022-09-03 22:49:45 +02:00
|
|
|
const auto PBORDERSIZE = &g_pConfigManager->getConfigValuePtr("general:border_size")->intValue;
|
|
|
|
const auto PGAPSIN = &g_pConfigManager->getConfigValuePtr("general:gaps_in")->intValue;
|
|
|
|
const auto PGAPSOUT = &g_pConfigManager->getConfigValuePtr("general:gaps_out")->intValue;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
const auto PWINDOW = pNode->pWindow;
|
|
|
|
|
|
|
|
if (!g_pCompositor->windowValidMapped(PWINDOW)) {
|
|
|
|
Debug::log(ERR, "Node %x holding invalid window %x!!", pNode, PWINDOW);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-08-01 12:57:37 +02:00
|
|
|
static auto *const PNOGAPSWHENONLY = &g_pConfigManager->getConfigValuePtr("master:no_gaps_when_only")->intValue;
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
PWINDOW->m_vSize = pNode->size;
|
|
|
|
PWINDOW->m_vPosition = pNode->position;
|
|
|
|
|
2022-09-26 17:38:08 +02:00
|
|
|
auto calcPos = PWINDOW->m_vPosition + Vector2D(*PBORDERSIZE, *PBORDERSIZE);
|
|
|
|
auto calcSize = PWINDOW->m_vSize - Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-08-01 12:57:37 +02:00
|
|
|
if (*PNOGAPSWHENONLY && PWINDOW->m_iWorkspaceID != SPECIAL_WORKSPACE_ID && getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) == 1) {
|
2022-09-26 17:38:08 +02:00
|
|
|
PWINDOW->m_vRealPosition = calcPos - Vector2D(*PBORDERSIZE, *PBORDERSIZE);
|
|
|
|
PWINDOW->m_vRealSize = calcSize + Vector2D(2 * *PBORDERSIZE, 2 * *PBORDERSIZE);
|
2022-08-01 12:57:37 +02:00
|
|
|
|
|
|
|
PWINDOW->updateWindowDecos();
|
|
|
|
|
|
|
|
PWINDOW->m_sSpecialRenderData.rounding = false;
|
2022-08-16 16:19:52 +02:00
|
|
|
PWINDOW->m_sSpecialRenderData.border = false;
|
2022-09-23 17:47:58 +02:00
|
|
|
PWINDOW->m_sSpecialRenderData.decorate = false;
|
2022-08-01 12:57:37 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
PWINDOW->m_sSpecialRenderData.rounding = true;
|
2022-08-16 16:19:52 +02:00
|
|
|
PWINDOW->m_sSpecialRenderData.border = true;
|
2022-09-23 17:47:58 +02:00
|
|
|
PWINDOW->m_sSpecialRenderData.decorate = true;
|
2022-08-01 12:57:37 +02:00
|
|
|
|
2022-09-03 22:49:45 +02:00
|
|
|
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? *PGAPSOUT : *PGAPSIN,
|
|
|
|
DISPLAYTOP ? *PGAPSOUT : *PGAPSIN);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-09-03 22:49:45 +02:00
|
|
|
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? *PGAPSOUT : *PGAPSIN,
|
|
|
|
DISPLAYBOTTOM ? *PGAPSOUT : *PGAPSIN);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
calcPos = calcPos + OFFSETTOPLEFT;
|
|
|
|
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
|
|
|
|
|
|
|
if (PWINDOW->m_iWorkspaceID == SPECIAL_WORKSPACE_ID) {
|
|
|
|
static auto *const PSCALEFACTOR = &g_pConfigManager->getConfigValuePtr("master:special_scale_factor")->floatValue;
|
|
|
|
|
|
|
|
PWINDOW->m_vRealPosition = calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f;
|
|
|
|
PWINDOW->m_vRealSize = calcSize * *PSCALEFACTOR;
|
|
|
|
|
|
|
|
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize * *PSCALEFACTOR);
|
|
|
|
} else {
|
|
|
|
PWINDOW->m_vRealSize = calcSize;
|
|
|
|
PWINDOW->m_vRealPosition = calcPos;
|
|
|
|
|
|
|
|
g_pXWaylandManager->setWindowSize(PWINDOW, calcSize);
|
|
|
|
}
|
|
|
|
|
2022-08-03 12:27:20 +02:00
|
|
|
if (m_bForceWarps) {
|
2022-08-24 13:44:48 +02:00
|
|
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
|
|
|
|
2022-08-03 12:27:20 +02:00
|
|
|
PWINDOW->m_vRealPosition.warp();
|
|
|
|
PWINDOW->m_vRealSize.warp();
|
2022-08-23 15:08:15 +02:00
|
|
|
|
|
|
|
g_pHyprRenderer->damageWindow(PWINDOW);
|
2022-08-03 12:27:20 +02:00
|
|
|
}
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
PWINDOW->updateWindowDecos();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CHyprMasterLayout::isWindowTiled(CWindow* pWindow) {
|
|
|
|
return getNodeFromWindow(pWindow) != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, CWindow* pWindow) {
|
|
|
|
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
|
|
|
|
|
|
|
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto PNODE = getNodeFromWindow(PWINDOW);
|
|
|
|
|
|
|
|
if (!PNODE) {
|
2022-11-10 13:05:22 +01:00
|
|
|
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goalv() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goalv() + pixResize).y, 20.0));
|
2022-07-16 15:57:31 +02:00
|
|
|
PWINDOW->updateWindowDecos();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-11-10 13:05:22 +01:00
|
|
|
// get monitor
|
2022-07-16 15:57:31 +02:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
|
|
|
|
|
|
|
if (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) < 2)
|
|
|
|
return;
|
|
|
|
|
2022-08-03 12:27:20 +02:00
|
|
|
m_bForceWarps = true;
|
|
|
|
|
2022-11-10 13:05:22 +01:00
|
|
|
double delta = pixResize.x / PMONITOR->vecSize.x;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-11-10 13:05:22 +01:00
|
|
|
for (auto& n : m_lMasterNodesData) {
|
|
|
|
if (n.isMaster)
|
|
|
|
n.percMaster = std::clamp(n.percMaster + delta, 0.05, 0.95);
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-11-10 13:05:22 +01:00
|
|
|
// check the up/down resize
|
|
|
|
if (pixResize.y != 0) {
|
|
|
|
if (PNODE->isMaster && getMastersOnWorkspace(PNODE->workspaceID) > 1) {
|
|
|
|
// check master size
|
|
|
|
const auto SIZEY = (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getMastersOnWorkspace(PNODE->workspaceID);
|
|
|
|
PNODE->percSize = std::clamp(PNODE->percSize + pixResize.y / SIZEY, 0.05, 1.95);
|
|
|
|
} else if (!PNODE->isMaster && (getNodesOnWorkspace(PWINDOW->m_iWorkspaceID) - getMastersOnWorkspace(PNODE->workspaceID)) > 1) {
|
|
|
|
const auto SIZEY = (PMONITOR->vecSize.y - PMONITOR->vecReservedTopLeft.y - PMONITOR->vecReservedBottomRight.y) / getNodesOnWorkspace(PNODE->workspaceID);
|
|
|
|
PNODE->percSize = std::clamp(PNODE->percSize + pixResize.y / SIZEY, 0.05, 1.95);
|
|
|
|
}
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
recalculateMonitor(PMONITOR->ID);
|
2022-08-03 12:27:20 +02:00
|
|
|
|
|
|
|
m_bForceWarps = false;
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::fullscreenRequestForWindow(CWindow* pWindow, eFullscreenMode fullscreenMode, bool on) {
|
|
|
|
if (!g_pCompositor->windowValidMapped(pWindow))
|
|
|
|
return;
|
|
|
|
|
2022-09-17 16:07:03 +02:00
|
|
|
if (on == pWindow->m_bIsFullscreen || pWindow->m_iWorkspaceID == SPECIAL_WORKSPACE_ID)
|
2022-07-16 15:57:31 +02:00
|
|
|
return; // ignore
|
|
|
|
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
|
|
|
const auto PWORKSPACE = g_pCompositor->getWorkspaceByID(pWindow->m_iWorkspaceID);
|
|
|
|
|
|
|
|
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
|
|
|
// if the window wants to be fullscreen but there already is one,
|
|
|
|
// ignore the request.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// otherwise, accept it.
|
|
|
|
pWindow->m_bIsFullscreen = on;
|
|
|
|
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
|
|
|
|
2022-07-20 18:39:08 +02:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
if (!pWindow->m_bIsFullscreen) {
|
|
|
|
// if it got its fullscreen disabled, set back its node if it had one
|
|
|
|
const auto PNODE = getNodeFromWindow(pWindow);
|
|
|
|
if (PNODE)
|
|
|
|
applyNodeDataToWindow(PNODE);
|
|
|
|
else {
|
|
|
|
// get back its' dimensions from position and size
|
|
|
|
pWindow->m_vRealPosition = pWindow->m_vPosition;
|
|
|
|
pWindow->m_vRealSize = pWindow->m_vSize;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// if it now got fullscreen, make it fullscreen
|
|
|
|
|
|
|
|
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
|
|
|
|
|
|
|
// save position and size if floating
|
|
|
|
if (pWindow->m_bIsFloating) {
|
|
|
|
pWindow->m_vPosition = pWindow->m_vRealPosition.vec();
|
|
|
|
pWindow->m_vSize = pWindow->m_vRealSize.vec();
|
|
|
|
}
|
|
|
|
|
|
|
|
// apply new pos and size being monitors' box
|
|
|
|
if (fullscreenMode == FULLSCREEN_FULL) {
|
|
|
|
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
|
|
|
pWindow->m_vRealSize = PMONITOR->vecSize;
|
|
|
|
} else {
|
|
|
|
// This is a massive hack.
|
|
|
|
// We make a fake "only" node and apply
|
|
|
|
// To keep consistent with the settings without C+P code
|
|
|
|
|
|
|
|
SMasterNodeData fakeNode;
|
|
|
|
fakeNode.pWindow = pWindow;
|
|
|
|
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
|
|
|
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
|
|
|
fakeNode.workspaceID = pWindow->m_iWorkspaceID;
|
|
|
|
pWindow->m_vPosition = fakeNode.position;
|
|
|
|
pWindow->m_vSize = fakeNode.size;
|
|
|
|
|
|
|
|
applyNodeDataToWindow(&fakeNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
|
|
|
|
|
|
|
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goalv());
|
|
|
|
|
|
|
|
g_pCompositor->moveWindowToTop(pWindow);
|
|
|
|
|
|
|
|
recalculateMonitor(PMONITOR->ID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::recalculateWindow(CWindow* pWindow) {
|
|
|
|
const auto PNODE = getNodeFromWindow(pWindow);
|
|
|
|
|
|
|
|
if (!PNODE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
recalculateMonitor(pWindow->m_iMonitorID);
|
|
|
|
}
|
|
|
|
|
|
|
|
SWindowRenderLayoutHints CHyprMasterLayout::requestRenderHints(CWindow* pWindow) {
|
|
|
|
// window should be valid, insallah
|
|
|
|
|
|
|
|
SWindowRenderLayoutHints hints;
|
|
|
|
|
|
|
|
return hints; // master doesnt have any hints
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
|
|
|
// windows should be valid, insallah
|
|
|
|
|
|
|
|
const auto PNODE = getNodeFromWindow(pWindow);
|
|
|
|
const auto PNODE2 = getNodeFromWindow(pWindow2);
|
|
|
|
|
|
|
|
if (!PNODE2 || !PNODE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (PNODE->workspaceID != PNODE2->workspaceID) {
|
2022-09-14 17:30:16 +02:00
|
|
|
std::swap(pWindow2->m_iMonitorID, pWindow->m_iMonitorID);
|
|
|
|
std::swap(pWindow2->m_iWorkspaceID, pWindow->m_iWorkspaceID);
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// massive hack: just swap window pointers, lol
|
2022-09-14 17:30:16 +02:00
|
|
|
PNODE->pWindow = pWindow2;
|
|
|
|
PNODE2->pWindow = pWindow;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-09-14 17:30:16 +02:00
|
|
|
recalculateMonitor(pWindow->m_iMonitorID);
|
|
|
|
if (PNODE2->workspaceID != PNODE->workspaceID)
|
|
|
|
recalculateMonitor(pWindow2->m_iMonitorID);
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::alterSplitRatioBy(CWindow* pWindow, float ratio) {
|
|
|
|
// window should be valid, insallah
|
|
|
|
|
|
|
|
const auto PNODE = getNodeFromWindow(pWindow);
|
|
|
|
|
|
|
|
if (!PNODE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
|
|
|
|
|
|
|
PMASTER->percMaster = std::clamp(PMASTER->percMaster + ratio, 0.05f, 0.95f);
|
|
|
|
|
|
|
|
recalculateMonitor(pWindow->m_iMonitorID);
|
|
|
|
}
|
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
CWindow* CHyprMasterLayout::getNextWindow(CWindow* pWindow, bool next) {
|
|
|
|
if (!isWindowTiled(pWindow))
|
|
|
|
return nullptr;
|
2022-07-28 12:00:10 +02:00
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
const auto PNODE = getNodeFromWindow(pWindow);
|
2022-07-28 12:00:10 +02:00
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
if (next) {
|
2022-07-28 12:00:10 +02:00
|
|
|
if (PNODE->isMaster) {
|
|
|
|
// focus the first non master
|
|
|
|
for (auto n : m_lMasterNodesData) {
|
2022-08-24 21:50:48 +02:00
|
|
|
if (n.pWindow != pWindow && n.workspaceID == pWindow->m_iWorkspaceID) {
|
|
|
|
return n.pWindow;
|
2022-07-28 12:00:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// focus next
|
|
|
|
bool reached = false;
|
|
|
|
bool found = false;
|
|
|
|
for (auto n : m_lMasterNodesData) {
|
2022-08-24 21:50:48 +02:00
|
|
|
if (n.pWindow == pWindow) {
|
2022-07-28 12:00:10 +02:00
|
|
|
reached = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
if (n.workspaceID == pWindow->m_iWorkspaceID && reached) {
|
|
|
|
return n.pWindow;
|
2022-07-28 12:00:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
2022-08-24 21:50:48 +02:00
|
|
|
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
2022-07-28 12:00:10 +02:00
|
|
|
|
|
|
|
if (PMASTER)
|
2022-08-24 21:50:48 +02:00
|
|
|
return PMASTER->pWindow;
|
2022-07-28 12:00:10 +02:00
|
|
|
}
|
|
|
|
}
|
2022-08-24 21:50:48 +02:00
|
|
|
} else {
|
2022-07-28 12:00:10 +02:00
|
|
|
if (PNODE->isMaster) {
|
|
|
|
// focus the first non master
|
|
|
|
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
|
2022-08-24 21:50:48 +02:00
|
|
|
if (it->pWindow != pWindow && it->workspaceID == pWindow->m_iWorkspaceID) {
|
|
|
|
return it->pWindow;
|
2022-07-28 12:00:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// focus next
|
|
|
|
bool reached = false;
|
|
|
|
bool found = false;
|
|
|
|
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
|
2022-08-24 21:50:48 +02:00
|
|
|
if (it->pWindow == pWindow) {
|
2022-07-28 12:00:10 +02:00
|
|
|
reached = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
if (it->workspaceID == pWindow->m_iWorkspaceID && reached) {
|
|
|
|
return it->pWindow;
|
2022-07-28 12:00:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found) {
|
2022-08-24 21:50:48 +02:00
|
|
|
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->m_iWorkspaceID);
|
2022-07-28 12:00:10 +02:00
|
|
|
|
|
|
|
if (PMASTER)
|
2022-08-24 21:50:48 +02:00
|
|
|
return PMASTER->pWindow;
|
2022-07-28 12:00:10 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
|
|
|
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
|
|
|
|
if (!g_pCompositor->windowValidMapped(PWINDOWTOCHANGETO))
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
|
|
|
Vector2D middle = PWINDOWTOCHANGETO->m_vRealPosition.goalv() + PWINDOWTOCHANGETO->m_vRealSize.goalv() / 2.f;
|
|
|
|
wlr_cursor_warp(g_pCompositor->m_sWLRCursor, nullptr, middle.x, middle.y);
|
|
|
|
};
|
|
|
|
|
|
|
|
if (message == "swapwithmaster") {
|
|
|
|
const auto PWINDOW = header.pWindow;
|
|
|
|
|
2022-11-03 23:55:44 +01:00
|
|
|
if (!PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
if (!isWindowTiled(PWINDOW))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID);
|
|
|
|
|
|
|
|
if (!PMASTER || PMASTER->pWindow == PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switchWindows(PWINDOW, PMASTER->pWindow);
|
|
|
|
|
|
|
|
switchToWindow(PWINDOW);
|
|
|
|
|
2022-11-02 11:15:11 +01:00
|
|
|
return 0;
|
|
|
|
} else if (message == "focusmaster") {
|
|
|
|
const auto PWINDOW = header.pWindow;
|
2022-11-03 23:55:44 +01:00
|
|
|
|
|
|
|
if (!PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
2022-11-02 11:15:11 +01:00
|
|
|
const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->m_iWorkspaceID);
|
|
|
|
|
|
|
|
if (!PMASTER || PMASTER->pWindow == PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switchToWindow(PMASTER->pWindow);
|
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
return 0;
|
|
|
|
} else if (message == "cyclenext") {
|
|
|
|
const auto PWINDOW = header.pWindow;
|
|
|
|
|
2022-11-03 23:55:44 +01:00
|
|
|
if (!PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
switchToWindow(getNextWindow(PWINDOW, true));
|
|
|
|
} else if (message == "cycleprev") {
|
|
|
|
const auto PWINDOW = header.pWindow;
|
|
|
|
|
2022-11-03 23:55:44 +01:00
|
|
|
if (!PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
switchToWindow(getNextWindow(PWINDOW, false));
|
|
|
|
} else if (message == "swapnext") {
|
|
|
|
if (!g_pCompositor->windowValidMapped(header.pWindow))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (header.pWindow->m_bIsFloating) {
|
|
|
|
g_pKeybindManager->m_mDispatchers["swapnext"]("");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, true);
|
|
|
|
|
|
|
|
if (PWINDOWTOSWAPWITH) {
|
|
|
|
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
|
|
|
|
g_pCompositor->focusWindow(header.pWindow);
|
|
|
|
}
|
|
|
|
} else if (message == "swapprev") {
|
|
|
|
if (!g_pCompositor->windowValidMapped(header.pWindow))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (header.pWindow->m_bIsFloating) {
|
|
|
|
g_pKeybindManager->m_mDispatchers["swapnext"]("prev");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
const auto PWINDOWTOSWAPWITH = getNextWindow(header.pWindow, false);
|
|
|
|
|
|
|
|
if (PWINDOWTOSWAPWITH) {
|
|
|
|
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
|
|
|
|
g_pCompositor->focusWindow(header.pWindow);
|
|
|
|
}
|
2022-11-08 13:39:52 +01:00
|
|
|
} else if (message == "addmaster") {
|
|
|
|
if (!g_pCompositor->windowValidMapped(header.pWindow))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (header.pWindow->m_bIsFloating)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
const auto PNODE = getNodeFromWindow(header.pWindow);
|
|
|
|
|
|
|
|
const auto WINDOWS = getNodesOnWorkspace(header.pWindow->m_iWorkspaceID);
|
|
|
|
const auto MASTERS = getMastersOnWorkspace(header.pWindow->m_iWorkspaceID);
|
|
|
|
|
|
|
|
if (MASTERS + 2 > WINDOWS)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!PNODE || PNODE->isMaster) {
|
|
|
|
// first non-master node
|
|
|
|
for (auto& n : m_lMasterNodesData) {
|
|
|
|
if (n.workspaceID == header.pWindow->m_iWorkspaceID && !n.isMaster) {
|
|
|
|
n.isMaster = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PNODE->isMaster = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
recalculateMonitor(header.pWindow->m_iMonitorID);
|
|
|
|
|
|
|
|
} else if (message == "removemaster") {
|
|
|
|
|
|
|
|
if (!g_pCompositor->windowValidMapped(header.pWindow))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (header.pWindow->m_bIsFloating)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
const auto PNODE = getNodeFromWindow(header.pWindow);
|
|
|
|
|
|
|
|
const auto WINDOWS = getNodesOnWorkspace(header.pWindow->m_iWorkspaceID);
|
|
|
|
const auto MASTERS = getMastersOnWorkspace(header.pWindow->m_iWorkspaceID);
|
|
|
|
|
|
|
|
if (WINDOWS < 2 || MASTERS < 2)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!PNODE || !PNODE->isMaster) {
|
|
|
|
// first non-master node
|
|
|
|
for (auto it = m_lMasterNodesData.rbegin(); it != m_lMasterNodesData.rend(); it++) {
|
|
|
|
if (it->workspaceID == header.pWindow->m_iWorkspaceID && it->isMaster) {
|
|
|
|
it->isMaster = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PNODE->isMaster = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
recalculateMonitor(header.pWindow->m_iMonitorID);
|
2022-08-24 21:50:48 +02:00
|
|
|
}
|
|
|
|
|
2022-07-28 12:00:10 +02:00
|
|
|
return 0;
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::onEnable() {
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2022-10-14 21:46:32 +02:00
|
|
|
if (w->m_bIsFloating || !w->m_bMappedX11 || !w->m_bIsMapped || w->isHidden())
|
2022-07-16 15:57:31 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
onWindowCreatedTiling(w.get());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::onDisable() {
|
|
|
|
m_lMasterNodesData.clear();
|
2022-09-25 12:42:39 +02:00
|
|
|
}
|