added a layoutmanager and basic dwindle

This commit is contained in:
vaxerski 2022-03-19 15:59:53 +01:00
parent e664b0b692
commit 61e10e2048
12 changed files with 308 additions and 16 deletions

View File

@ -109,6 +109,9 @@ void CCompositor::startCompositor() {
Debug::log(LOG, "Creating the XWaylandManager!");
g_pXWaylandManager = std::make_unique<CHyprXWaylandManager>();
Debug::log(LOG, "Creating the LayoutManager!");
g_pLayoutManager = std::make_unique<CLayoutManager>();
//
//
@ -185,7 +188,7 @@ bool CCompositor::windowExists(CWindow* pWindow) {
CWindow* CCompositor::vectorToWindow(const Vector2D& pos) {
for (auto& w : m_lWindows) {
wlr_box box = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
wlr_box box = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
if (wlr_box_contains_point(&box, pos.x, pos.y))
return &w;
}

View File

@ -11,10 +11,10 @@
#include "managers/ThreadManager.hpp"
#include "managers/XWaylandManager.hpp"
#include "managers/InputManager.hpp"
#include "managers/LayoutManager.hpp"
#include "helpers/Monitor.hpp"
#include "Window.hpp"
#include "render/Renderer.hpp"
class CCompositor {
public:
CCompositor();

View File

@ -12,3 +12,7 @@
#define DYNLISTENER(name) wl_listener listen_##name = { .notify = Events::listener_##name };
#define VECINRECT(vec, x1, y1, x2, y2) (vec.x >= (x1) && vec.x <= (x2) && vec.y >= (y1) && vec.y <= (y2))
#define interface class
#define STICKS(a, b) abs((a) - (b)) < 2

View File

@ -206,10 +206,8 @@ void Events::listener_mapWindow(wl_listener* listener, void* data) {
PWINDOW->m_iMonitorID = PMONITOR->ID;
PWINDOW->m_bMappedX11 = true;
// test
PWINDOW->m_vSize = PMONITOR->vecSize;
PWINDOW->m_vPosition = PMONITOR->vecPosition;
g_pXWaylandManager->setWindowSize(PWINDOW, PMONITOR->vecSize);
g_pLayoutManager->getCurrentLayout()->onWindowCreated(PWINDOW);
g_pCompositor->focusWindow(PWINDOW);
Debug::log(LOG, "Map request dispatched.");
@ -218,6 +216,8 @@ void Events::listener_mapWindow(wl_listener* listener, void* data) {
void Events::listener_unmapWindow(wl_listener* listener, void* data) {
CWindow* PWINDOW = wl_container_of(listener, PWINDOW, listen_unmapWindow);
g_pLayoutManager->getCurrentLayout()->onWindowRemoved(PWINDOW);
g_pCompositor->removeWindowFromVectorSafe(PWINDOW);
Debug::log(LOG, "Window %x unmapped", PWINDOW);

View File

@ -0,0 +1,202 @@
#include "DwindleLayout.hpp"
#include "../Compositor.hpp"
int CHyprDwindleLayout::getNodesOnMonitor(const int& id) {
int no = 0;
for (auto& n : m_lDwindleNodesData) {
if (n.monitorID == id)
++no;
}
return no;
}
SDwindleNodeData* CHyprDwindleLayout::getFirstNodeOnMonitor(const int& id) {
for (auto& n : m_lDwindleNodesData) {
if (n.monitorID == id)
return &n;
}
return nullptr;
}
SDwindleNodeData* CHyprDwindleLayout::getNodeFromWindow(CWindow* pWindow) {
for (auto& n : m_lDwindleNodesData) {
if (n.pWindow == pWindow)
return &n;
}
return nullptr;
}
void CHyprDwindleLayout::applyNodeDataToWindow(SDwindleNodeData* pNode) {
const auto PMONITOR = g_pCompositor->getMonitorFromID(pNode->monitorID);
if (!PMONITOR){
Debug::log(ERR, "Orphaned Node %x (monitor ID: %i)!!", pNode, pNode->monitorID);
return;
}
// Don't set nodes, only windows.
if (pNode->isNode)
return;
// for gaps outer
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 BORDERSIZE = g_pConfigManager->getInt("general:border_size");
const auto GAPSIN = g_pConfigManager->getInt("general:gaps_in");
const auto GAPSOUT = g_pConfigManager->getInt("general:gaps_out");
const auto PWINDOW = pNode->pWindow;
if (!g_pCompositor->windowValidMapped(PWINDOW)) {
Debug::log(ERR, "Node %x holding invalid window %x!!", pNode, PWINDOW);
return;
}
PWINDOW->m_vSize = pNode->size;
PWINDOW->m_vPosition = pNode->position;
PWINDOW->m_vEffectivePosition = PWINDOW->m_vPosition + Vector2D(BORDERSIZE, BORDERSIZE);
PWINDOW->m_vEffectiveSize = PWINDOW->m_vSize - Vector2D(2 * BORDERSIZE, 2 * BORDERSIZE);
const auto OFFSETTOPLEFT = Vector2D(DISPLAYLEFT ? GAPSOUT : GAPSIN,
DISPLAYTOP ? GAPSOUT : GAPSIN);
const auto OFFSETBOTTOMRIGHT = Vector2D(DISPLAYRIGHT ? GAPSOUT : GAPSIN,
DISPLAYBOTTOM ? GAPSOUT : GAPSIN);
PWINDOW->m_vEffectivePosition = PWINDOW->m_vEffectivePosition + OFFSETTOPLEFT;
PWINDOW->m_vEffectiveSize = PWINDOW->m_vEffectiveSize - OFFSETTOPLEFT - OFFSETBOTTOMRIGHT;
// TEMP: remove when anims added
PWINDOW->m_vRealPosition = PWINDOW->m_vEffectivePosition;
PWINDOW->m_vRealSize = PWINDOW->m_vEffectiveSize;
g_pXWaylandManager->setWindowSize(PWINDOW, PWINDOW->m_vRealSize);
}
void CHyprDwindleLayout::onWindowCreated(CWindow* pWindow) {
m_lDwindleNodesData.push_back(SDwindleNodeData());
const auto PNODE = &m_lDwindleNodesData.back();
if (pWindow->m_bIsFloating) {
// handle floating, TODO:
return;
}
// Populate the node with our window's data
PNODE->monitorID = pWindow->m_iMonitorID;
PNODE->pWindow = pWindow;
PNODE->isNode = false;
const auto PMONITOR = g_pCompositor->getMonitorFromID(PNODE->monitorID);
// if it's the first, it's easy. Make it fullscreen.
if (getNodesOnMonitor(pWindow->m_iMonitorID) == 1) {
PNODE->position = PMONITOR->vecPosition + PMONITOR->vecReservedTopLeft;
PNODE->size = PMONITOR->vecSize - PMONITOR->vecReservedTopLeft - PMONITOR->vecReservedBottomRight;
applyNodeDataToWindow(PNODE);
return;
}
// If it's not, get the last node.
const auto PLASTFOCUS = getNodeFromWindow(g_pCompositor->m_pLastFocus);
SDwindleNodeData* OPENINGON = PLASTFOCUS;
if (PLASTFOCUS) {
if (PLASTFOCUS->monitorID != PNODE->monitorID) {
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindow(g_pInputManager->getMouseCoordsInternal()));
}
} else {
OPENINGON = getNodeFromWindow(g_pCompositor->vectorToWindow(g_pInputManager->getMouseCoordsInternal()));
}
if (!OPENINGON) {
OPENINGON = getFirstNodeOnMonitor(PNODE->monitorID);
}
if (!OPENINGON) {
Debug::log(ERR, "OPENINGON still null?????");
return;
}
m_lDwindleNodesData.push_back(SDwindleNodeData());
const auto NEWPARENT = &m_lDwindleNodesData.back();
// make the parent have the OPENINGON's stats
NEWPARENT->children[0] = OPENINGON;
NEWPARENT->children[1] = PNODE;
NEWPARENT->position = OPENINGON->position;
NEWPARENT->size = OPENINGON->size;
NEWPARENT->monitorID = OPENINGON->monitorID;
NEWPARENT->isNode = true; // it is a node
// and update the previous parent if it exists
if (OPENINGON->pParent) {
if (OPENINGON->pParent->children[0] == OPENINGON) {
OPENINGON->pParent->children[0] == NEWPARENT;
} else {
OPENINGON->pParent->children[1] == NEWPARENT;
}
}
// Update the children
if (NEWPARENT->size.x > NEWPARENT->size.y) {
// split sidey
OPENINGON->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
PNODE->position = Vector2D(NEWPARENT->position.x + NEWPARENT->size.x / 2.f, NEWPARENT->position.y);
PNODE->size = Vector2D(NEWPARENT->size.x / 2.f, NEWPARENT->size.y);
} else {
// split toppy bottomy
OPENINGON->position = NEWPARENT->position;
OPENINGON->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
PNODE->position = Vector2D(NEWPARENT->position.x, NEWPARENT->position.y + NEWPARENT->size.y / 2.f);
PNODE->size = Vector2D(NEWPARENT->size.x, NEWPARENT->size.y / 2.f);
}
OPENINGON->pParent = NEWPARENT;
PNODE->pParent = NEWPARENT;
applyNodeDataToWindow(PNODE);
applyNodeDataToWindow(OPENINGON);
}
void CHyprDwindleLayout::onWindowRemoved(CWindow* pWindow) {
if (!g_pCompositor->windowValidMapped(pWindow))
return;
const auto PNODE = getNodeFromWindow(pWindow);
if (!PNODE)
return;
const auto PPARENT = PNODE->pParent;
if (!PPARENT){
m_lDwindleNodesData.remove(*PNODE);
return;
}
const auto PSIBLING = PPARENT->children[0] == PNODE ? PPARENT->children[1] : PPARENT->children[0];
PSIBLING->position = PPARENT->position;
PSIBLING->size = PPARENT->size;
PSIBLING->pParent = PPARENT->pParent;
if (PPARENT->pParent != nullptr) {
if (PPARENT->pParent->children[0] == PPARENT) {
PPARENT->pParent->children[0] = PSIBLING;
} else {
PPARENT->pParent->children[1] = PSIBLING;
}
}
m_lDwindleNodesData.remove(*PPARENT);
m_lDwindleNodesData.remove(*PNODE);
applyNodeDataToWindow(PSIBLING);
}

View File

@ -0,0 +1,40 @@
#pragma once
#include "IHyprLayout.hpp"
#include <list>
struct SDwindleNodeData {
SDwindleNodeData* pParent = nullptr;
bool isNode = false;
CWindow* pWindow = nullptr;
std::array<SDwindleNodeData*, 2> children = { nullptr, nullptr };
Vector2D position;
Vector2D size;
int monitorID = -1;
// For list lookup
bool operator==(const SDwindleNodeData& rhs) {
return pWindow == rhs.pWindow && monitorID == rhs.monitorID && position == rhs.position && size == rhs.size && pParent == rhs.pParent;
}
// TODO: recalcsizepos for dynamic
};
class CHyprDwindleLayout : public IHyprLayout {
public:
virtual void onWindowCreated(CWindow*);
virtual void onWindowRemoved(CWindow*);
private:
std::list<SDwindleNodeData> m_lDwindleNodesData;
int getNodesOnMonitor(const int&);
void applyNodeDataToWindow(SDwindleNodeData*);
SDwindleNodeData* getNodeFromWindow(CWindow*);
SDwindleNodeData* getFirstNodeOnMonitor(const int&);
};

View File

@ -0,0 +1,12 @@
#pragma once
#include "../defines.hpp"
#include "../Window.hpp"
interface IHyprLayout {
public:
virtual void onWindowCreated(CWindow*) = 0;
virtual void onWindowRemoved(CWindow*) = 0;
};

View File

@ -45,7 +45,7 @@ void CInputManager::mouseMoveUnified(uint32_t time) {
g_pCompositor->focusWindow(PWINDOW);
Vector2D surfaceLocal = m_vWLRMouseCoords - PWINDOW->m_vPosition;
Vector2D surfaceLocal = m_vWLRMouseCoords - PWINDOW->m_vEffectivePosition;
wlr_seat_pointer_notify_enter(g_pCompositor->m_sWLRSeat, g_pXWaylandManager->getWindowSurface(PWINDOW), surfaceLocal.x, surfaceLocal.y);
wlr_seat_pointer_notify_motion(g_pCompositor->m_sWLRSeat, time, surfaceLocal.x, surfaceLocal.y);

View File

@ -0,0 +1,11 @@
#include "LayoutManager.hpp"
IHyprLayout* CLayoutManager::getCurrentLayout() {
switch (m_iCurrentLayoutID) {
case DWINDLE:
return &m_cDwindleLayout;
}
// fallback
return &m_cDwindleLayout;
}

View File

@ -0,0 +1,20 @@
#pragma once
#include "../layout/DwindleLayout.hpp"
class CLayoutManager {
public:
IHyprLayout* getCurrentLayout();
private:
enum HYPRLAYOUTS {
DWINDLE = 0,
};
HYPRLAYOUTS m_iCurrentLayoutID = DWINDLE;
CHyprDwindleLayout m_cDwindleLayout;
};
inline std::unique_ptr<CLayoutManager> g_pLayoutManager;

View File

@ -65,7 +65,7 @@ void CHyprXWaylandManager::sendCloseWindow(CWindow* pWindow) {
void CHyprXWaylandManager::setWindowSize(CWindow* pWindow, const Vector2D& size) {
if (pWindow->m_bIsX11)
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vPosition.x, pWindow->m_vPosition.y, size.x, size.y);
wlr_xwayland_surface_configure(pWindow->m_uSurface.xwayland, pWindow->m_vEffectivePosition.x, pWindow->m_vEffectivePosition.y, size.x, size.y);
else
wlr_xdg_toplevel_set_size(pWindow->m_uSurface.xdg->toplevel, size.x, size.y);

View File

@ -53,15 +53,15 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
if (w.m_bIsX11)
continue;
wlr_box geometry = { w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y };
wlr_box geometry = { w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y };
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &geometry))
continue;
// render the bad boy
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &w.m_vPosition.x, &w.m_vPosition.y);
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &w.m_vRealPosition.x, &w.m_vRealPosition.y);
SRenderData renderdata = {PMONITOR->output, time, w.m_vPosition.x, w.m_vPosition.y};
SRenderData renderdata = {PMONITOR->output, time, w.m_vRealPosition.x, w.m_vRealPosition.y};
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(&w), renderSurface, &renderdata);
wlr_xdg_surface_for_each_popup_surface(w.m_uSurface.xdg, renderSurface, &renderdata);
@ -75,15 +75,15 @@ void CHyprRenderer::renderAllClientsForMonitor(const int& ID, timespec* time) {
if (!g_pCompositor->windowValidMapped(&w))
continue;
wlr_box geometry = {w.m_vPosition.x, w.m_vPosition.y, w.m_vSize.x, w.m_vSize.y};
wlr_box geometry = {w.m_vRealPosition.x, w.m_vRealPosition.y, w.m_vRealSize.x, w.m_vRealSize.y};
if (!wlr_output_layout_intersects(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &geometry))
continue;
// render the bad boy
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &w.m_vPosition.x, &w.m_vPosition.y);
wlr_output_layout_output_coords(g_pCompositor->m_sWLROutputLayout, PMONITOR->output, &w.m_vRealPosition.x, &w.m_vRealPosition.y);
SRenderData renderdata = {PMONITOR->output, time, w.m_vPosition.x, w.m_vPosition.y};
SRenderData renderdata = {PMONITOR->output, time, w.m_vRealPosition.x, w.m_vRealPosition.y};
if (w.m_uSurface.xwayland->surface)
wlr_surface_for_each_surface(g_pXWaylandManager->getWindowSurface(&w), renderSurface, &renderdata);