From 4f372d5b25d4c303112c6bf7a381d1434a08a0f6 Mon Sep 17 00:00:00 2001 From: Maarten van Gompel Date: Sat, 10 Dec 2022 22:59:16 +0100 Subject: [PATCH] Implement orientation (placement of master area) for master layout (#1202) * Implemented choosing placement of master area (#1059) This implement a per workspace 'orientation' that can be set to left, right, top or bottom. Reflecting placement of the master area. Left (default) and right are horizontal layouts, top and bottom produce vertical layouts. Orientation can be switched with: 'hyprctl dispatch layoutmsg orientationleft' --- src/config/ConfigManager.cpp | 1 + src/helpers/Workspace.hpp | 2 +- src/layout/MasterLayout.cpp | 173 +++++++++++++++++++++++++++++++---- src/layout/MasterLayout.hpp | 25 ++++- 4 files changed, 181 insertions(+), 20 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 89152acca442..21659cf2fccd 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -109,6 +109,7 @@ void CConfigManager::setDefaultVars() { configValues["master:new_is_master"].intValue = 1; configValues["master:new_on_top"].intValue = 0; configValues["master:no_gaps_when_only"].intValue = 0; + configValues["master:orientation"].strValue = "left"; configValues["animations:enabled"].intValue = 1; configValues["animations:speed"].floatValue = 7.f; diff --git a/src/helpers/Workspace.hpp b/src/helpers/Workspace.hpp index e4243f921922..d093205ebd68 100644 --- a/src/helpers/Workspace.hpp +++ b/src/helpers/Workspace.hpp @@ -52,4 +52,4 @@ class CWorkspace { void moveToMonitor(const int&); CWindow* getLastFocusedWindow(); -}; \ No newline at end of file +}; diff --git a/src/layout/MasterLayout.cpp b/src/layout/MasterLayout.cpp index 25a2d61c3754..aa5f6a32e07d 100644 --- a/src/layout/MasterLayout.cpp +++ b/src/layout/MasterLayout.cpp @@ -30,6 +30,28 @@ int CHyprMasterLayout::getMastersOnWorkspace(const int& ws) { return no; } +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 + const auto PWORKSPACEDATA = &m_lMasterWorkspacesData.emplace_back(); + PWORKSPACEDATA->workspaceID = ws; + const auto orientation = &g_pConfigManager->getConfigValuePtr("master:orientation")->strValue; + if (*orientation == "top") { + PWORKSPACEDATA->orientation = ORIENTATION_TOP; + } else if (*orientation == "right") { + PWORKSPACEDATA->orientation = ORIENTATION_RIGHT; + } else if (*orientation == "bottom") { + PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM; + } else { + PWORKSPACEDATA->orientation = ORIENTATION_LEFT; + } + return PWORKSPACEDATA; +} + std::string CHyprMasterLayout::getLayoutName() { return "Master"; } @@ -187,6 +209,8 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { if (!PWORKSPACE) return; + const auto PWORKSPACEDATA = getMasterWorkspaceData(ws); + const auto PMONITOR = g_pCompositor->getMonitorFromID(PWORKSPACE->m_iMonitorID); const auto PMASTERNODE = getMasterNodeOnWorkspace(PWORKSPACE->m_iID); @@ -196,53 +220,119 @@ void CHyprMasterLayout::calculateWorkspace(const int& ws) { const auto MASTERS = getMastersOnWorkspace(PWORKSPACE->m_iID); + //compute placement of master window(s) 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 { + } else if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT || PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) { float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; int nodesLeft = MASTERS; float nextY = 0; + const float WIDTH = (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x) * PMASTERNODE->percMaster; for (auto& n : m_lMasterNodesData) { if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) { - n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY); + if (PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) { + n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMONITOR->vecSize.x - WIDTH, nextY); + } else { + 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); + n.size = Vector2D(WIDTH, HEIGHT); nodesLeft--; heightLeft -= HEIGHT; nextY += HEIGHT; + applyNodeDataToWindow(&n); + } + } + } else if (PWORKSPACEDATA->orientation == ORIENTATION_TOP || PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) { + float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x; + int nodesLeft = MASTERS; + float nextX = 0; + const float HEIGHT = (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y) * PMASTERNODE->percMaster; + + for (auto& n : m_lMasterNodesData) { + if (n.workspaceID == PWORKSPACE->m_iID && n.isMaster) { + if (PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) { + n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX,PMONITOR->vecSize.y - HEIGHT - PMONITOR->vecReservedBottomRight.y); + } else { + n.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0); + } + float WIDTH = nodesLeft > 1 ? widthLeft / nodesLeft * n.percSize : widthLeft; + if (WIDTH > widthLeft * 0.9f && nodesLeft > 1) + WIDTH = widthLeft * 0.9f; + n.size = Vector2D(WIDTH, HEIGHT); + + nodesLeft--; + widthLeft -= WIDTH; + nextX += WIDTH; + applyNodeDataToWindow(&n); } } } - float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; + + //compute placement of slave window(s) int slavesLeft = getNodesOnWorkspace(PWORKSPACE->m_iID) - MASTERS; - float nextY = 0; + if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT || PWORKSPACEDATA->orientation == ORIENTATION_RIGHT) { + float heightLeft = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y; + float nextY = 0; + const float WIDTH = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x - PMASTERNODE->size.x; - for (auto& nd : m_lMasterNodesData) { - if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) - continue; + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) + continue; + + if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT) { + nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMASTERNODE->percMaster * (PMONITOR->vecSize.x - PMONITOR->vecReservedTopLeft.x - PMONITOR->vecReservedBottomRight.x), nextY); + } else { + nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(0, nextY); + } + float HEIGHT = slavesLeft > 1 ? heightLeft / slavesLeft * nd.percSize : heightLeft; + if (HEIGHT > heightLeft * 0.9f && slavesLeft > 1) + HEIGHT = heightLeft * 0.9f; + nd.size = Vector2D(WIDTH, HEIGHT); - nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(PMASTERNODE->percMaster * PMONITOR->vecSize.x, nextY); - 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); + slavesLeft--; + heightLeft -= HEIGHT; + nextY += HEIGHT; - slavesLeft--; - heightLeft -= HEIGHT; - nextY += HEIGHT; + applyNodeDataToWindow(&nd); + } + } else if (PWORKSPACEDATA->orientation == ORIENTATION_TOP || PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) { + float widthLeft = PMONITOR->vecSize.x - PMONITOR->vecReservedBottomRight.x - PMONITOR->vecReservedTopLeft.x; + float nextX = 0; + const float HEIGHT = PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y - PMASTERNODE->size.y; + + for (auto& nd : m_lMasterNodesData) { + if (nd.workspaceID != PWORKSPACE->m_iID || nd.isMaster) + continue; + if (PWORKSPACEDATA->orientation == ORIENTATION_TOP) { + nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, PMASTERNODE->percMaster * (PMONITOR->vecSize.y - PMONITOR->vecReservedBottomRight.y - PMONITOR->vecReservedTopLeft.y)); + } else { + nd.position = PMONITOR->vecReservedTopLeft + PMONITOR->vecPosition + Vector2D(nextX, 0); + } + float WIDTH = slavesLeft > 1 ? widthLeft / slavesLeft * nd.percSize : widthLeft; + if (WIDTH > widthLeft * 0.9f && slavesLeft > 1) + WIDTH = widthLeft * 0.9f; + nd.size = Vector2D(WIDTH, HEIGHT); - applyNodeDataToWindow(&nd); + slavesLeft--; + widthLeft -= WIDTH; + nextX += WIDTH; + + applyNodeDataToWindow(&nd); + } } + + } void CHyprMasterLayout::applyNodeDataToWindow(SMasterNodeData* pNode) { @@ -752,6 +842,55 @@ std::any CHyprMasterLayout::layoutMessage(SLayoutMessageHeader header, std::stri PNODE->isMaster = false; } + recalculateMonitor(header.pWindow->m_iMonitorID); + } else if (message == "orientationleft" || message == "orientationright" || message == "orientationtop" || message == "orientationbottom") { + const auto PWINDOW = header.pWindow; + + if (!PWINDOW) + return 0; + + const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID); + + if (message == "orientationleft") + PWORKSPACEDATA->orientation = ORIENTATION_LEFT; + else if (message == "orientationright") + PWORKSPACEDATA->orientation = ORIENTATION_RIGHT; + else if (message == "orientationtop") + PWORKSPACEDATA->orientation = ORIENTATION_TOP; + else if (message == "orientationbottom") + PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM; + + recalculateMonitor(header.pWindow->m_iMonitorID); + + } else if (message == "orientationnext") { + const auto PWINDOW = header.pWindow; + + if (!PWINDOW) + return 0; + + const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID); + + if (PWORKSPACEDATA->orientation == ORIENTATION_BOTTOM) { + PWORKSPACEDATA->orientation = ORIENTATION_LEFT; + } else { + PWORKSPACEDATA->orientation = (eOrientation) (PWORKSPACEDATA->orientation + 1); + } + + recalculateMonitor(header.pWindow->m_iMonitorID); + } else if (message == "orientationprev") { + const auto PWINDOW = header.pWindow; + + if (!PWINDOW) + return 0; + + const auto PWORKSPACEDATA = getMasterWorkspaceData(PWINDOW->m_iWorkspaceID); + + if (PWORKSPACEDATA->orientation == ORIENTATION_LEFT) { + PWORKSPACEDATA->orientation = ORIENTATION_BOTTOM; + } else { + PWORKSPACEDATA->orientation = (eOrientation) (PWORKSPACEDATA->orientation - 1); + } + recalculateMonitor(header.pWindow->m_iMonitorID); } diff --git a/src/layout/MasterLayout.hpp b/src/layout/MasterLayout.hpp index 3e1744df75e0..b7761cefa9d9 100644 --- a/src/layout/MasterLayout.hpp +++ b/src/layout/MasterLayout.hpp @@ -1,11 +1,20 @@ #pragma once #include "IHyprLayout.hpp" +#include #include #include enum eFullscreenMode : uint8_t; +//orientation determines which side of the screen the master area resides +enum eOrientation : uint8_t { + ORIENTATION_LEFT = 0, + ORIENTATION_TOP, + ORIENTATION_RIGHT, + ORIENTATION_BOTTOM +}; + struct SMasterNodeData { bool isMaster = false; float percMaster = 0.5f; @@ -24,6 +33,15 @@ struct SMasterNodeData { } }; +struct SMasterWorkspaceData { + int workspaceID = -1; + eOrientation orientation = ORIENTATION_LEFT; + + bool operator==(const SMasterWorkspaceData& rhs) { + return workspaceID == rhs.workspaceID; + } +}; + class CHyprMasterLayout : public IHyprLayout { public: virtual void onWindowCreatedTiling(CWindow*); @@ -44,7 +62,8 @@ class CHyprMasterLayout : public IHyprLayout { private: - std::list m_lMasterNodesData; + std::list m_lMasterNodesData; + std::vector m_lMasterWorkspacesData; bool m_bForceWarps = false; @@ -52,9 +71,11 @@ class CHyprMasterLayout : public IHyprLayout { void applyNodeDataToWindow(SMasterNodeData*); SMasterNodeData* getNodeFromWindow(CWindow*); SMasterNodeData* getMasterNodeOnWorkspace(const int&); + SMasterWorkspaceData* getMasterWorkspaceData(const int&); void calculateWorkspace(const int&); CWindow* getNextWindow(CWindow*, bool); int getMastersOnWorkspace(const int&); friend struct SMasterNodeData; -}; \ No newline at end of file + friend struct SMasterWorkspaceData; +};