Added a master layout (configurable)

This commit is contained in:
vaxerski 2021-12-04 23:16:24 +01:00
parent 1f317f2ebc
commit 4e4d7870a3
8 changed files with 263 additions and 46 deletions

View file

@ -8,6 +8,7 @@ border_size=1
gaps_out=20
rounding=0
max_fps=60 # max fps for updates of config & animations
layout=0 # 0 - dwindle (default), 1 - master
# Execs

View file

@ -15,6 +15,8 @@ void ConfigManager::init() {
configValues["gaps_out"].intValue = 20;
configValues["rounding"].intValue = 5;
configValues["layout"].intValue = LAYOUT_DWINDLE;
configValues["max_fps"].intValue = 60;
configValues["bar:monitor"].intValue = 0;
@ -324,7 +326,8 @@ void ConfigManager::loadConfigLoadVars() {
ifs.close();
}
g_pWindowManager->setAllWindowsDirty();
// recalc all workspaces
g_pWindowManager->recalcAllWorkspaces();
// Reload the bar as well, don't load it before the default is loaded.
if (loadBar && g_pWindowManager->statusBar) {
@ -332,6 +335,12 @@ void ConfigManager::loadConfigLoadVars() {
g_pWindowManager->statusBar->setup(configValues["bar:monitor"].intValue);
}
// Ensure correct layout
if (configValues["layout"].intValue < 0 || configValues["layout"].intValue > 1) {
Debug::log(ERR, "Invalid layout ID, falling back to 0.");
configValues["layout"].intValue = 0;
}
loadBar = true;
isFirstLaunch = false;
}

View file

@ -3,6 +3,11 @@
#include <map>
#include "../utilities/Debug.hpp"
enum ELayouts {
LAYOUT_DWINDLE = 0,
LAYOUT_MASTER
};
struct SConfigValue {
int64_t intValue = -1;
float floatValue = -1;

View file

@ -280,17 +280,28 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) {
window.setParentNodeID(0);
}
// Also sets the old one
g_pWindowManager->calculateNewWindowParams(&window);
// For master layout, add the index
window.setMasterChildIndex(g_pWindowManager->getWindowsOnWorkspace(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) - 1);
// and set master if needed
if (g_pWindowManager->getWindowsOnWorkspace(g_pWindowManager->activeWorkspaces[CURRENTSCREEN]) == 0)
window.setMaster(true);
// Set real size. No animations in the beginning. Maybe later. TODO?
window.setRealPosition(window.getEffectivePosition());
window.setRealSize(window.getEffectiveSize());
// Add to arr
g_pWindowManager->addWindowToVectorSafe(window);
Debug::log(LOG, "Created a new tiled window! X: " + std::to_string(window.getPosition().x) + ", Y: " + std::to_string(window.getPosition().y) + ", W: " + std::to_string(window.getSize().x) + ", H:" + std::to_string(window.getSize().y) + " ID: " + std::to_string(windowID));
// Now we need to modify the copy in the array.
const auto PWINDOWINARR = g_pWindowManager->getWindowFromDrawable(windowID);
// Also sets the old one
g_pWindowManager->calculateNewWindowParams(PWINDOWINARR);
// Set real size. No animations in the beginning. Maybe later. TODO?
PWINDOWINARR->setRealPosition(PWINDOWINARR->getEffectivePosition());
PWINDOWINARR->setRealSize(PWINDOWINARR->getEffectiveSize());
Debug::log(LOG, "Created a new tiled window! X: " + std::to_string(PWINDOWINARR->getPosition().x) + ", Y: " + std::to_string(PWINDOWINARR->getPosition().y) + ", W: " + std::to_string(PWINDOWINARR->getSize().x) + ", H:" + std::to_string(PWINDOWINARR->getSize().y) + " ID: " + std::to_string(windowID));
// Set map values
g_pWindowManager->Values[0] = XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_FOCUS_CHANGE;
@ -301,7 +312,7 @@ CWindow* Events::remapWindow(int windowID, bool wasfloating, int forcemonitor) {
// Make all floating windows above
g_pWindowManager->setAllFloatingWindowsTop();
return g_pWindowManager->getWindowFromDrawable(windowID);
return PWINDOWINARR;
}
void Events::eventMapWindow(xcb_generic_event_t* event) {

View file

@ -1,7 +1,7 @@
#include "window.hpp"
#include "windowManager.hpp"
CWindow::CWindow() { this->setCanKill(false); this->setImmovable(false); this->setNoInterventions(false); this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); this->setParentNodeID(0); this->setChildNodeAID(0); this->setChildNodeBID(0); this->setName(""); }
CWindow::CWindow() { this->setDead(false); this->setMasterChildIndex(0); this->setMaster(false); this->setCanKill(false); this->setImmovable(false); this->setNoInterventions(false); this->setDirty(true); this->setFullscreen(false); this->setIsFloating(false); this->setParentNodeID(0); this->setChildNodeAID(0); this->setChildNodeBID(0); this->setName(""); }
CWindow::~CWindow() { }
void CWindow::generateNodeID() {

View file

@ -39,6 +39,7 @@ public:
EXPOSED_MEMBER(Dirty, bool, b);
void setDirtyRecursive(bool);
// ONLY for dwindle layout!
void recalcSizePosRecursive();
EXPOSED_MEMBER(Size, Vector2D, vec);
@ -69,6 +70,11 @@ public:
// ICCCM
EXPOSED_MEMBER(CanKill, bool, b);
// Master layout
EXPOSED_MEMBER(Master, bool, b);
EXPOSED_MEMBER(MasterChildIndex, int, i);
EXPOSED_MEMBER(Dead, bool, b);
private:

View file

@ -732,50 +732,171 @@ void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) {
// Get the parent and both children, one of which will be pWindow
const auto PPARENT = getWindowFromDrawable(pWindow->getParentNodeID());
const auto PMONITOR = getMonitorFromWindow(pWindow);
if (!PMONITOR) {
Debug::log(ERR, "Monitor was nullptr! (calculateNewTileSetOldTile)");
return;
}
if (!PPARENT) {
// New window on this workspace.
// Open a fullscreen window.
const auto MONITOR = getMonitorFromWindow(pWindow);
if (!MONITOR) {
Debug::log(ERR, "Monitor was nullptr! (calculateNewTileSetOldTile)");
return;
}
pWindow->setSize(Vector2D(MONITOR->vecSize.x, MONITOR->vecSize.y));
pWindow->setPosition(Vector2D(MONITOR->vecPosition.x, MONITOR->vecPosition.y));
pWindow->setSize(Vector2D(PMONITOR->vecSize.x, PMONITOR->vecSize.y));
pWindow->setPosition(Vector2D(PMONITOR->vecPosition.x, PMONITOR->vecPosition.y));
return;
}
// Get the sibling
const auto PSIBLING = getWindowFromDrawable(PPARENT->getChildNodeAID() == pWindow->getDrawable() ? PPARENT->getChildNodeBID() : PPARENT->getChildNodeAID());
// Should NEVER be null
if (PSIBLING) {
const auto PLASTSIZE = PPARENT->getSize();
const auto PLASTPOS = PPARENT->getPosition();
switch (ConfigManager::getInt("layout"))
{
case LAYOUT_DWINDLE:
{
// Get the sibling
const auto PSIBLING = getWindowFromDrawable(PPARENT->getChildNodeAID() == pWindow->getDrawable() ? PPARENT->getChildNodeBID() : PPARENT->getChildNodeAID());
if (PLASTSIZE.x > PLASTSIZE.y) {
PSIBLING->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y));
PSIBLING->setSize(Vector2D(PLASTSIZE.x / 2.f, PLASTSIZE.y));
pWindow->setSize(Vector2D(PLASTSIZE.x / 2.f, PLASTSIZE.y));
pWindow->setPosition(Vector2D(PLASTPOS.x + PLASTSIZE.x / 2.f, PLASTPOS.y));
} else {
PSIBLING->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y));
PSIBLING->setSize(Vector2D(PLASTSIZE.x, PLASTSIZE.y / 2.f));
pWindow->setSize(Vector2D(PLASTSIZE.x, PLASTSIZE.y / 2.f));
pWindow->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y + PLASTSIZE.y / 2.f));
// Should NEVER be null
if (PSIBLING) {
const auto PLASTSIZE = PPARENT->getSize();
const auto PLASTPOS = PPARENT->getPosition();
if (PLASTSIZE.x > PLASTSIZE.y) {
PSIBLING->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y));
PSIBLING->setSize(Vector2D(PLASTSIZE.x / 2.f, PLASTSIZE.y));
pWindow->setSize(Vector2D(PLASTSIZE.x / 2.f, PLASTSIZE.y));
pWindow->setPosition(Vector2D(PLASTPOS.x + PLASTSIZE.x / 2.f, PLASTPOS.y));
} else {
PSIBLING->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y));
PSIBLING->setSize(Vector2D(PLASTSIZE.x, PLASTSIZE.y / 2.f));
pWindow->setSize(Vector2D(PLASTSIZE.x, PLASTSIZE.y / 2.f));
pWindow->setPosition(Vector2D(PLASTPOS.x, PLASTPOS.y + PLASTSIZE.y / 2.f));
}
PSIBLING->setDirty(true);
} else {
Debug::log(ERR, "Sibling node was null?? pWindow x,y,w,h: " + std::to_string(pWindow->getPosition().x) + " " + std::to_string(pWindow->getPosition().y) + " " + std::to_string(pWindow->getSize().x) + " " + std::to_string(pWindow->getSize().y));
}
}
break;
case LAYOUT_MASTER:
{
recalcEntireWorkspace(pWindow->getWorkspaceID());
}
break;
}
}
PSIBLING->setDirty(true);
} else {
Debug::log(ERR, "Sibling node was null?? pWindow x,y,w,h: " + std::to_string(pWindow->getPosition().x) + " "
+ std::to_string(pWindow->getPosition().y) + " " + std::to_string(pWindow->getSize().x) + " "
+ std::to_string(pWindow->getSize().y));
int CWindowManager::getWindowsOnWorkspace(const int& workspace) {
int number = 0;
for (auto& w : windows) {
if (w.getWorkspaceID() == workspace && w.getDrawable() > 0) {
++number;
}
}
Values[0] = XCB_STACK_MODE_BELOW;
xcb_configure_window(DisplayConnection, pWindow->getDrawable(), XCB_CONFIG_WINDOW_STACK_MODE, Values);
return number;
}
SMonitor* CWindowManager::getMonitorFromWorkspace(const int& workspace) {
int monitorID = -1;
for (auto& work : workspaces) {
if (work.getID() == workspace) {
monitorID = work.getMonitor();
break;
}
}
for (auto& monitor : monitors) {
if (monitor.ID == monitorID) {
return &monitor;
}
}
return nullptr;
}
void CWindowManager::recalcEntireWorkspace(const int& workspace) {
switch (ConfigManager::getInt("layout"))
{
case LAYOUT_MASTER:
{
// Get the monitor
const auto PMONITOR = getMonitorFromWorkspace(workspace);
// first, calc the size
CWindow* pMaster = nullptr;
for (auto& w : windows) {
if (w.getWorkspaceID() == workspace && w.getMaster() && !w.getDead()) {
pMaster = &w;
break;
}
}
if (!pMaster) {
Debug::log(ERR, "No master found on workspace???");
return;
}
// set the xy for master
pMaster->setPosition(Vector2D(0, 0) + PMONITOR->vecPosition);
pMaster->setSize(Vector2D(PMONITOR->vecSize.x / 2, PMONITOR->vecSize.y));
// get children sorted
std::vector<CWindow*> children;
for (auto& w : windows) {
if (w.getWorkspaceID() == workspace && !w.getMaster() && w.getDrawable() > 0 && !w.getDead())
children.push_back(&w);
}
std::sort(children.begin(), children.end(), [](CWindow*& a, CWindow*& b) {
return a->getMasterChildIndex() < b->getMasterChildIndex();
});
// if no children, master full
if (children.size() == 0) {
pMaster->setPosition(Vector2D(0, 0) + PMONITOR->vecPosition);
pMaster->setSize(Vector2D(PMONITOR->vecSize.x, PMONITOR->vecSize.y));
}
// Children sorted, set xy
int yoff = 0;
for (const auto& child : children) {
child->setPosition(Vector2D(PMONITOR->vecSize.x / 2, yoff) + PMONITOR->vecPosition);
child->setSize(Vector2D(PMONITOR->vecSize.x / 2, PMONITOR->vecSize.y / children.size()));
yoff += PMONITOR->vecSize.y / children.size();
}
// done
setAllWorkspaceWindowsDirtyByID(workspace);
}
break;
case LAYOUT_DWINDLE:
{
// get the master on the workspace
CWindow* pMasterWindow = nullptr;
for (auto& w : windows) {
if (w.getWorkspaceID() == workspace && w.getParentNodeID() == 0) {
pMasterWindow = &w;
break;
}
}
if (!pMasterWindow) {
return;
}
pMasterWindow->recalcSizePosRecursive();
setAllWorkspaceWindowsDirtyByID(workspace);
}
break;
default:
break;
}
}
void CWindowManager::calculateNewFloatingWindow(CWindow* pWindow) {
@ -906,6 +1027,45 @@ void CWindowManager::closeWindowAllChecks(int64_t id) {
g_pWindowManager->removeWindowFromVectorSafe(id);
}
void CWindowManager::fixMasterWorkspaceOnClosed(CWindow* pWindow) {
// get children and master
CWindow* pMaster = nullptr;
for (auto& w : windows) {
if (w.getWorkspaceID() == pWindow->getWorkspaceID() && w.getMaster()) {
pMaster = &w;
break;
}
}
if (!pMaster) {
Debug::log(ERR, "No master found on workspace???");
return;
}
// get children sorted
std::vector<CWindow*> children;
for (auto& w : windows) {
if (w.getWorkspaceID() == pWindow->getWorkspaceID() && !w.getMaster() && w.getDrawable() > 0 && w.getDrawable() != pWindow->getDrawable())
children.push_back(&w);
}
std::sort(children.begin(), children.end(), [](CWindow*& a, CWindow*& b) {
return a->getMasterChildIndex() < b->getMasterChildIndex();
});
// If closed window was master, set a new master.
if (pWindow->getMaster()) {
if (children.size() > 0) {
children[0]->setMaster(true);
}
} else {
// else fix the indices
for (long unsigned int i = pWindow->getMasterChildIndex() - 1; i < children.size(); ++i) {
// masterChildIndex = 1 for the first child
children[i]->setMasterChildIndex(i);
}
}
}
void CWindowManager::fixWindowOnClose(CWindow* pClosedWindow) {
if (!pClosedWindow)
return;
@ -924,13 +1084,16 @@ void CWindowManager::fixWindowOnClose(CWindow* pClosedWindow) {
return;
}
// used by master layout
pClosedWindow->setDead(true);
// FIX TREE ----
// make the sibling replace the parent
PSIBLING->setPosition(PPARENT->getPosition());
PSIBLING->setSize(PPARENT->getSize());
// make the sibling replace the parent
PSIBLING->setParentNodeID(PPARENT->getParentNodeID());
if (PPARENT->getParentNodeID() != 0
if (PPARENT->getParentNodeID() != 0
&& getWindowFromDrawable(PPARENT->getParentNodeID())) {
if (getWindowFromDrawable(PPARENT->getParentNodeID())->getChildNodeAID() == PPARENT->getDrawable()) {
getWindowFromDrawable(PPARENT->getParentNodeID())->setChildNodeAID(PSIBLING->getDrawable());
@ -938,11 +1101,20 @@ void CWindowManager::fixWindowOnClose(CWindow* pClosedWindow) {
getWindowFromDrawable(PPARENT->getParentNodeID())->setChildNodeBID(PSIBLING->getDrawable());
}
}
// TREE FIXED ----
// Make the sibling eat the closed window
PSIBLING->setDirtyRecursive(true);
PSIBLING->recalcSizePosRecursive();
// Fix master stuff
const auto WORKSPACE = pClosedWindow->getWorkspaceID();
fixMasterWorkspaceOnClosed(pClosedWindow);
// recalc the workspace
if (ConfigManager::getInt("layout") == LAYOUT_MASTER)
recalcEntireWorkspace(WORKSPACE);
else {
PSIBLING->recalcSizePosRecursive();
PSIBLING->setDirtyRecursive(true);
}
// Remove the parent
removeWindowFromVectorSafe(PPARENT->getDrawable());
@ -1437,4 +1609,10 @@ void CWindowManager::refocusWindowOnClosed() {
LastWindow = PWINDOW->getDrawable();
setFocusedWindow(PWINDOW->getDrawable());
}
void CWindowManager::recalcAllWorkspaces() {
for (auto& workspace : workspaces) {
recalcEntireWorkspace(workspace.getID());
}
}

View file

@ -106,6 +106,10 @@ public:
void updateActiveWindowName();
void updateBarInfo();
int getWindowsOnWorkspace(const int&);
void recalcAllWorkspaces();
private:
// Internal WM functions that don't have to be exposed
@ -122,6 +126,9 @@ public:
xcb_visualtype_t* setupColors(const int&);
void updateRootCursor();
void applyRoundedCornersToWindow(CWindow* pWindow);
SMonitor* getMonitorFromWorkspace(const int&);
void recalcEntireWorkspace(const int&);
void fixMasterWorkspaceOnClosed(CWindow* pWindow);
};
inline std::unique_ptr<CWindowManager> g_pWindowManager = std::make_unique<CWindowManager>();