Skip to content

Commit

Permalink
Implement orientation (placement of master area) for master layout (h…
Browse files Browse the repository at this point in the history
…yprwm#1202)

* Implemented choosing placement of master area (hyprwm#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'
  • Loading branch information
proycon authored and scorpion-26 committed Dec 15, 2022
1 parent 7b02118 commit 4f372d5
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 20 deletions.
1 change: 1 addition & 0 deletions src/config/ConfigManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/Workspace.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,4 @@ class CWorkspace {
void moveToMonitor(const int&);

CWindow* getLastFocusedWindow();
};
};
173 changes: 156 additions & 17 deletions src/layout/MasterLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";
}
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
}

Expand Down
25 changes: 23 additions & 2 deletions src/layout/MasterLayout.hpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
#pragma once

#include "IHyprLayout.hpp"
#include <vector>
#include <list>
#include <deque>

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;
Expand All @@ -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*);
Expand All @@ -44,17 +62,20 @@ class CHyprMasterLayout : public IHyprLayout {

private:

std::list<SMasterNodeData> m_lMasterNodesData;
std::list<SMasterNodeData> m_lMasterNodesData;
std::vector<SMasterWorkspaceData> m_lMasterWorkspacesData;

bool m_bForceWarps = false;

int getNodesOnWorkspace(const int&);
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;
};
friend struct SMasterWorkspaceData;
};

0 comments on commit 4f372d5

Please sign in to comment.