Hyprland/src/helpers/SubsurfaceTree.cpp

163 lines
5.4 KiB
C++
Raw Normal View History

2022-03-27 17:25:20 +02:00
#include "SubsurfaceTree.hpp"
#include "../events/Events.hpp"
void addSurfaceGlobalOffset(SSurfaceTreeNode* node, int* lx, int* ly) {
*lx += node->pSurface->sx;
*ly += node->pSurface->sy;
if (node->offsetfn) {
// This is the root node
RASSERT(!node->pSubsurface, "Node had no subsurface!");
node->offsetfn(node->globalOffsetData, lx, ly);
} else {
RASSERT(node->pSubsurface, "Node had no subsurface!");
*lx += node->pSubsurface->pSubsurface->current.x;
*ly += node->pSubsurface->pSubsurface->current.y;
addSurfaceGlobalOffset(node->pParent, lx, ly);
}
}
SSurfaceTreeNode* createTree(wlr_surface* pSurface) {
SubsurfaceTree::surfaceTreeNodes.push_back(SSurfaceTreeNode());
const auto PNODE = &SubsurfaceTree::surfaceTreeNodes.back();
PNODE->pSurface = pSurface;
PNODE->listen_newSubsurface.notify = Events::listener_newSubsurfaceNode;
PNODE->listen_commit.notify = Events::listener_commitSubsurface;
PNODE->listen_destroy.notify = Events::listener_destroySubsurfaceNode;
wl_signal_add(&pSurface->events.commit, &PNODE->listen_commit);
wl_signal_add(&pSurface->events.destroy, &PNODE->listen_destroy);
wl_signal_add(&pSurface->events.new_subsurface, &PNODE->listen_newSubsurface);
return PNODE;
}
SSurfaceTreeNode* createSubsurfaceNode(SSurfaceTreeNode* pParent, SSubsurface* pSubsurface, wlr_surface* surface) {
const auto PNODE = createTree(surface);
PNODE->pParent = pParent;
PNODE->pSubsurface = pSubsurface;
return PNODE;
}
SSurfaceTreeNode* SubsurfaceTree::createTreeRoot(wlr_surface* pSurface, applyGlobalOffsetFn fn, void* data) {
const auto PNODE = createTree(pSurface);
PNODE->offsetfn = fn;
PNODE->globalOffsetData = data;
return PNODE;
}
void destroySubsurface(SSubsurface* pSubsurface);
void SubsurfaceTree::destroySurfaceTree(SSurfaceTreeNode* pNode) {
for (auto& c : pNode->childSubsurfaces)
destroySubsurface(&c);
pNode->childSubsurfaces.clear();
wl_list_remove(&pNode->listen_newSubsurface.link);
wl_list_remove(&pNode->listen_commit.link);
wl_list_remove(&pNode->listen_destroy.link);
Debug::log(LOG, "SurfaceTree Node removed");
}
void destroySubsurface(SSubsurface* pSubsurface) {
if (pSubsurface->pChild) {
SubsurfaceTree::destroySurfaceTree(pSubsurface->pChild);
pSubsurface->pChild = nullptr;
}
wl_list_remove(&pSubsurface->listen_map.link);
wl_list_remove(&pSubsurface->listen_unmap.link);
wl_list_remove(&pSubsurface->listen_destroy.link);
}
//
// Subsurface listeners
//
void Events::listener_newSubsurfaceNode(wl_listener* listener, void* data) {
SSurfaceTreeNode* pNode = wl_container_of(listener, pNode, listen_newSubsurface);
const auto PSUBSURFACE = (wlr_subsurface*)data;
pNode->childSubsurfaces.push_back(SSubsurface());
const auto PNEWSUBSURFACE = &pNode->childSubsurfaces.back();
Debug::log(LOG, "Added a new subsurface %x", PSUBSURFACE);
PNEWSUBSURFACE->pSubsurface = PSUBSURFACE;
PNEWSUBSURFACE->pParent = pNode;
PNEWSUBSURFACE->listen_map.notify = Events::listener_mapSubsurface;
PNEWSUBSURFACE->listen_unmap.notify = Events::listener_unmapSubsurface;
PNEWSUBSURFACE->listen_destroy.notify = Events::listener_destroySubsurface;
wl_signal_add(&PSUBSURFACE->events.map, &PNEWSUBSURFACE->listen_map);
wl_signal_add(&PSUBSURFACE->events.unmap, &PNEWSUBSURFACE->listen_unmap);
wl_signal_add(&PSUBSURFACE->events.destroy, &PNEWSUBSURFACE->listen_destroy);
}
void Events::listener_mapSubsurface(wl_listener* listener, void* data) {
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_map);
Debug::log(LOG, "Subsurface %x mapped", subsurface->pSubsurface);
subsurface->pChild = createSubsurfaceNode(subsurface->pParent, subsurface, subsurface->pSubsurface->surface);
}
void Events::listener_unmapSubsurface(wl_listener* listener, void* data) {
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_unmap);
Debug::log(LOG, "Subsurface %x unmapped", subsurface);
if (subsurface->pChild) {
const auto PNODE = subsurface->pChild;
int lx = 0, ly = 0;
addSurfaceGlobalOffset(PNODE, &lx, &ly);
wlr_box extents = {0};
wlr_surface_get_extends(PNODE->pSurface, &extents);
extents.x += lx;
extents.y += ly;
SubsurfaceTree::destroySurfaceTree(subsurface->pChild);
subsurface->pChild = nullptr;
}
}
void Events::listener_commitSubsurface(wl_listener* listener, void* data) {
SSurfaceTreeNode* pNode = wl_container_of(listener, pNode, listen_commit);
}
void Events::listener_destroySubsurface(wl_listener* listener, void* data) {
SSubsurface* subsurface = wl_container_of(listener, subsurface, listen_destroy);
Debug::log(LOG, "Subsurface %x destroyed", subsurface);
subsurface->pParent->childSubsurfaces.remove(*subsurface);
}
void Events::listener_destroySubsurfaceNode(wl_listener* listener, void* data) {
SSurfaceTreeNode* pNode = wl_container_of(listener, pNode, listen_destroy);
Debug::log(LOG, "Subsurface Node %x destroyed", pNode);
for (auto& c : pNode->childSubsurfaces)
destroySubsurface(&c);
wl_list_remove(&pNode->listen_newSubsurface.link);
wl_list_remove(&pNode->listen_commit.link);
wl_list_remove(&pNode->listen_destroy.link);
SubsurfaceTree::surfaceTreeNodes.remove(*pNode);
}