2022-07-16 15:57:31 +02:00
|
|
|
#include "MasterLayout.hpp"
|
|
|
|
#include "../Compositor.hpp"
|
2023-09-20 17:25:03 +02:00
|
|
|
#include "../render/decorations/CHyprGroupBarDecoration.hpp"
|
2024-02-21 12:07:39 +01:00
|
|
|
#include "config/ConfigDataValues.hpp"
|
2023-03-01 15:06:52 +01:00
|
|
|
#include <ranges>
|
2024-03-03 19:39:20 +01:00
|
|
|
#include "../config/ConfigValue.hpp"
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
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-12-10 22:59:16 +01:00
|
|
|
SMasterWorkspaceData* CHyprMasterLayout::getMasterWorkspaceData(const int& ws) {
|
|
|
|
for (auto& n : m_lMasterWorkspacesData) {
|
|
|
|
if (n.workspaceID == ws)
|
|
|
|
return &n;
|
|
|
|
}
|
|
|
|
|
|
|
|
//create on the fly if it doesn't exist yet
|
2024-03-31 01:49:53 +01:00
|
|
|
const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back();
|
|
|
|
PWORKSPACEDATA->workspaceID = ws;
|
|
|
|
static auto PORIENTATION = CConfigValue<std::string>("master:orientation");
|
2024-04-05 17:54:30 +02:00
|
|
|
const auto layoutoptsForWs = g_pConfigManager->getWorkspaceRuleFor(g_pCompositor->getWorkspaceByID(ws)).layoutopts;
|
2024-03-31 01:49:53 +01:00
|
|
|
|
2024-03-15 20:31:33 +01:00
|
|
|
std::string orientationForWs = *PORIENTATION;
|
2023-12-02 15:42:49 +01:00
|
|
|
|
2024-04-05 17:54:30 +02:00
|
|
|
if (layoutoptsForWs.contains("orientation"))
|
|
|
|
orientationForWs = layoutoptsForWs.at("orientation");
|
2023-12-02 15:42:49 +01:00
|
|
|
|
2024-04-01 04:02:47 +02:00
|
|
|
if (orientationForWs == "top")
|
2022-12-10 22:59:16 +01:00
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
|
2024-04-01 04:02:47 +02:00
|
|
|
else if (orientationForWs == "right")
|
2022-12-10 22:59:16 +01:00
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
|
2024-04-01 04:02:47 +02:00
|
|
|
else if (orientationForWs == "bottom")
|
2022-12-10 22:59:16 +01:00
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
|
2024-04-01 04:02:47 +02:00
|
|
|
else if (orientationForWs == "center")
|
2023-02-27 00:12:14 +01:00
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_CENTER;
|
2024-04-01 04:02:47 +02:00
|
|
|
else
|
2023-12-11 23:58:40 +01:00
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
|
|
|
|
|
2022-12-10 22:59:16 +01:00
|
|
|
return PWORKSPACEDATA;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2023-09-13 12:13:29 +02:00
|
|
|
void CHyprMasterLayout::onWindowCreatedTiling(CWindow* pWindow, eDirection direction) {
|
2022-07-16 15:57:31 +02:00
|
|
|
if (pWindow->m_bIsFloating)
|
|
|
|
return;
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PNEWTOP = CConfigValue<Hyprlang::INT>("master:new_on_top");
|
2022-07-16 23:24:42 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
2022-08-05 18:10:59 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto PNODE = *PNEWTOP ? &m_lMasterNodesData.emplace_front() : &m_lMasterNodesData.emplace_back();
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
PNODE->workspaceID = pWindow->workspaceID();
|
2022-12-16 18:17:31 +01:00
|
|
|
PNODE->pWindow = pWindow;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PNEWISMASTER = CConfigValue<Hyprlang::INT>("master:new_is_master");
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto WINDOWSONWORKSPACE = getNodesOnWorkspace(PNODE->workspaceID);
|
|
|
|
static auto PMFACT = CConfigValue<Hyprlang::FLOAT>("master:mfact");
|
|
|
|
float lastSplitPercent = *PMFACT;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
auto OPENINGON = isWindowTiled(g_pCompositor->m_pLastWindow) && g_pCompositor->m_pLastWindow->m_pWorkspace == pWindow->m_pWorkspace ?
|
2024-03-03 19:39:20 +01:00
|
|
|
getNodeFromWindow(g_pCompositor->m_pLastWindow) :
|
2024-04-02 21:32:39 +02:00
|
|
|
getMasterNodeOnWorkspace(pWindow->workspaceID());
|
2023-02-19 22:07:32 +01:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto MOUSECOORDS = g_pInputManager->getMouseCoordsInternal();
|
2023-08-30 17:39:22 +02:00
|
|
|
|
2023-11-02 18:20:32 +01:00
|
|
|
if (g_pInputManager->m_bWasDraggingWindow && OPENINGON) {
|
2023-12-28 23:54:41 +01:00
|
|
|
if (OPENINGON->pWindow->checkInputOnDecos(INPUT_TYPE_DRAG_END, MOUSECOORDS, pWindow))
|
|
|
|
return;
|
2023-10-29 21:14:47 +01:00
|
|
|
}
|
|
|
|
|
2023-07-03 12:49:56 +02:00
|
|
|
// if it's a group, add the window
|
2023-10-30 15:54:12 +01:00
|
|
|
if (OPENINGON && OPENINGON != PNODE && OPENINGON->pWindow->m_sGroupData.pNextWindow // target is group
|
|
|
|
&& pWindow->canBeGroupedInto(OPENINGON->pWindow)) {
|
2023-09-22 01:42:00 +02:00
|
|
|
|
2023-09-14 13:27:16 +02:00
|
|
|
m_lMasterNodesData.remove(*PNODE);
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto USECURRPOS = CConfigValue<Hyprlang::INT>("group:insert_after_current");
|
|
|
|
(*USECURRPOS ? OPENINGON->pWindow : OPENINGON->pWindow->getGroupTail())->insertWindowToGroup(pWindow);
|
2023-07-03 12:49:56 +02:00
|
|
|
|
2023-09-14 13:27:16 +02:00
|
|
|
OPENINGON->pWindow->setGroupCurrent(pWindow);
|
2023-09-22 01:42:00 +02:00
|
|
|
pWindow->applyGroupRules();
|
2023-09-14 13:27:16 +02:00
|
|
|
pWindow->updateWindowDecos();
|
|
|
|
recalculateWindow(pWindow);
|
2023-07-03 12:49:56 +02:00
|
|
|
|
2023-11-11 15:37:17 +01:00
|
|
|
if (!pWindow->getDecorationByType(DECORATION_GROUPBAR))
|
|
|
|
pWindow->addWindowDeco(std::make_unique<CHyprGroupBarDecoration>(pWindow));
|
|
|
|
|
2023-09-14 13:27:16 +02:00
|
|
|
return;
|
2023-02-19 22:07:32 +01:00
|
|
|
}
|
|
|
|
|
2023-09-22 01:42:00 +02:00
|
|
|
pWindow->applyGroupRules();
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PDROPATCURSOR = CConfigValue<Hyprlang::INT>("master:drop_at_cursor");
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACEDATA = getMasterWorkspaceData(pWindow->workspaceID());
|
2024-03-03 19:39:20 +01:00
|
|
|
eOrientation orientation = PWORKSPACEDATA->orientation;
|
|
|
|
const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE);
|
2023-11-03 18:02:59 +01:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
bool forceDropAsMaster = false;
|
2023-11-03 18:02:59 +01:00
|
|
|
// if dragging window to move, drop it at the cursor position instead of bottom/top of stack
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PDROPATCURSOR && g_pInputManager->dragMode == MBIND_MOVE) {
|
2023-11-03 18:02:59 +01:00
|
|
|
if (WINDOWSONWORKSPACE > 2) {
|
|
|
|
for (auto it = m_lMasterNodesData.begin(); it != m_lMasterNodesData.end(); ++it) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (it->workspaceID != pWindow->workspaceID())
|
2023-11-03 18:02:59 +01:00
|
|
|
continue;
|
2023-11-04 18:03:05 +01:00
|
|
|
const CBox box = it->pWindow->getWindowIdealBoundingBoxIgnoreReserved();
|
|
|
|
if (box.containsPoint(MOUSECOORDS)) {
|
2023-11-03 18:02:59 +01:00
|
|
|
switch (orientation) {
|
|
|
|
case ORIENTATION_LEFT:
|
|
|
|
case ORIENTATION_RIGHT:
|
|
|
|
if (MOUSECOORDS.y > it->pWindow->middle().y)
|
|
|
|
++it;
|
|
|
|
break;
|
|
|
|
case ORIENTATION_TOP:
|
|
|
|
case ORIENTATION_BOTTOM:
|
|
|
|
if (MOUSECOORDS.x > it->pWindow->middle().x)
|
|
|
|
++it;
|
|
|
|
break;
|
|
|
|
case ORIENTATION_CENTER: break;
|
|
|
|
default: UNREACHABLE();
|
|
|
|
}
|
|
|
|
m_lMasterNodesData.splice(it, m_lMasterNodesData, NODEIT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (WINDOWSONWORKSPACE == 2) {
|
|
|
|
// when dropping as the second tiled window in the workspace,
|
|
|
|
// make it the master only if the cursor is on the master side of the screen
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
|
|
|
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
|
|
|
switch (orientation) {
|
|
|
|
case ORIENTATION_LEFT:
|
|
|
|
case ORIENTATION_CENTER:
|
|
|
|
if (MOUSECOORDS.x < nd.pWindow->middle().x)
|
|
|
|
forceDropAsMaster = true;
|
|
|
|
break;
|
|
|
|
case ORIENTATION_RIGHT:
|
|
|
|
if (MOUSECOORDS.x > nd.pWindow->middle().x)
|
|
|
|
forceDropAsMaster = true;
|
|
|
|
break;
|
|
|
|
case ORIENTATION_TOP:
|
|
|
|
if (MOUSECOORDS.y < nd.pWindow->middle().y)
|
|
|
|
forceDropAsMaster = true;
|
|
|
|
break;
|
|
|
|
case ORIENTATION_BOTTOM:
|
|
|
|
if (MOUSECOORDS.y > nd.pWindow->middle().y)
|
|
|
|
forceDropAsMaster = true;
|
|
|
|
break;
|
|
|
|
default: UNREACHABLE();
|
|
|
|
}
|
|
|
|
break;
|
2023-10-03 23:16:57 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if ((*PNEWISMASTER && g_pInputManager->dragMode != MBIND_MOVE) || WINDOWSONWORKSPACE == 1 || (WINDOWSONWORKSPACE > 2 && !pWindow->m_bFirstMap && OPENINGON->isMaster) ||
|
2023-11-03 18:02:59 +01:00
|
|
|
forceDropAsMaster) {
|
2022-07-16 15:57:31 +02:00
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
|
|
|
if (nd.isMaster && nd.workspaceID == PNODE->workspaceID) {
|
2022-12-16 18:17:31 +01:00
|
|
|
nd.isMaster = false;
|
2022-07-16 15:57:31 +02:00
|
|
|
lastSplitPercent = nd.percMaster;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
PNODE->isMaster = true;
|
2022-07-16 15:57:31 +02:00
|
|
|
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 {
|
2023-03-06 10:03:49 +01:00
|
|
|
PNODE->isMaster = false;
|
|
|
|
PNODE->percMaster = lastSplitPercent;
|
2022-08-05 18:10:59 +02:00
|
|
|
|
|
|
|
// first, check if it isn't too big.
|
2022-12-16 18:17:31 +01:00
|
|
|
if (const auto MAXSIZE = g_pXWaylandManager->getMaxSizeForWindow(pWindow);
|
|
|
|
MAXSIZE.x < PMONITOR->vecSize.x * (1 - lastSplitPercent) || MAXSIZE.y < PMONITOR->vecSize.y * (1.f / (WINDOWSONWORKSPACE - 1))) {
|
2022-08-05 18:10:59 +02:00
|
|
|
// 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
|
|
|
}
|
|
|
|
|
|
|
|
// recalc
|
|
|
|
recalculateMonitor(pWindow->m_iMonitorID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::onWindowRemovedTiling(CWindow* pWindow) {
|
|
|
|
const auto PNODE = getNodeFromWindow(pWindow);
|
|
|
|
|
|
|
|
if (!PNODE)
|
|
|
|
return;
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto WORKSPACEID = PNODE->workspaceID;
|
|
|
|
const auto MASTERSLEFT = getMastersOnWorkspace(WORKSPACEID);
|
|
|
|
static auto SMALLSPLIT = CConfigValue<Hyprlang::INT>("master:allow_small_split");
|
2023-04-13 16:20:58 +02:00
|
|
|
|
2023-08-17 10:13:19 +02:00
|
|
|
pWindow->updateSpecialRenderData();
|
2022-11-26 19:48:16 +01:00
|
|
|
|
2024-03-13 03:09:20 +01:00
|
|
|
g_pCompositor->setWindowFullscreen(pWindow, false, FULLSCREEN_FULL);
|
2022-09-20 10:55:25 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (PNODE->isMaster && (MASTERSLEFT <= 1 || *SMALLSPLIT == 1)) {
|
2023-04-13 16:20:58 +02:00
|
|
|
// find a new master from top of the list
|
2022-07-16 15:57:31 +02:00
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
2023-04-13 16:20:58 +02:00
|
|
|
if (!nd.isMaster && nd.workspaceID == WORKSPACEID) {
|
2022-12-17 23:52:58 +01:00
|
|
|
nd.isMaster = true;
|
|
|
|
nd.percMaster = PNODE->percMaster;
|
2022-07-16 15:57:31 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
m_lMasterNodesData.remove(*PNODE);
|
|
|
|
|
2022-12-12 15:18:43 +01:00
|
|
|
if (getMastersOnWorkspace(WORKSPACEID) == getNodesOnWorkspace(WORKSPACEID) && MASTERSLEFT > 1) {
|
2023-03-01 15:06:52 +01:00
|
|
|
for (auto& nd : m_lMasterNodesData | std::views::reverse) {
|
|
|
|
if (nd.workspaceID == WORKSPACEID) {
|
|
|
|
nd.isMaster = false;
|
2022-11-08 13:39:52 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-04-13 16:20:58 +02:00
|
|
|
// BUGFIX: correct bug where closing one master in a stack of 2 would leave
|
|
|
|
// the screen half bare, and make it difficult to select remaining window
|
|
|
|
if (getNodesOnWorkspace(WORKSPACEID) == 1) {
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
|
|
|
if (nd.workspaceID == WORKSPACEID && nd.isMaster == false) {
|
|
|
|
nd.isMaster = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
recalculateMonitor(pWindow->m_iMonitorID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::recalculateMonitor(const int& monid) {
|
2023-05-26 13:41:52 +02:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(monid);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (!PMONITOR || !PMONITOR->activeWorkspace)
|
2023-05-26 13:41:52 +02:00
|
|
|
return;
|
|
|
|
|
2024-03-17 01:15:12 +01:00
|
|
|
g_pHyprRenderer->damageMonitor(PMONITOR);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (PMONITOR->activeSpecialWorkspace)
|
|
|
|
calculateWorkspace(PMONITOR->activeSpecialWorkspace);
|
2024-03-17 01:15:12 +01:00
|
|
|
|
|
|
|
calculateWorkspace(PMONITOR->activeWorkspace);
|
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
void CHyprMasterLayout::calculateWorkspace(PHLWORKSPACE pWorkspace) {
|
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWorkspace->m_iMonitorID);
|
2024-03-07 14:27:58 +01:00
|
|
|
|
2024-03-17 01:15:12 +01:00
|
|
|
if (!PMONITOR)
|
|
|
|
return;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (pWorkspace->m_bHasFullscreenWindow) {
|
2022-07-16 15:57:31 +02:00
|
|
|
// massive hack from the fullscreen func
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PFULLWINDOW = g_pCompositor->getFullscreenWindowOnWorkspace(pWorkspace->m_iID);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (pWorkspace->m_efFullscreenMode == FULLSCREEN_FULL) {
|
2023-03-20 17:07:18 +01:00
|
|
|
PFULLWINDOW->m_vRealPosition = PMONITOR->vecPosition;
|
|
|
|
PFULLWINDOW->m_vRealSize = PMONITOR->vecSize;
|
2024-04-02 21:32:39 +02:00
|
|
|
} else if (pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED) {
|
2023-03-20 17:07:18 +01:00
|
|
|
SMasterNodeData fakeNode;
|
2024-03-17 01:15:12 +01:00
|
|
|
fakeNode.pWindow = PFULLWINDOW;
|
|
|
|
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
|
|
|
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
2024-04-02 21:32:39 +02:00
|
|
|
fakeNode.workspaceID = pWorkspace->m_iID;
|
2024-03-17 01:15:12 +01:00
|
|
|
PFULLWINDOW->m_vPosition = fakeNode.position;
|
|
|
|
PFULLWINDOW->m_vSize = fakeNode.size;
|
|
|
|
fakeNode.ignoreFullscreenChecks = true;
|
2023-03-20 17:07:18 +01:00
|
|
|
|
|
|
|
applyNodeDataToWindow(&fakeNode);
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-03-17 01:15:12 +01:00
|
|
|
// if has fullscreen, don't calculate the rest
|
2022-07-16 15:57:31 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACEDATA = getMasterWorkspaceData(pWorkspace->m_iID);
|
|
|
|
const auto PMASTERNODE = getMasterNodeOnWorkspace(pWorkspace->m_iID);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
if (!PMASTERNODE)
|
|
|
|
return;
|
|
|
|
|
2024-04-01 04:02:47 +02:00
|
|
|
// dynamic workspace rules
|
2024-04-05 17:54:30 +02:00
|
|
|
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(pWorkspace);
|
2024-04-01 04:02:47 +02:00
|
|
|
std::string orientationForWs;
|
|
|
|
|
2024-04-05 17:54:30 +02:00
|
|
|
if (WORKSPACERULE.layoutopts.contains("orientation"))
|
|
|
|
orientationForWs = WORKSPACERULE.layoutopts.at("orientation");
|
2024-04-01 04:02:47 +02:00
|
|
|
|
|
|
|
if (orientationForWs == "top")
|
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
|
|
|
|
else if (orientationForWs == "right")
|
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
|
|
|
|
else if (orientationForWs == "bottom")
|
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
|
|
|
|
else if (orientationForWs == "center")
|
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_CENTER;
|
|
|
|
else if (orientationForWs == "left")
|
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
eOrientation orientation = PWORKSPACEDATA->orientation;
|
|
|
|
bool centerMasterWindow = false;
|
|
|
|
static auto ALWAYSCENTER = CConfigValue<Hyprlang::INT>("master:always_center_master");
|
|
|
|
static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing");
|
2023-08-15 18:13:45 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto MASTERS = getMastersOnWorkspace(pWorkspace->m_iID);
|
|
|
|
const auto WINDOWS = getNodesOnWorkspace(pWorkspace->m_iID);
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto STACKWINDOWS = WINDOWS - MASTERS;
|
|
|
|
const auto WSSIZE = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
|
|
|
const auto WSPOS = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
2023-08-15 18:13:45 +02:00
|
|
|
|
2023-02-27 00:12:14 +01:00
|
|
|
if (orientation == ORIENTATION_CENTER) {
|
2024-03-03 19:39:20 +01:00
|
|
|
if (STACKWINDOWS >= 2 || (*ALWAYSCENTER == 1)) {
|
2023-02-27 00:12:14 +01:00
|
|
|
centerMasterWindow = true;
|
|
|
|
} else {
|
|
|
|
orientation = ORIENTATION_LEFT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-09-13 12:13:29 +02:00
|
|
|
const float totalSize = (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) ? WSSIZE.x : WSSIZE.y;
|
|
|
|
const float masterAverageSize = totalSize / MASTERS;
|
|
|
|
const float slaveAverageSize = totalSize / STACKWINDOWS;
|
|
|
|
float masterAccumulatedSize = 0;
|
|
|
|
float slaveAccumulatedSize = 0;
|
2023-09-10 23:58:06 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PSMARTRESIZING) {
|
2023-09-10 23:58:06 +02:00
|
|
|
// check the total width and height so that later
|
|
|
|
// if larger/smaller than screen size them down/up
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (nd.workspaceID == pWorkspace->m_iID) {
|
2023-09-10 23:58:06 +02:00
|
|
|
if (nd.isMaster)
|
|
|
|
masterAccumulatedSize += totalSize / MASTERS * nd.percSize;
|
|
|
|
else
|
|
|
|
slaveAccumulatedSize += totalSize / STACKWINDOWS * nd.percSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-15 18:13:45 +02:00
|
|
|
// compute placement of master window(s)
|
|
|
|
if (WINDOWS == 1 && !centerMasterWindow) {
|
|
|
|
PMASTERNODE->size = WSSIZE;
|
|
|
|
PMASTERNODE->position = WSPOS;
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
applyNodeDataToWindow(PMASTERNODE);
|
|
|
|
return;
|
2023-02-27 00:12:14 +01:00
|
|
|
} else if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) {
|
2023-08-15 18:13:45 +02:00
|
|
|
const float HEIGHT = WSSIZE.y * PMASTERNODE->percMaster;
|
|
|
|
float widthLeft = WSSIZE.x;
|
|
|
|
int mastersLeft = MASTERS;
|
|
|
|
float nextX = 0;
|
|
|
|
float nextY = 0;
|
|
|
|
|
2023-09-13 12:48:19 +02:00
|
|
|
if (orientation == ORIENTATION_BOTTOM)
|
|
|
|
nextY = WSSIZE.y - HEIGHT;
|
|
|
|
|
2023-08-15 18:13:45 +02:00
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (nd.workspaceID != pWorkspace->m_iID || !nd.isMaster)
|
2023-08-15 18:13:45 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
float WIDTH = mastersLeft > 1 ? widthLeft / mastersLeft * nd.percSize : widthLeft;
|
|
|
|
if (WIDTH > widthLeft * 0.9f && mastersLeft > 1)
|
|
|
|
WIDTH = widthLeft * 0.9f;
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PSMARTRESIZING) {
|
2023-09-10 23:58:06 +02:00
|
|
|
nd.percSize *= WSSIZE.x / masterAccumulatedSize;
|
|
|
|
WIDTH = masterAverageSize * nd.percSize;
|
|
|
|
}
|
|
|
|
|
2023-08-30 17:39:22 +02:00
|
|
|
nd.size = Vector2D(WIDTH, HEIGHT);
|
2023-08-15 18:13:45 +02:00
|
|
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
|
|
|
applyNodeDataToWindow(&nd);
|
|
|
|
|
|
|
|
mastersLeft--;
|
|
|
|
widthLeft -= WIDTH;
|
|
|
|
nextX += WIDTH;
|
2023-02-27 00:12:14 +01:00
|
|
|
}
|
2023-08-15 18:13:45 +02:00
|
|
|
} else { // orientation left, right or center
|
2023-08-30 17:39:22 +02:00
|
|
|
float WIDTH = WSSIZE.x;
|
|
|
|
float heightLeft = WSSIZE.y;
|
|
|
|
int mastersLeft = MASTERS;
|
|
|
|
float nextX = 0;
|
|
|
|
float nextY = 0;
|
2023-08-15 18:13:45 +02:00
|
|
|
|
|
|
|
if (STACKWINDOWS > 0 || centerMasterWindow)
|
|
|
|
WIDTH *= PMASTERNODE->percMaster;
|
|
|
|
|
|
|
|
if (orientation == ORIENTATION_RIGHT) {
|
|
|
|
nextX = WSSIZE.x - WIDTH;
|
|
|
|
} else if (centerMasterWindow) {
|
|
|
|
nextX = (WSSIZE.x - WIDTH) / 2;
|
2022-11-08 13:39:52 +01:00
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-12-10 22:59:16 +01:00
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (nd.workspaceID != pWorkspace->m_iID || !nd.isMaster)
|
2022-12-10 22:59:16 +01:00
|
|
|
continue;
|
|
|
|
|
2023-08-15 18:13:45 +02:00
|
|
|
float HEIGHT = mastersLeft > 1 ? heightLeft / mastersLeft * nd.percSize : heightLeft;
|
|
|
|
if (HEIGHT > heightLeft * 0.9f && mastersLeft > 1)
|
2022-12-10 22:59:16 +01:00
|
|
|
HEIGHT = heightLeft * 0.9f;
|
2023-08-15 18:13:45 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PSMARTRESIZING) {
|
2023-09-10 23:58:06 +02:00
|
|
|
nd.percSize *= WSSIZE.y / masterAccumulatedSize;
|
|
|
|
HEIGHT = masterAverageSize * nd.percSize;
|
|
|
|
}
|
|
|
|
|
2023-08-30 17:39:22 +02:00
|
|
|
nd.size = Vector2D(WIDTH, HEIGHT);
|
2023-08-15 18:13:45 +02:00
|
|
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
|
|
|
applyNodeDataToWindow(&nd);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2023-08-15 18:13:45 +02:00
|
|
|
mastersLeft--;
|
2022-12-10 22:59:16 +01:00
|
|
|
heightLeft -= HEIGHT;
|
|
|
|
nextY += HEIGHT;
|
|
|
|
}
|
2023-08-15 18:13:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (STACKWINDOWS == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// compute placement of slave window(s)
|
|
|
|
int slavesLeft = STACKWINDOWS;
|
|
|
|
if (orientation == ORIENTATION_TOP || orientation == ORIENTATION_BOTTOM) {
|
|
|
|
const float HEIGHT = WSSIZE.y - PMASTERNODE->size.y;
|
|
|
|
float widthLeft = WSSIZE.x;
|
2022-12-16 18:17:31 +01:00
|
|
|
float nextX = 0;
|
2023-08-15 18:13:45 +02:00
|
|
|
float nextY = 0;
|
|
|
|
|
|
|
|
if (orientation == ORIENTATION_TOP)
|
|
|
|
nextY = PMASTERNODE->size.y;
|
2022-12-10 22:59:16 +01:00
|
|
|
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster)
|
2022-12-10 22:59:16 +01:00
|
|
|
continue;
|
2023-08-15 18:13:45 +02:00
|
|
|
|
2022-12-10 22:59:16 +01:00
|
|
|
float WIDTH = slavesLeft > 1 ? widthLeft / slavesLeft * nd.percSize : widthLeft;
|
|
|
|
if (WIDTH > widthLeft * 0.9f && slavesLeft > 1)
|
|
|
|
WIDTH = widthLeft * 0.9f;
|
2023-08-15 18:13:45 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PSMARTRESIZING) {
|
2023-09-10 23:58:06 +02:00
|
|
|
nd.percSize *= WSSIZE.x / slaveAccumulatedSize;
|
|
|
|
WIDTH = slaveAverageSize * nd.percSize;
|
|
|
|
}
|
|
|
|
|
2023-08-30 17:39:22 +02:00
|
|
|
nd.size = Vector2D(WIDTH, HEIGHT);
|
2023-08-15 18:13:45 +02:00
|
|
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
|
|
|
applyNodeDataToWindow(&nd);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-12-10 22:59:16 +01:00
|
|
|
slavesLeft--;
|
|
|
|
widthLeft -= WIDTH;
|
|
|
|
nextX += WIDTH;
|
2023-08-15 18:13:45 +02:00
|
|
|
}
|
|
|
|
} else if (orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT) {
|
|
|
|
const float WIDTH = WSSIZE.x - PMASTERNODE->size.x;
|
|
|
|
float heightLeft = WSSIZE.y;
|
|
|
|
float nextY = 0;
|
|
|
|
float nextX = 0;
|
|
|
|
|
|
|
|
if (orientation == ORIENTATION_LEFT)
|
|
|
|
nextX = PMASTERNODE->size.x;
|
|
|
|
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster)
|
2023-08-15 18:13:45 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft;
|
|
|
|
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
|
|
|
HEIGHT = heightLeft * 0.9f;
|
2022-12-10 22:59:16 +01:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PSMARTRESIZING) {
|
2023-09-10 23:58:06 +02:00
|
|
|
nd.percSize *= WSSIZE.y / slaveAccumulatedSize;
|
|
|
|
HEIGHT = slaveAverageSize * nd.percSize;
|
|
|
|
}
|
|
|
|
|
2023-08-30 17:39:22 +02:00
|
|
|
nd.size = Vector2D(WIDTH, HEIGHT);
|
2023-08-15 18:13:45 +02:00
|
|
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
2022-12-10 22:59:16 +01:00
|
|
|
applyNodeDataToWindow(&nd);
|
2023-08-15 18:13:45 +02:00
|
|
|
|
|
|
|
slavesLeft--;
|
|
|
|
heightLeft -= HEIGHT;
|
|
|
|
nextY += HEIGHT;
|
2022-12-10 22:59:16 +01:00
|
|
|
}
|
2023-08-15 18:13:45 +02:00
|
|
|
} else { // slaves for centered master window(s)
|
|
|
|
const float WIDTH = (WSSIZE.x - PMASTERNODE->size.x) / 2.0;
|
2023-02-28 22:18:09 +01:00
|
|
|
float heightLeft = 0;
|
2023-08-15 18:13:45 +02:00
|
|
|
float heightLeftL = WSSIZE.y;
|
|
|
|
float heightLeftR = WSSIZE.y;
|
|
|
|
float nextX = 0;
|
|
|
|
float nextY = 0;
|
2023-02-28 22:18:09 +01:00
|
|
|
float nextYL = 0;
|
|
|
|
float nextYR = 0;
|
2023-08-15 18:13:45 +02:00
|
|
|
bool onRight = true;
|
2023-02-27 00:12:14 +01:00
|
|
|
|
2023-08-15 18:13:45 +02:00
|
|
|
int slavesLeftR = 1 + (slavesLeft - 1) / 2;
|
|
|
|
int slavesLeftL = slavesLeft - slavesLeftR;
|
2023-02-27 00:12:14 +01:00
|
|
|
|
2023-09-10 23:58:06 +02:00
|
|
|
const float slaveAverageHeightL = WSSIZE.y / slavesLeftL;
|
|
|
|
const float slaveAverageHeightR = WSSIZE.y / slavesLeftR;
|
|
|
|
float slaveAccumulatedHeightL = 0;
|
|
|
|
float slaveAccumulatedHeightR = 0;
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PSMARTRESIZING) {
|
2023-09-10 23:58:06 +02:00
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster)
|
2023-09-10 23:58:06 +02:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (onRight) {
|
|
|
|
slaveAccumulatedHeightR += slaveAverageHeightR * nd.percSize;
|
|
|
|
} else {
|
|
|
|
slaveAccumulatedHeightL += slaveAverageHeightL * nd.percSize;
|
|
|
|
}
|
|
|
|
onRight = !onRight;
|
|
|
|
}
|
|
|
|
onRight = true;
|
|
|
|
}
|
|
|
|
|
2023-02-27 00:12:14 +01:00
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (nd.workspaceID != pWorkspace->m_iID || nd.isMaster)
|
2023-02-27 00:12:14 +01:00
|
|
|
continue;
|
|
|
|
|
2023-08-15 18:13:45 +02:00
|
|
|
if (onRight) {
|
2023-08-30 17:39:22 +02:00
|
|
|
nextX = WIDTH + PMASTERNODE->size.x;
|
|
|
|
nextY = nextYR;
|
2023-08-15 18:13:45 +02:00
|
|
|
heightLeft = heightLeftR;
|
|
|
|
slavesLeft = slavesLeftR;
|
2023-02-27 00:12:14 +01:00
|
|
|
} else {
|
2023-08-30 17:39:22 +02:00
|
|
|
nextX = 0;
|
|
|
|
nextY = nextYL;
|
2023-08-15 18:13:45 +02:00
|
|
|
heightLeft = heightLeftL;
|
|
|
|
slavesLeft = slavesLeftL;
|
2023-02-27 00:12:14 +01:00
|
|
|
}
|
2023-08-15 18:13:45 +02:00
|
|
|
|
2023-02-27 00:12:14 +01:00
|
|
|
float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft;
|
|
|
|
if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1)
|
|
|
|
HEIGHT = heightLeft * 0.9f;
|
2023-08-15 18:13:45 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (*PSMARTRESIZING) {
|
2023-09-10 23:58:06 +02:00
|
|
|
if (onRight) {
|
|
|
|
nd.percSize *= WSSIZE.y / slaveAccumulatedHeightR;
|
|
|
|
HEIGHT = slaveAverageHeightR * nd.percSize;
|
|
|
|
} else {
|
|
|
|
nd.percSize *= WSSIZE.y / slaveAccumulatedHeightL;
|
|
|
|
HEIGHT = slaveAverageHeightL * nd.percSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-30 17:39:22 +02:00
|
|
|
nd.size = Vector2D(WIDTH, HEIGHT);
|
2023-08-15 18:13:45 +02:00
|
|
|
nd.position = WSPOS + Vector2D(nextX, nextY);
|
|
|
|
applyNodeDataToWindow(&nd);
|
2023-02-27 00:12:14 +01:00
|
|
|
|
2023-08-15 18:13:45 +02:00
|
|
|
if (onRight) {
|
2023-02-27 00:12:14 +01:00
|
|
|
heightLeftR -= HEIGHT;
|
|
|
|
nextYR += HEIGHT;
|
|
|
|
slavesLeftR--;
|
2023-08-15 18:13:45 +02:00
|
|
|
} else {
|
|
|
|
heightLeftL -= HEIGHT;
|
|
|
|
nextYL += HEIGHT;
|
|
|
|
slavesLeftL--;
|
2023-02-27 00:12:14 +01:00
|
|
|
}
|
|
|
|
|
2023-08-15 18:13:45 +02:00
|
|
|
onRight = !onRight;
|
2023-02-27 00:12:14 +01:00
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-03 13:19:23 +01:00
|
|
|
void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) {
|
2022-07-27 12:32:00 +02:00
|
|
|
CMonitor* PMONITOR = nullptr;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-11-27 23:42:22 +01:00
|
|
|
if (g_pCompositor->isWorkspaceSpecial(pNode->workspaceID)) {
|
2022-07-16 15:57:31 +02:00
|
|
|
for (auto& m : g_pCompositor->m_vMonitors) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (m->activeSpecialWorkspaceID() == pNode->workspaceID) {
|
2022-07-16 15:57:31 +02:00
|
|
|
PMONITOR = m.get();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PMONITOR = g_pCompositor->getMonitorFromID(g_pCompositor->getWorkspaceByID(pNode->workspaceID)->m_iMonitorID);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!PMONITOR) {
|
2023-09-20 17:25:03 +02:00
|
|
|
Debug::log(ERR, "Orphaned Node {}!!", pNode);
|
2022-07-16 15:57:31 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// for gaps outer
|
2023-05-01 23:28:27 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
const auto PWINDOW = pNode->pWindow;
|
|
|
|
// get specific gaps and rules for this workspace,
|
|
|
|
// if user specified them in config
|
2024-04-05 17:54:30 +02:00
|
|
|
const auto WORKSPACERULE = g_pConfigManager->getWorkspaceRuleFor(PWINDOW->m_pWorkspace);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2023-11-03 13:19:23 +01:00
|
|
|
if (PWINDOW->m_bIsFullscreen && !pNode->ignoreFullscreenChecks)
|
2023-11-01 02:28:43 +01:00
|
|
|
return;
|
|
|
|
|
2023-08-17 10:13:19 +02:00
|
|
|
PWINDOW->updateSpecialRenderData();
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PNOGAPSWHENONLY = CConfigValue<Hyprlang::INT>("master:no_gaps_when_only");
|
|
|
|
static auto PANIMATE = CConfigValue<Hyprlang::INT>("misc:animate_manual_resizes");
|
|
|
|
static auto PGAPSINDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_in");
|
|
|
|
static auto PGAPSOUTDATA = CConfigValue<Hyprlang::CUSTOMTYPE>("general:gaps_out");
|
|
|
|
auto* PGAPSIN = (CCssGapData*)(PGAPSINDATA.ptr())->getData();
|
|
|
|
auto* PGAPSOUT = (CCssGapData*)(PGAPSOUTDATA.ptr())->getData();
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-04-05 17:54:30 +02:00
|
|
|
auto gapsIn = WORKSPACERULE.gapsIn.value_or(*PGAPSIN);
|
|
|
|
auto gapsOut = WORKSPACERULE.gapsOut.value_or(*PGAPSOUT);
|
2023-07-23 15:49:49 +02:00
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
if (!g_pCompositor->windowValidMapped(PWINDOW)) {
|
2023-09-20 17:25:03 +02:00
|
|
|
Debug::log(ERR, "Node {} holding invalid {}!!", pNode, PWINDOW);
|
2022-07-16 15:57:31 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
PWINDOW->m_vSize = pNode->size;
|
2022-07-16 15:57:31 +02:00
|
|
|
PWINDOW->m_vPosition = pNode->position;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (*PNOGAPSWHENONLY && !PWINDOW->onSpecialWorkspace() &&
|
|
|
|
(getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 || (PWINDOW->m_bIsFullscreen && PWINDOW->m_pWorkspace->m_efFullscreenMode == FULLSCREEN_MAXIMIZED))) {
|
2022-08-01 12:57:37 +02:00
|
|
|
|
2024-04-05 17:54:30 +02:00
|
|
|
PWINDOW->m_sSpecialRenderData.border = WORKSPACERULE.border.value_or(*PNOGAPSWHENONLY == 2);
|
|
|
|
PWINDOW->m_sSpecialRenderData.decorate = WORKSPACERULE.decorate.value_or(true);
|
2022-08-01 12:57:37 +02:00
|
|
|
PWINDOW->m_sSpecialRenderData.rounding = false;
|
2023-08-13 10:18:48 +02:00
|
|
|
PWINDOW->m_sSpecialRenderData.shadow = false;
|
2023-07-24 12:13:40 +02:00
|
|
|
|
2023-12-10 17:28:12 +01:00
|
|
|
PWINDOW->updateWindowDecos();
|
2023-07-24 12:13:40 +02:00
|
|
|
|
2023-12-10 17:28:12 +01:00
|
|
|
const auto RESERVED = PWINDOW->getFullWindowReservedArea();
|
2023-07-24 12:13:40 +02:00
|
|
|
|
2023-12-10 17:28:12 +01:00
|
|
|
PWINDOW->m_vRealPosition = PWINDOW->m_vPosition + RESERVED.topLeft;
|
|
|
|
PWINDOW->m_vRealSize = PWINDOW->m_vSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
2022-08-01 12:57:37 +02:00
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize.goal());
|
2023-11-05 00:00:20 +01:00
|
|
|
|
2022-08-01 12:57:37 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-12-10 17:28:12 +01:00
|
|
|
auto calcPos = PWINDOW->m_vPosition;
|
|
|
|
auto calcSize = PWINDOW->m_vSize;
|
2023-07-24 12:13:40 +02:00
|
|
|
|
2024-02-21 12:07:39 +01:00
|
|
|
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? gapsOut.left : gapsIn.left, DISPLAYTOP ? gapsOut.top : gapsIn.top);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-02-21 12:07:39 +01:00
|
|
|
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? gapsOut.right : gapsIn.right, DISPLAYBOTTOM ? gapsOut.bottom : gapsIn.bottom);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
calcPos = calcPos + OFFSETTOPLEFT;
|
2022-07-16 15:57:31 +02:00
|
|
|
calcSize = calcSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
|
|
|
|
|
2023-02-28 22:18:09 +01:00
|
|
|
const auto RESERVED = PWINDOW->getFullWindowReservedArea();
|
|
|
|
calcPos = calcPos + RESERVED.topLeft;
|
|
|
|
calcSize = calcSize - (RESERVED.topLeft + RESERVED.bottomRight);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (PWINDOW->onSpecialWorkspace() && !PWINDOW->m_bIsFullscreen) {
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PSCALEFACTOR = CConfigValue<Hyprlang::FLOAT>("master:special_scale_factor");
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
CBox wb = {calcPos + (calcSize - calcSize * *PSCALEFACTOR) / 2.f, calcSize * *PSCALEFACTOR};
|
2023-11-05 20:57:11 +01:00
|
|
|
wb.round(); // avoid rounding mess
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2023-11-05 20:57:11 +01:00
|
|
|
PWINDOW->m_vRealPosition = wb.pos();
|
|
|
|
PWINDOW->m_vRealSize = wb.size();
|
|
|
|
|
|
|
|
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
2022-07-16 15:57:31 +02:00
|
|
|
} else {
|
2023-11-06 18:00:37 +01:00
|
|
|
CBox wb = {calcPos, calcSize};
|
|
|
|
wb.round(); // avoid rounding mess
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2023-11-06 18:00:37 +01:00
|
|
|
PWINDOW->m_vRealPosition = wb.pos();
|
|
|
|
PWINDOW->m_vRealSize = wb.size();
|
|
|
|
|
|
|
|
g_pXWaylandManager->setWindowSize(PWINDOW, wb.size());
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (m_bForceWarps && !*PANIMATE) {
|
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;
|
|
|
|
}
|
|
|
|
|
2023-07-13 16:52:11 +02:00
|
|
|
void CHyprMasterLayout::resizeActiveWindow(const Vector2D& pixResize, eRectCorner corner, CWindow* pWindow) {
|
2022-07-16 15:57:31 +02:00
|
|
|
const auto PWINDOW = pWindow ? pWindow : g_pCompositor->m_pLastWindow;
|
|
|
|
|
|
|
|
if (!g_pCompositor->windowValidMapped(PWINDOW))
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto PNODE = getNodeFromWindow(PWINDOW);
|
|
|
|
|
|
|
|
if (!PNODE) {
|
2024-03-02 01:35:17 +01:00
|
|
|
PWINDOW->m_vRealSize = Vector2D(std::max((PWINDOW->m_vRealSize.goal() + pixResize).x, 20.0), std::max((PWINDOW->m_vRealSize.goal() + pixResize).y, 20.0));
|
2022-07-16 15:57:31 +02:00
|
|
|
PWINDOW->updateWindowDecos();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(PWINDOW->m_iMonitorID);
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->workspaceID());
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto ALWAYSCENTER = CConfigValue<Hyprlang::INT>("master:always_center_master");
|
|
|
|
static auto PSMARTRESIZING = CConfigValue<Hyprlang::INT>("master:smart_resizing");
|
2023-08-15 18:13:45 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
eOrientation orientation = PWORKSPACEDATA->orientation;
|
|
|
|
bool centered = orientation == ORIENTATION_CENTER && (*ALWAYSCENTER == 1);
|
|
|
|
double delta = 0;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const bool DISPLAYBOTTOM = STICKS(PWINDOW->m_vPosition.y + PWINDOW->m_vSize.y, PMONITOR->vecPosition.y + PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y);
|
|
|
|
const bool DISPLAYRIGHT = STICKS(PWINDOW->m_vPosition.x + PWINDOW->m_vSize.x, PMONITOR->vecPosition.x + PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x);
|
|
|
|
const bool DISPLAYTOP = STICKS(PWINDOW->m_vPosition.y, PMONITOR->vecPosition.y + PMONITOR->vecReservedTopLeft.y);
|
|
|
|
const bool DISPLAYLEFT = STICKS(PWINDOW->m_vPosition.x, PMONITOR->vecPosition.x + PMONITOR->vecReservedTopLeft.x);
|
2023-09-10 23:58:06 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const bool LEFT = corner == CORNER_TOPLEFT || corner == CORNER_BOTTOMLEFT;
|
|
|
|
const bool TOP = corner == CORNER_TOPLEFT || corner == CORNER_TOPRIGHT;
|
|
|
|
const bool NONE = corner == CORNER_NONE;
|
2023-09-13 12:48:19 +02:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto MASTERS = getMastersOnWorkspace(PNODE->workspaceID);
|
|
|
|
const auto WINDOWS = getNodesOnWorkspace(PNODE->workspaceID);
|
|
|
|
const auto STACKWINDOWS = WINDOWS - MASTERS;
|
2023-09-10 23:58:06 +02:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (getNodesOnWorkspace(PWINDOW->workspaceID()) == 1 && !centered)
|
2022-07-16 15:57:31 +02:00
|
|
|
return;
|
|
|
|
|
2023-09-15 23:13:23 +02:00
|
|
|
m_bForceWarps = true;
|
|
|
|
|
2023-08-15 18:13:45 +02:00
|
|
|
switch (orientation) {
|
2022-12-30 13:01:43 +01:00
|
|
|
case ORIENTATION_LEFT: delta = pixResize.x / PMONITOR->vecSize.x; break;
|
|
|
|
case ORIENTATION_RIGHT: delta = -pixResize.x / PMONITOR->vecSize.x; break;
|
|
|
|
case ORIENTATION_BOTTOM: delta = -pixResize.y / PMONITOR->vecSize.y; break;
|
|
|
|
case ORIENTATION_TOP: delta = pixResize.y / PMONITOR->vecSize.y; break;
|
2023-09-13 12:48:19 +02:00
|
|
|
case ORIENTATION_CENTER:
|
|
|
|
delta = pixResize.x / PMONITOR->vecSize.x;
|
2024-04-03 02:22:27 +02:00
|
|
|
if (WINDOWS > 2 || *ALWAYSCENTER) {
|
2023-09-13 12:48:19 +02:00
|
|
|
if (!NONE || !PNODE->isMaster)
|
|
|
|
delta *= 2;
|
2024-03-03 19:39:20 +01:00
|
|
|
if ((!PNODE->isMaster && DISPLAYLEFT) || (PNODE->isMaster && LEFT && *PSMARTRESIZING))
|
2023-09-13 12:48:19 +02:00
|
|
|
delta = -delta;
|
|
|
|
}
|
|
|
|
break;
|
2022-12-30 13:01:43 +01:00
|
|
|
default: UNREACHABLE();
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-04-03 02:22:59 +02:00
|
|
|
const auto workspaceIdForResizing = PMONITOR->activeSpecialWorkspace ? PMONITOR->activeSpecialWorkspaceID() : PMONITOR->activeWorkspaceID();
|
2022-11-10 13:05:22 +01:00
|
|
|
for (auto& n : m_lMasterNodesData) {
|
2023-10-17 13:06:16 +02:00
|
|
|
if (n.isMaster && n.workspaceID == workspaceIdForResizing)
|
2022-11-10 13:05:22 +01:00
|
|
|
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
|
2023-09-13 12:48:19 +02:00
|
|
|
const bool isStackVertical = orientation == ORIENTATION_LEFT || orientation == ORIENTATION_RIGHT || orientation == ORIENTATION_CENTER;
|
|
|
|
|
2023-09-14 13:27:16 +02:00
|
|
|
const auto RESIZEDELTA = isStackVertical ? pixResize.y : pixResize.x;
|
|
|
|
const auto WSSIZE = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
2023-09-13 12:48:19 +02:00
|
|
|
|
|
|
|
auto nodesInSameColumn = PNODE->isMaster ? MASTERS : STACKWINDOWS;
|
|
|
|
if (orientation == ORIENTATION_CENTER && !PNODE->isMaster)
|
|
|
|
nodesInSameColumn = DISPLAYRIGHT ? (nodesInSameColumn + 1) / 2 : nodesInSameColumn / 2;
|
|
|
|
|
|
|
|
const auto SIZE = isStackVertical ? WSSIZE.y / nodesInSameColumn : WSSIZE.x / nodesInSameColumn;
|
|
|
|
|
|
|
|
if (RESIZEDELTA != 0 && nodesInSameColumn > 1) {
|
2024-03-03 19:39:20 +01:00
|
|
|
if (!*PSMARTRESIZING) {
|
2023-09-13 12:48:19 +02:00
|
|
|
PNODE->percSize = std::clamp(PNODE->percSize + RESIZEDELTA / SIZE, 0.05, 1.95);
|
|
|
|
} else {
|
2023-09-14 13:27:16 +02:00
|
|
|
const auto NODEIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *PNODE);
|
|
|
|
const auto REVNODEIT = std::find(m_lMasterNodesData.rbegin(), m_lMasterNodesData.rend(), *PNODE);
|
2023-09-10 23:58:06 +02:00
|
|
|
|
|
|
|
const float totalSize = isStackVertical ? WSSIZE.y : WSSIZE.x;
|
|
|
|
const float minSize = totalSize / nodesInSameColumn * 0.2;
|
|
|
|
const bool resizePrevNodes = isStackVertical ? (TOP || DISPLAYBOTTOM) && !DISPLAYTOP : (LEFT || DISPLAYRIGHT) && !DISPLAYLEFT;
|
|
|
|
|
2023-09-13 12:13:29 +02:00
|
|
|
int nodesLeft = 0;
|
|
|
|
float sizeLeft = 0;
|
|
|
|
int nodeCount = 0;
|
2023-09-10 23:58:06 +02:00
|
|
|
// check the sizes of all the nodes to be resized for later calculation
|
|
|
|
auto checkNodesLeft = [&sizeLeft, &nodesLeft, orientation, isStackVertical, &nodeCount, PNODE](auto it) {
|
|
|
|
if (it.isMaster != PNODE->isMaster || it.workspaceID != PNODE->workspaceID)
|
|
|
|
return;
|
|
|
|
nodeCount++;
|
|
|
|
if (!it.isMaster && orientation == ORIENTATION_CENTER && nodeCount % 2 == 1)
|
|
|
|
return;
|
|
|
|
sizeLeft += isStackVertical ? it.size.y : it.size.x;
|
|
|
|
nodesLeft++;
|
|
|
|
};
|
|
|
|
float resizeDiff;
|
|
|
|
if (resizePrevNodes) {
|
|
|
|
std::for_each(std::next(REVNODEIT), m_lMasterNodesData.rend(), checkNodesLeft);
|
|
|
|
resizeDiff = -RESIZEDELTA;
|
|
|
|
} else {
|
|
|
|
std::for_each(std::next(NODEIT), m_lMasterNodesData.end(), checkNodesLeft);
|
|
|
|
resizeDiff = RESIZEDELTA;
|
|
|
|
}
|
|
|
|
|
|
|
|
const float nodeSize = isStackVertical ? PNODE->size.y : PNODE->size.x;
|
|
|
|
const float maxSizeIncrease = sizeLeft - nodesLeft * minSize;
|
|
|
|
const float maxSizeDecrease = minSize - nodeSize;
|
|
|
|
|
|
|
|
// leaves enough room for the other nodes
|
|
|
|
resizeDiff = std::clamp(resizeDiff, maxSizeDecrease, maxSizeIncrease);
|
|
|
|
PNODE->percSize += resizeDiff / SIZE;
|
|
|
|
|
|
|
|
// resize the other nodes
|
2023-09-13 12:13:29 +02:00
|
|
|
nodeCount = 0;
|
|
|
|
auto resizeNodesLeft = [maxSizeIncrease, resizeDiff, minSize, orientation, isStackVertical, SIZE, &nodeCount, nodesLeft, PNODE](auto& it) {
|
2023-09-10 23:58:06 +02:00
|
|
|
if (it.isMaster != PNODE->isMaster || it.workspaceID != PNODE->workspaceID)
|
|
|
|
return;
|
|
|
|
nodeCount++;
|
|
|
|
// if center orientation, only resize when on the same side
|
|
|
|
if (!it.isMaster && orientation == ORIENTATION_CENTER && nodeCount % 2 == 1)
|
|
|
|
return;
|
2023-09-13 12:13:29 +02:00
|
|
|
const float size = isStackVertical ? it.size.y : it.size.x;
|
|
|
|
const float resizeDeltaForEach = maxSizeIncrease != 0 ? resizeDiff * (size - minSize) / maxSizeIncrease : resizeDiff / nodesLeft;
|
2023-09-10 23:58:06 +02:00
|
|
|
it.percSize -= resizeDeltaForEach / SIZE;
|
|
|
|
};
|
|
|
|
if (resizePrevNodes) {
|
|
|
|
std::for_each(std::next(REVNODEIT), m_lMasterNodesData.rend(), resizeNodesLeft);
|
|
|
|
} else {
|
|
|
|
std::for_each(std::next(NODEIT), m_lMasterNodesData.end(), resizeNodesLeft);
|
|
|
|
}
|
2022-11-10 13:05:22 +01:00
|
|
|
}
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
recalculateMonitor(PMONITOR->ID);
|
2023-09-15 23:13:23 +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;
|
|
|
|
|
2024-03-05 00:29:45 +01:00
|
|
|
if (on == pWindow->m_bIsFullscreen)
|
2022-12-16 18:17:31 +01:00
|
|
|
return; // ignore
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto PMONITOR = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = pWindow->m_pWorkspace;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
if (PWORKSPACE->m_bHasFullscreenWindow && on) {
|
|
|
|
// if the window wants to be fullscreen but there already is one,
|
|
|
|
// ignore the request.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2024-01-26 18:24:00 +01:00
|
|
|
// save position and size if floating
|
|
|
|
if (pWindow->m_bIsFloating && on) {
|
2024-03-02 01:35:17 +01:00
|
|
|
pWindow->m_vLastFloatingSize = pWindow->m_vRealSize.goal();
|
|
|
|
pWindow->m_vLastFloatingPosition = pWindow->m_vRealPosition.goal();
|
|
|
|
pWindow->m_vPosition = pWindow->m_vRealPosition.goal();
|
|
|
|
pWindow->m_vSize = pWindow->m_vRealSize.goal();
|
2024-01-26 18:24:00 +01:00
|
|
|
}
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
// otherwise, accept it.
|
2022-12-16 18:17:31 +01:00
|
|
|
pWindow->m_bIsFullscreen = on;
|
2022-07-16 15:57:31 +02:00
|
|
|
PWORKSPACE->m_bHasFullscreenWindow = !PWORKSPACE->m_bHasFullscreenWindow;
|
|
|
|
|
2024-01-02 14:21:22 +01:00
|
|
|
pWindow->updateDynamicRules();
|
|
|
|
pWindow->updateWindowDecos();
|
|
|
|
|
2022-07-20 18:39:08 +02:00
|
|
|
g_pEventManager->postEvent(SHyprIPCEvent{"fullscreen", std::to_string((int)on)});
|
2023-02-19 21:54:53 +01:00
|
|
|
EMIT_HOOK_EVENT("fullscreen", pWindow);
|
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
|
2023-01-13 21:58:14 +01:00
|
|
|
pWindow->m_vRealPosition = pWindow->m_vLastFloatingPosition;
|
|
|
|
pWindow->m_vRealSize = pWindow->m_vLastFloatingSize;
|
2023-01-31 13:15:34 +01:00
|
|
|
|
2023-08-17 10:13:19 +02:00
|
|
|
pWindow->updateSpecialRenderData();
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// if it now got fullscreen, make it fullscreen
|
|
|
|
|
|
|
|
PWORKSPACE->m_efFullscreenMode = fullscreenMode;
|
|
|
|
|
|
|
|
// apply new pos and size being monitors' box
|
|
|
|
if (fullscreenMode == FULLSCREEN_FULL) {
|
|
|
|
pWindow->m_vRealPosition = PMONITOR->vecPosition;
|
2022-12-16 18:17:31 +01:00
|
|
|
pWindow->m_vRealSize = PMONITOR->vecSize;
|
2022-07-16 15:57:31 +02:00
|
|
|
} 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;
|
2023-11-03 13:19:23 +01:00
|
|
|
fakeNode.pWindow = pWindow;
|
|
|
|
fakeNode.position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
|
|
|
|
fakeNode.size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
|
2024-04-02 21:32:39 +02:00
|
|
|
fakeNode.workspaceID = pWindow->workspaceID();
|
2023-11-03 13:19:23 +01:00
|
|
|
pWindow->m_vPosition = fakeNode.position;
|
|
|
|
pWindow->m_vSize = fakeNode.size;
|
|
|
|
fakeNode.ignoreFullscreenChecks = true;
|
|
|
|
|
|
|
|
applyNodeDataToWindow(&fakeNode);
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_pCompositor->updateWindowAnimatedDecorationValues(pWindow);
|
|
|
|
|
2024-03-02 01:35:17 +01:00
|
|
|
g_pXWaylandManager->setWindowSize(pWindow, pWindow->m_vRealSize.goal());
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2023-09-21 23:18:26 +02:00
|
|
|
g_pCompositor->changeWindowZOrder(pWindow, true);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2023-09-04 15:34:07 +02:00
|
|
|
void CHyprMasterLayout::moveWindowTo(CWindow* pWindow, const std::string& dir) {
|
|
|
|
if (!isDirection(dir))
|
|
|
|
return;
|
|
|
|
|
|
|
|
const auto PWINDOW2 = g_pCompositor->getWindowInDirection(pWindow, dir[0]);
|
|
|
|
|
2024-04-02 13:46:05 +02:00
|
|
|
if (!PWINDOW2)
|
|
|
|
return;
|
|
|
|
|
2024-03-19 03:52:52 +01:00
|
|
|
pWindow->setAnimationsToMove();
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
if (pWindow->m_pWorkspace != PWINDOW2->m_pWorkspace) {
|
2023-10-20 19:01:04 +02:00
|
|
|
// if different monitors, send to monitor
|
|
|
|
onWindowRemovedTiling(pWindow);
|
2024-04-02 21:32:39 +02:00
|
|
|
pWindow->moveToWorkspace(PWINDOW2->m_pWorkspace);
|
2023-10-20 19:01:04 +02:00
|
|
|
pWindow->m_iMonitorID = PWINDOW2->m_iMonitorID;
|
2024-03-07 14:23:22 +01:00
|
|
|
const auto pMonitor = g_pCompositor->getMonitorFromID(pWindow->m_iMonitorID);
|
|
|
|
g_pCompositor->setActiveMonitor(pMonitor);
|
2023-10-20 19:01:04 +02:00
|
|
|
onWindowCreatedTiling(pWindow);
|
|
|
|
} else {
|
|
|
|
// if same monitor, switch windows
|
|
|
|
switchWindows(pWindow, PWINDOW2);
|
|
|
|
}
|
2023-09-04 15:34:07 +02:00
|
|
|
}
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
void CHyprMasterLayout::switchWindows(CWindow* pWindow, CWindow* pWindow2) {
|
|
|
|
// windows should be valid, insallah
|
|
|
|
|
2022-12-16 18:17:31 +01:00
|
|
|
const auto PNODE = getNodeFromWindow(pWindow);
|
2022-07-16 15:57:31 +02:00
|
|
|
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);
|
2024-04-02 21:32:39 +02:00
|
|
|
std::swap(pWindow2->m_pWorkspace, pWindow->m_pWorkspace);
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// massive hack: just swap window pointers, lol
|
2022-12-16 18:17:31 +01:00
|
|
|
PNODE->pWindow = pWindow2;
|
2022-09-14 17:30:16 +02:00
|
|
|
PNODE2->pWindow = pWindow;
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2024-03-19 03:52:52 +01:00
|
|
|
pWindow->setAnimationsToMove();
|
|
|
|
pWindow2->setAnimationsToMove();
|
|
|
|
|
2022-09-14 17:30:16 +02:00
|
|
|
recalculateMonitor(pWindow->m_iMonitorID);
|
|
|
|
if (PNODE2->workspaceID != PNODE->workspaceID)
|
|
|
|
recalculateMonitor(pWindow2->m_iMonitorID);
|
2022-11-25 20:52:23 +01:00
|
|
|
|
|
|
|
g_pHyprRenderer->damageWindow(pWindow);
|
|
|
|
g_pHyprRenderer->damageWindow(pWindow2);
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
2022-12-17 23:37:44 +01:00
|
|
|
void CHyprMasterLayout::alterSplitRatio(CWindow* pWindow, float ratio, bool exact) {
|
2022-07-16 15:57:31 +02:00
|
|
|
// window should be valid, insallah
|
|
|
|
|
|
|
|
const auto PNODE = getNodeFromWindow(pWindow);
|
|
|
|
|
|
|
|
if (!PNODE)
|
|
|
|
return;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PMASTER = getMasterNodeOnWorkspace(pWindow->workspaceID());
|
2022-07-16 15:57:31 +02:00
|
|
|
|
2022-12-30 13:01:43 +01:00
|
|
|
float newRatio = exact ? ratio : PMASTER->percMaster + ratio;
|
2022-12-17 23:37:44 +01:00
|
|
|
PMASTER->percMaster = std::clamp(newRatio, 0.05f, 0.95f);
|
2022-07-16 15:57:31 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
2023-03-13 02:07:05 +01:00
|
|
|
auto nodes = m_lMasterNodesData;
|
|
|
|
if (!next)
|
|
|
|
std::reverse(nodes.begin(), nodes.end());
|
2022-07-28 12:00:10 +02:00
|
|
|
|
2023-03-13 02:07:05 +01:00
|
|
|
const auto NODEIT = std::find(nodes.begin(), nodes.end(), *PNODE);
|
2022-07-28 12:00:10 +02:00
|
|
|
|
2023-03-13 02:07:05 +01:00
|
|
|
const bool ISMASTER = PNODE->isMaster;
|
2022-07-28 12:00:10 +02:00
|
|
|
|
2023-03-13 02:07:05 +01:00
|
|
|
auto CANDIDATE = std::find_if(NODEIT, nodes.end(), [&](const auto& other) { return other != *PNODE && ISMASTER == other.isMaster && other.workspaceID == PNODE->workspaceID; });
|
|
|
|
if (CANDIDATE == nodes.end())
|
|
|
|
CANDIDATE =
|
|
|
|
std::find_if(nodes.begin(), nodes.end(), [&](const auto& other) { return other != *PNODE && ISMASTER != other.isMaster && other.workspaceID == PNODE->workspaceID; });
|
2022-07-28 12:00:10 +02:00
|
|
|
|
2023-03-13 02:07:05 +01:00
|
|
|
return CANDIDATE == nodes.end() ? nullptr : CANDIDATE->pWindow;
|
2022-08-24 21:50:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::string message) {
|
|
|
|
auto switchToWindow = [&](CWindow* PWINDOWTOCHANGETO) {
|
|
|
|
if (!g_pCompositor->windowValidMapped(PWINDOWTOCHANGETO))
|
|
|
|
return;
|
|
|
|
|
2024-03-13 03:09:20 +01:00
|
|
|
if (header.pWindow->m_bIsFullscreen) {
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACE = header.pWindow->m_pWorkspace;
|
2024-03-13 03:09:20 +01:00
|
|
|
const auto FSMODE = PWORKSPACE->m_efFullscreenMode;
|
|
|
|
static auto INHERITFULLSCREEN = CConfigValue<Hyprlang::INT>("master:inherit_fullscreen");
|
|
|
|
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
|
|
|
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
|
|
|
if (*INHERITFULLSCREEN)
|
|
|
|
g_pCompositor->setWindowFullscreen(PWINDOWTOCHANGETO, true, FSMODE);
|
|
|
|
} else {
|
|
|
|
g_pCompositor->focusWindow(PWINDOWTOCHANGETO);
|
|
|
|
g_pCompositor->warpCursorTo(PWINDOWTOCHANGETO->middle());
|
|
|
|
}
|
|
|
|
|
|
|
|
g_pInputManager->m_pForcedFocus = PWINDOWTOCHANGETO;
|
|
|
|
g_pInputManager->simulateMouseMovement();
|
|
|
|
g_pInputManager->m_pForcedFocus = nullptr;
|
2022-08-24 21:50:48 +02:00
|
|
|
};
|
|
|
|
|
2023-02-10 20:13:38 +01:00
|
|
|
CVarList vars(message, 0, ' ');
|
|
|
|
|
|
|
|
if (vars.size() < 1 || vars[0].empty()) {
|
|
|
|
Debug::log(ERR, "layoutmsg called without params");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto command = vars[0];
|
|
|
|
|
2023-02-11 14:00:05 +01:00
|
|
|
// swapwithmaster <master | child | auto>
|
|
|
|
// first message argument can have the following values:
|
|
|
|
// * master - keep the focus at the new master
|
|
|
|
// * child - keep the focus at the new child
|
|
|
|
// * auto (default) - swap the focus (keep the focus of the previously selected window)
|
2023-02-10 20:13:38 +01:00
|
|
|
if (command == "swapwithmaster") {
|
2022-08-24 21:50:48 +02:00
|
|
|
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;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->workspaceID());
|
2022-08-24 21:50:48 +02:00
|
|
|
|
2022-11-20 12:54:51 +01:00
|
|
|
if (!PMASTER)
|
2022-08-24 21:50:48 +02:00
|
|
|
return 0;
|
|
|
|
|
2023-02-11 14:00:05 +01:00
|
|
|
const auto NEWCHILD = PMASTER->pWindow;
|
|
|
|
|
2022-11-20 12:54:51 +01:00
|
|
|
if (PMASTER->pWindow != PWINDOW) {
|
2024-03-13 03:09:20 +01:00
|
|
|
const auto NEWMASTER = PWINDOW;
|
|
|
|
const bool newFocusToChild = vars.size() >= 2 && vars[1] == "child";
|
2023-02-11 14:00:05 +01:00
|
|
|
switchWindows(NEWMASTER, NEWCHILD);
|
|
|
|
const auto NEWFOCUS = newFocusToChild ? NEWCHILD : NEWMASTER;
|
|
|
|
switchToWindow(NEWFOCUS);
|
2022-11-20 12:54:51 +01:00
|
|
|
} else {
|
|
|
|
for (auto& n : m_lMasterNodesData) {
|
|
|
|
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
|
2024-03-13 03:09:20 +01:00
|
|
|
const auto NEWMASTER = n.pWindow;
|
2023-02-11 14:00:05 +01:00
|
|
|
switchWindows(NEWMASTER, NEWCHILD);
|
|
|
|
const bool newFocusToMaster = vars.size() >= 2 && vars[1] == "master";
|
|
|
|
const auto NEWFOCUS = newFocusToMaster ? NEWMASTER : NEWCHILD;
|
|
|
|
switchToWindow(NEWFOCUS);
|
2022-11-20 12:54:51 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-08-24 21:50:48 +02:00
|
|
|
|
2022-11-02 11:15:11 +01:00
|
|
|
return 0;
|
2023-02-11 14:00:05 +01:00
|
|
|
}
|
|
|
|
// focusmaster <master | auto>
|
|
|
|
// first message argument can have the following values:
|
|
|
|
// * master - keep the focus at the new master, even if it was focused before
|
|
|
|
// * auto (default) - swap the focus with the first child, if the current focus was master, otherwise focus master
|
|
|
|
else if (command == "focusmaster") {
|
2022-11-02 11:15:11 +01:00
|
|
|
const auto PWINDOW = header.pWindow;
|
2022-11-03 23:55:44 +01:00
|
|
|
|
|
|
|
if (!PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PMASTER = getMasterNodeOnWorkspace(PWINDOW->workspaceID());
|
2022-11-02 11:15:11 +01:00
|
|
|
|
2022-11-20 12:54:51 +01:00
|
|
|
if (!PMASTER)
|
2022-11-02 11:15:11 +01:00
|
|
|
return 0;
|
|
|
|
|
2022-12-12 15:34:52 +01:00
|
|
|
if (PMASTER->pWindow != PWINDOW) {
|
2022-11-20 12:54:51 +01:00
|
|
|
switchToWindow(PMASTER->pWindow);
|
2023-02-10 20:13:38 +01:00
|
|
|
} else if (vars.size() >= 2 && vars[1] == "master") {
|
2023-02-11 14:00:05 +01:00
|
|
|
return 0;
|
2022-12-12 15:34:52 +01:00
|
|
|
} else {
|
2023-02-10 20:13:38 +01:00
|
|
|
// if master is focused keep master focused (don't do anything)
|
2022-11-20 12:54:51 +01:00
|
|
|
for (auto& n : m_lMasterNodesData) {
|
|
|
|
if (n.workspaceID == PMASTER->workspaceID && !n.isMaster) {
|
|
|
|
switchToWindow(n.pWindow);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-11-02 11:15:11 +01:00
|
|
|
|
2022-08-24 21:50:48 +02:00
|
|
|
return 0;
|
2023-02-10 20:13:38 +01:00
|
|
|
} else if (command == "cyclenext") {
|
2022-08-24 21:50:48 +02:00
|
|
|
const auto PWINDOW = header.pWindow;
|
|
|
|
|
2022-11-03 23:55:44 +01:00
|
|
|
if (!PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
2022-12-12 15:34:52 +01:00
|
|
|
const auto PNEXTWINDOW = getNextWindow(PWINDOW, true);
|
|
|
|
switchToWindow(PNEXTWINDOW);
|
2023-02-10 20:13:38 +01:00
|
|
|
} else if (command == "cycleprev") {
|
2022-08-24 21:50:48 +02:00
|
|
|
const auto PWINDOW = header.pWindow;
|
|
|
|
|
2022-11-03 23:55:44 +01:00
|
|
|
if (!PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
2022-12-17 15:37:10 +01:00
|
|
|
const auto PPREVWINDOW = getNextWindow(PWINDOW, false);
|
2022-12-12 15:34:52 +01:00
|
|
|
switchToWindow(PPREVWINDOW);
|
2023-02-10 20:13:38 +01:00
|
|
|
} else if (command == "swapnext") {
|
2022-08-24 21:50:48 +02:00
|
|
|
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) {
|
2024-03-13 03:09:20 +01:00
|
|
|
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
2022-08-24 21:50:48 +02:00
|
|
|
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
|
2024-03-13 03:09:20 +01:00
|
|
|
switchToWindow(header.pWindow);
|
2022-08-24 21:50:48 +02:00
|
|
|
}
|
2023-02-10 20:13:38 +01:00
|
|
|
} else if (command == "swapprev") {
|
2022-08-24 21:50:48 +02:00
|
|
|
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) {
|
2024-03-13 03:09:20 +01:00
|
|
|
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
2022-08-24 21:50:48 +02:00
|
|
|
switchWindows(header.pWindow, PWINDOWTOSWAPWITH);
|
2024-03-13 03:09:20 +01:00
|
|
|
switchToWindow(header.pWindow);
|
2022-08-24 21:50:48 +02:00
|
|
|
}
|
2023-02-10 20:13:38 +01:00
|
|
|
} else if (command == "addmaster") {
|
2022-11-08 13:39:52 +01:00
|
|
|
if (!g_pCompositor->windowValidMapped(header.pWindow))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (header.pWindow->m_bIsFloating)
|
|
|
|
return 0;
|
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
const auto PNODE = getNodeFromWindow(header.pWindow);
|
2022-11-08 13:39:52 +01:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto WINDOWS = getNodesOnWorkspace(header.pWindow->workspaceID());
|
|
|
|
const auto MASTERS = getMastersOnWorkspace(header.pWindow->workspaceID());
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto SMALLSPLIT = CConfigValue<Hyprlang::INT>("master:allow_small_split");
|
2022-11-08 13:39:52 +01:00
|
|
|
|
2024-03-03 19:39:20 +01:00
|
|
|
if (MASTERS + 2 > WINDOWS && *SMALLSPLIT == 0)
|
2022-11-08 13:39:52 +01:00
|
|
|
return 0;
|
2024-03-13 03:09:20 +01:00
|
|
|
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
2022-12-12 15:34:52 +01:00
|
|
|
|
2022-11-08 13:39:52 +01:00
|
|
|
if (!PNODE || PNODE->isMaster) {
|
|
|
|
// first non-master node
|
|
|
|
for (auto& n : m_lMasterNodesData) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (n.workspaceID == header.pWindow->workspaceID() && !n.isMaster) {
|
2022-11-08 13:39:52 +01:00
|
|
|
n.isMaster = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PNODE->isMaster = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
recalculateMonitor(header.pWindow->m_iMonitorID);
|
|
|
|
|
2023-02-10 20:13:38 +01:00
|
|
|
} else if (command == "removemaster") {
|
2022-11-08 13:39:52 +01:00
|
|
|
|
|
|
|
if (!g_pCompositor->windowValidMapped(header.pWindow))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (header.pWindow->m_bIsFloating)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
const auto PNODE = getNodeFromWindow(header.pWindow);
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto WINDOWS = getNodesOnWorkspace(header.pWindow->workspaceID());
|
|
|
|
const auto MASTERS = getMastersOnWorkspace(header.pWindow->workspaceID());
|
2022-11-08 13:39:52 +01:00
|
|
|
|
|
|
|
if (WINDOWS < 2 || MASTERS < 2)
|
|
|
|
return 0;
|
|
|
|
|
2024-03-13 03:09:20 +01:00
|
|
|
g_pCompositor->setWindowFullscreen(header.pWindow, false, FULLSCREEN_FULL);
|
2022-12-12 15:34:52 +01:00
|
|
|
|
2022-11-08 13:39:52 +01:00
|
|
|
if (!PNODE || !PNODE->isMaster) {
|
|
|
|
// first non-master node
|
2023-03-01 15:06:52 +01:00
|
|
|
for (auto& nd : m_lMasterNodesData | std::views::reverse) {
|
2024-04-02 21:32:39 +02:00
|
|
|
if (nd.workspaceID == header.pWindow->workspaceID() && nd.isMaster) {
|
2023-03-01 15:06:52 +01:00
|
|
|
nd.isMaster = false;
|
2022-11-08 13:39:52 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
PNODE->isMaster = false;
|
|
|
|
}
|
|
|
|
|
2022-12-10 22:59:16 +01:00
|
|
|
recalculateMonitor(header.pWindow->m_iMonitorID);
|
2023-02-27 00:12:14 +01:00
|
|
|
} else if (command == "orientationleft" || command == "orientationright" || command == "orientationtop" || command == "orientationbottom" || command == "orientationcenter") {
|
2022-12-10 22:59:16 +01:00
|
|
|
const auto PWINDOW = header.pWindow;
|
|
|
|
|
|
|
|
if (!PWINDOW)
|
|
|
|
return 0;
|
|
|
|
|
2024-03-13 03:09:20 +01:00
|
|
|
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
2022-12-12 15:34:52 +01:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->workspaceID());
|
2022-12-10 22:59:16 +01:00
|
|
|
|
2023-02-10 20:13:38 +01:00
|
|
|
if (command == "orientationleft")
|
2022-12-10 22:59:16 +01:00
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_LEFT;
|
2023-02-10 20:13:38 +01:00
|
|
|
else if (command == "orientationright")
|
2022-12-10 22:59:16 +01:00
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_RIGHT;
|
2023-02-10 20:13:38 +01:00
|
|
|
else if (command == "orientationtop")
|
2022-12-10 22:59:16 +01:00
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_TOP;
|
2023-02-10 20:13:38 +01:00
|
|
|
else if (command == "orientationbottom")
|
2022-12-10 22:59:16 +01:00
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM;
|
2023-02-27 00:12:14 +01:00
|
|
|
else if (command == "orientationcenter")
|
|
|
|
PWORKSPACEDATA->orientation = ORIENTATION_CENTER;
|
2022-12-10 22:59:16 +01:00
|
|
|
|
|
|
|
recalculateMonitor(header.pWindow->m_iMonitorID);
|
|
|
|
|
2023-02-10 20:13:38 +01:00
|
|
|
} else if (command == "orientationnext") {
|
2023-09-04 16:45:58 +02:00
|
|
|
runOrientationCycle(header, nullptr, 1);
|
|
|
|
} else if (command == "orientationprev") {
|
|
|
|
runOrientationCycle(header, nullptr, -1);
|
|
|
|
} else if (command == "orientationcycle") {
|
|
|
|
runOrientationCycle(header, &vars, 1);
|
2023-09-15 13:03:05 +02:00
|
|
|
} else if (command == "mfact") {
|
|
|
|
if (vars.size() >= 2) {
|
|
|
|
float newMfact = 0;
|
|
|
|
try {
|
|
|
|
newMfact = std::stof(vars[1]);
|
|
|
|
} catch (std::exception& e) {
|
|
|
|
Debug::log(ERR, "Argument is invalid: {}", e.what());
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
|
|
|
if (nd.isMaster)
|
|
|
|
nd.percMaster = std::clamp(newMfact, 0.05f, 0.95f);
|
|
|
|
}
|
|
|
|
}
|
2023-12-22 12:37:38 +01:00
|
|
|
} else if (command == "rollnext") {
|
|
|
|
const auto PWINDOW = header.pWindow;
|
|
|
|
const auto PNODE = getNodeFromWindow(PWINDOW);
|
|
|
|
|
2024-01-02 22:18:30 +01:00
|
|
|
if (!PNODE)
|
|
|
|
return 0;
|
|
|
|
|
2024-01-04 16:17:17 +01:00
|
|
|
const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID);
|
|
|
|
if (!OLDMASTER)
|
|
|
|
return 0;
|
|
|
|
|
2023-12-22 12:37:38 +01:00
|
|
|
const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER);
|
|
|
|
|
|
|
|
for (auto& nd : m_lMasterNodesData) {
|
|
|
|
if (nd.workspaceID == PNODE->workspaceID && !nd.isMaster) {
|
|
|
|
nd.isMaster = true;
|
|
|
|
const auto NEWMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), nd);
|
|
|
|
m_lMasterNodesData.splice(OLDMASTERIT, m_lMasterNodesData, NEWMASTERIT);
|
|
|
|
switchToWindow(nd.pWindow);
|
|
|
|
OLDMASTER->isMaster = false;
|
|
|
|
m_lMasterNodesData.splice(m_lMasterNodesData.end(), m_lMasterNodesData, OLDMASTERIT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
recalculateMonitor(PWINDOW->m_iMonitorID);
|
|
|
|
} else if (command == "rollprev") {
|
|
|
|
const auto PWINDOW = header.pWindow;
|
|
|
|
const auto PNODE = getNodeFromWindow(PWINDOW);
|
|
|
|
|
2024-01-02 22:18:30 +01:00
|
|
|
if (!PNODE)
|
|
|
|
return 0;
|
|
|
|
|
2024-01-04 16:17:17 +01:00
|
|
|
const auto OLDMASTER = PNODE->isMaster ? PNODE : getMasterNodeOnWorkspace(PNODE->workspaceID);
|
|
|
|
if (!OLDMASTER)
|
|
|
|
return 0;
|
|
|
|
|
2023-12-22 12:37:38 +01:00
|
|
|
const auto OLDMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), *OLDMASTER);
|
|
|
|
|
|
|
|
for (auto& nd : m_lMasterNodesData | std::views::reverse) {
|
|
|
|
if (nd.workspaceID == PNODE->workspaceID && !nd.isMaster) {
|
|
|
|
nd.isMaster = true;
|
|
|
|
const auto NEWMASTERIT = std::find(m_lMasterNodesData.begin(), m_lMasterNodesData.end(), nd);
|
|
|
|
m_lMasterNodesData.splice(OLDMASTERIT, m_lMasterNodesData, NEWMASTERIT);
|
|
|
|
switchToWindow(nd.pWindow);
|
|
|
|
OLDMASTER->isMaster = false;
|
|
|
|
m_lMasterNodesData.splice(m_lMasterNodesData.begin(), m_lMasterNodesData, OLDMASTERIT);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
recalculateMonitor(PWINDOW->m_iMonitorID);
|
2023-09-04 16:45:58 +02:00
|
|
|
}
|
2022-12-10 22:59:16 +01:00
|
|
|
|
2023-09-04 16:45:58 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2022-12-12 15:34:52 +01:00
|
|
|
|
2023-09-04 16:45:58 +02:00
|
|
|
// If vars is null, we use the default list
|
|
|
|
void CHyprMasterLayout::runOrientationCycle(SLayoutMessageHeader& header, CVarList* vars, int direction) {
|
|
|
|
std::vector<eOrientation> cycle;
|
|
|
|
if (vars != nullptr)
|
|
|
|
buildOrientationCycleVectorFromVars(cycle, *vars);
|
2022-12-10 22:59:16 +01:00
|
|
|
|
2023-09-04 16:45:58 +02:00
|
|
|
if (cycle.size() == 0)
|
|
|
|
buildOrientationCycleVectorFromEOperation(cycle);
|
2022-12-10 22:59:16 +01:00
|
|
|
|
2023-09-04 16:45:58 +02:00
|
|
|
const auto PWINDOW = header.pWindow;
|
2022-12-10 22:59:16 +01:00
|
|
|
|
2023-09-04 16:45:58 +02:00
|
|
|
if (!PWINDOW)
|
|
|
|
return;
|
2022-12-10 22:59:16 +01:00
|
|
|
|
2024-03-13 03:09:20 +01:00
|
|
|
g_pCompositor->setWindowFullscreen(PWINDOW, false, FULLSCREEN_FULL);
|
2022-12-12 15:34:52 +01:00
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->workspaceID());
|
2022-12-10 22:59:16 +01:00
|
|
|
|
2023-09-04 16:45:58 +02:00
|
|
|
int nextOrPrev = 0;
|
|
|
|
for (size_t i = 0; i < cycle.size(); ++i) {
|
|
|
|
if (PWORKSPACEDATA->orientation == cycle.at(i)) {
|
|
|
|
nextOrPrev = i + direction;
|
|
|
|
break;
|
2022-12-10 22:59:16 +01:00
|
|
|
}
|
2023-09-04 16:45:58 +02:00
|
|
|
}
|
2022-12-10 22:59:16 +01:00
|
|
|
|
2023-09-04 16:45:58 +02:00
|
|
|
if (nextOrPrev >= (int)cycle.size())
|
|
|
|
nextOrPrev = nextOrPrev % (int)cycle.size();
|
|
|
|
else if (nextOrPrev < 0)
|
|
|
|
nextOrPrev = cycle.size() + (nextOrPrev % (int)cycle.size());
|
|
|
|
|
|
|
|
PWORKSPACEDATA->orientation = cycle.at(nextOrPrev);
|
|
|
|
recalculateMonitor(header.pWindow->m_iMonitorID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CHyprMasterLayout::buildOrientationCycleVectorFromEOperation(std::vector<eOrientation>& cycle) {
|
|
|
|
for (int i = 0; i <= ORIENTATION_CENTER; ++i) {
|
|
|
|
cycle.push_back((eOrientation)i);
|
2022-08-24 21:50:48 +02:00
|
|
|
}
|
2023-09-04 16:45:58 +02:00
|
|
|
}
|
2022-08-24 21:50:48 +02:00
|
|
|
|
2023-09-04 16:45:58 +02:00
|
|
|
void CHyprMasterLayout::buildOrientationCycleVectorFromVars(std::vector<eOrientation>& cycle, CVarList& vars) {
|
|
|
|
for (size_t i = 1; i < vars.size(); ++i) {
|
|
|
|
if (vars[i] == "top") {
|
|
|
|
cycle.push_back(ORIENTATION_TOP);
|
|
|
|
} else if (vars[i] == "right") {
|
|
|
|
cycle.push_back(ORIENTATION_RIGHT);
|
|
|
|
} else if (vars[i] == "bottom") {
|
|
|
|
cycle.push_back(ORIENTATION_BOTTOM);
|
|
|
|
} else if (vars[i] == "left") {
|
|
|
|
cycle.push_back(ORIENTATION_LEFT);
|
|
|
|
} else if (vars[i] == "center") {
|
|
|
|
cycle.push_back(ORIENTATION_CENTER);
|
|
|
|
}
|
|
|
|
}
|
2022-07-16 15:57:31 +02:00
|
|
|
}
|
|
|
|
|
2023-02-19 22:07:32 +01:00
|
|
|
void CHyprMasterLayout::replaceWindowDataWith(CWindow* from, CWindow* to) {
|
|
|
|
const auto PNODE = getNodeFromWindow(from);
|
|
|
|
|
|
|
|
if (!PNODE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
PNODE->pWindow = to;
|
|
|
|
|
|
|
|
applyNodeDataToWindow(PNODE);
|
|
|
|
}
|
|
|
|
|
2024-03-29 01:43:50 +01:00
|
|
|
Vector2D CHyprMasterLayout::predictSizeForNewWindowTiled() {
|
2024-03-03 19:39:20 +01:00
|
|
|
static auto PNEWISMASTER = CConfigValue<Hyprlang::INT>("master:new_is_master");
|
2024-02-28 12:45:43 +01:00
|
|
|
|
|
|
|
if (!g_pCompositor->m_pLastMonitor)
|
|
|
|
return {};
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const int NODES = getNodesOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID);
|
2024-02-28 12:45:43 +01:00
|
|
|
|
|
|
|
if (NODES <= 0)
|
|
|
|
return g_pCompositor->m_pLastMonitor->vecSize;
|
|
|
|
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto MASTER = getMasterNodeOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID);
|
2024-02-28 12:45:43 +01:00
|
|
|
if (!MASTER) // wtf
|
|
|
|
return {};
|
|
|
|
|
|
|
|
if (*PNEWISMASTER) {
|
|
|
|
return MASTER->size;
|
|
|
|
} else {
|
2024-04-02 21:32:39 +02:00
|
|
|
const auto SLAVES = NODES - getMastersOnWorkspace(g_pCompositor->m_pLastMonitor->activeWorkspace->m_iID);
|
2024-02-28 12:45:43 +01:00
|
|
|
|
|
|
|
// TODO: make this better
|
|
|
|
return {g_pCompositor->m_pLastMonitor->vecSize.x - MASTER->size.x, g_pCompositor->m_pLastMonitor->vecSize.y / (SLAVES + 1)};
|
|
|
|
}
|
|
|
|
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2022-07-16 15:57:31 +02:00
|
|
|
void CHyprMasterLayout::onEnable() {
|
|
|
|
for (auto& w : g_pCompositor->m_vWindows) {
|
2023-12-17 21:00:18 +01:00
|
|
|
if (w->m_bIsFloating || !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
|
|
|
}
|