mirror of
https://github.com/hyprwm/Hypr.git
synced 2024-11-25 22:35:58 +01:00
Added a master layout (configurable)
This commit is contained in:
parent
1f317f2ebc
commit
4e4d7870a3
8 changed files with 263 additions and 46 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
EXPOSED_MEMBER(Dirty, bool, b);
|
||||
|
||||
void setDirtyRecursive(bool);
|
||||
// ONLY for dwindle layout!
|
||||
void recalcSizePosRecursive();
|
||||
|
||||
EXPOSED_MEMBER(Size, Vector2D, vec);
|
||||
|
@ -70,6 +71,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:
|
||||
|
||||
|
|
|
@ -732,21 +732,27 @@ void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) {
|
|||
// Get the parent and both children, one of which will be pWindow
|
||||
const auto PPARENT = getWindowFromDrawable(pWindow->getParentNodeID());
|
||||
|
||||
if (!PPARENT) {
|
||||
// New window on this workspace.
|
||||
// Open a fullscreen window.
|
||||
const auto MONITOR = getMonitorFromWindow(pWindow);
|
||||
if (!MONITOR) {
|
||||
const auto PMONITOR = getMonitorFromWindow(pWindow);
|
||||
if (!PMONITOR) {
|
||||
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));
|
||||
if (!PPARENT) {
|
||||
// New window on this workspace.
|
||||
// Open a fullscreen window.
|
||||
|
||||
pWindow->setSize(Vector2D(PMONITOR->vecSize.x, PMONITOR->vecSize.y));
|
||||
pWindow->setPosition(Vector2D(PMONITOR->vecPosition.x, PMONITOR->vecPosition.y));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch (ConfigManager::getInt("layout"))
|
||||
{
|
||||
case LAYOUT_DWINDLE:
|
||||
{
|
||||
// Get the sibling
|
||||
const auto PSIBLING = getWindowFromDrawable(PPARENT->getChildNodeAID() == pWindow->getDrawable() ? PPARENT->getChildNodeBID() : PPARENT->getChildNodeAID());
|
||||
|
||||
|
@ -754,7 +760,6 @@ void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) {
|
|||
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));
|
||||
|
@ -769,13 +774,129 @@ void CWindowManager::calculateNewTileSetOldTile(CWindow* pWindow) {
|
|||
|
||||
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));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int CWindowManager::getWindowsOnWorkspace(const int& workspace) {
|
||||
int number = 0;
|
||||
for (auto& w : windows) {
|
||||
if (w.getWorkspaceID() == workspace && w.getDrawable() > 0) {
|
||||
++number;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Values[0] = XCB_STACK_MODE_BELOW;
|
||||
xcb_configure_window(DisplayConnection, pWindow->getDrawable(), XCB_CONFIG_WINDOW_STACK_MODE, Values);
|
||||
}
|
||||
|
||||
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,10 +1084,13 @@ 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
|
||||
|
@ -938,10 +1101,19 @@ void CWindowManager::fixWindowOnClose(CWindow* pClosedWindow) {
|
|||
getWindowFromDrawable(PPARENT->getParentNodeID())->setChildNodeBID(PSIBLING->getDrawable());
|
||||
}
|
||||
}
|
||||
// TREE FIXED ----
|
||||
|
||||
// Make the sibling eat the closed window
|
||||
PSIBLING->setDirtyRecursive(true);
|
||||
// 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());
|
||||
|
@ -1438,3 +1610,9 @@ void CWindowManager::refocusWindowOnClosed() {
|
|||
|
||||
setFocusedWindow(PWINDOW->getDrawable());
|
||||
}
|
||||
|
||||
void CWindowManager::recalcAllWorkspaces() {
|
||||
for (auto& workspace : workspaces) {
|
||||
recalcEntireWorkspace(workspace.getID());
|
||||
}
|
||||
}
|
|
@ -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>();
|
||||
|
|
Loading…
Reference in a new issue