summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Compositor.cpp5
-rw-r--r--src/Compositor.hpp2
-rw-r--r--src/defines.hpp6
-rw-r--r--src/events/Events.cpp8
-rw-r--r--src/layout/DwindleLayout.cpp202
-rw-r--r--src/layout/DwindleLayout.hpp40
-rw-r--r--src/layout/IHyprLayout.hpp12
-rw-r--r--src/managers/InputManager.cpp2
-rw-r--r--src/managers/LayoutManager.cpp11
-rw-r--r--src/managers/LayoutManager.hpp20
-rw-r--r--src/managers/XWaylandManager.cpp4
-rw-r--r--src/render/Renderer.cpp12
12 files changed, 308 insertions, 16 deletions
diff --git a/src/Compositor.cpp b/src/Compositor.cpp
index 6386a07d..c0059836 100644
--- a/src/Compositor.cpp
+++ b/src/Compositor.cpp
@@ -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;
}
diff --git a/src/Compositor.hpp b/src/Compositor.hpp
index 26b16f42..7fd26b38 100644
--- a/src/Compositor.hpp
+++ b/src/Compositor.hpp
@@ -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();
diff --git a/src/defines.hpp b/src/defines.hpp
index 94807ac1..9c3856aa 100644
--- a/src/defines.hpp
+++ b/src/defines.hpp
@@ -11,4 +11,8 @@
#define LISTENER(name) void listener_##name(wl_listener*, void*); inline wl_listener listen_##name = { .notify = listener_##name };
#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)) \ No newline at end of file
+#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 \ No newline at end of file
diff --git a/src/events/Events.cpp b/src/events/Events.cpp
index 24c51a07..6baaeebb 100644
--- a/src/events/Events.cpp
+++ b/src/events/Events.cpp
@@ -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);
diff --git a/src/layout/DwindleLayout.cpp b/src/layout/DwindleLayout.cpp
new file mode 100644
index 00000000..290a8a6a
--- /dev/null
+++ b/src/layout/DwindleLayout.cpp
@@ -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);
+} \ No newline at end of file
diff --git a/src/layout/DwindleLayout.hpp b/src/layout/DwindleLayout.hpp
new file mode 100644
index 00000000..b666d72a
--- /dev/null
+++ b/src/layout/DwindleLayout.hpp
@@ -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&);
+}; \ No newline at end of file
diff --git a/src/layout/IHyprLayout.hpp b/src/layout/IHyprLayout.hpp
new file mode 100644
index 00000000..feaaa835
--- /dev/null
+++ b/src/layout/IHyprLayout.hpp
@@ -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;
+
+}; \ No newline at end of file
diff --git a/src/managers/InputManager.cpp b/src/managers/InputManager.cpp
index 725ce672..492251fd 100644
--- a/src/managers/InputManager.cpp
+++ b/src/managers/InputManager.cpp
@@ -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);
diff --git a/src/managers/LayoutManager.cpp b/src/managers/LayoutManager.cpp
new file mode 100644
index 00000000..ec723350
--- /dev/null
+++ b/src/managers/LayoutManager.cpp
@@ -0,0 +1,11 @@
+#include "LayoutManager.hpp"
+
+IHyprLayout* CLayoutManager::getCurrentLayout() {
+ switch (m_iCurrentLayoutID) {
+ case DWINDLE:
+ return &m_cDwindleLayout;
+ }
+
+ // fallback
+ return &m_cDwindleLayout;
+} \ No newline at end of file
diff --git a/src/managers/LayoutManager.hpp b/src/managers/LayoutManager.hpp
new file mode 100644
index 00000000..20f1f7f9
--- /dev/null
+++ b/src/managers/LayoutManager.hpp
@@ -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; \ No newline at end of file
diff --git a/src/managers/XWaylandManager.cpp b/src/managers/XWaylandManager.cpp
index 1c28ec35..dfe6cb19 100644
--- a/src/managers/XWaylandManager.cpp
+++ b/src/managers/XWaylandManager.cpp
@@ -64,8 +64,8 @@ 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);
+ if (pWindow->m_bIsX11)
+ 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);
diff --git a/src/render/Renderer.cpp b/src/render/Renderer.cpp
index b335cbe0..aeb19008 100644
--- a/src/render/Renderer.cpp
+++ b/src/render/Renderer.cpp
@@ -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);