mirror of
https://github.com/hyprwm/Hyprland
synced 2024-12-22 16:49:49 +01:00
added a layoutmanager and basic dwindle
This commit is contained in:
parent
e664b0b692
commit
61e10e2048
12 changed files with 308 additions and 16 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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))
|
||||
#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
|
|
@ -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);
|
||||
|
|
202
src/layout/DwindleLayout.cpp
Normal file
202
src/layout/DwindleLayout.cpp
Normal 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);
|
||||
}
|
40
src/layout/DwindleLayout.hpp
Normal file
40
src/layout/DwindleLayout.hpp
Normal 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&);
|
||||
};
|
12
src/layout/IHyprLayout.hpp
Normal file
12
src/layout/IHyprLayout.hpp
Normal 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;
|
||||
|
||||
};
|
|
@ -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);
|
||||
|
|
11
src/managers/LayoutManager.cpp
Normal file
11
src/managers/LayoutManager.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "LayoutManager.hpp"
|
||||
|
||||
IHyprLayout* CLayoutManager::getCurrentLayout() {
|
||||
switch (m_iCurrentLayoutID) {
|
||||
case DWINDLE:
|
||||
return &m_cDwindleLayout;
|
||||
}
|
||||
|
||||
// fallback
|
||||
return &m_cDwindleLayout;
|
||||
}
|
20
src/managers/LayoutManager.hpp
Normal file
20
src/managers/LayoutManager.hpp
Normal 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;
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue