rework popups completely

This commit is contained in:
vaxerski 2022-03-27 17:25:20 +02:00
parent 4c3b9ae207
commit ad36a9dc9e
11 changed files with 314 additions and 285 deletions

View file

@ -0,0 +1,163 @@
#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);
}

View file

@ -0,0 +1,50 @@
#pragma once
#include "../defines.hpp"
#include <list>
struct SSubsurface;
typedef void (*applyGlobalOffsetFn)(void *, int *, int *);
struct SSurfaceTreeNode {
wlr_surface* pSurface = nullptr;
DYNMULTILISTENER(newSubsurface);
DYNMULTILISTENER(commit);
DYNMULTILISTENER(destroy);
SSurfaceTreeNode* pParent = nullptr;
SSubsurface* pSubsurface = nullptr;
std::list<SSubsurface> childSubsurfaces;
applyGlobalOffsetFn offsetfn;
void *globalOffsetData;
bool operator==(const SSurfaceTreeNode& rhs) {
return pSurface == rhs.pSurface;
}
};
struct SSubsurface {
wlr_subsurface* pSubsurface = nullptr;
SSurfaceTreeNode* pParent = nullptr;
SSurfaceTreeNode* pChild = nullptr;
DYNMULTILISTENER(map);
DYNMULTILISTENER(unmap);
DYNMULTILISTENER(destroy);
bool operator==(const SSubsurface& rhs) {
return pSubsurface == rhs.pSubsurface;
}
};
namespace SubsurfaceTree {
SSurfaceTreeNode* createTreeRoot(wlr_surface*, applyGlobalOffsetFn, void*);
void destroySurfaceTree(SSurfaceTreeNode*);
inline std::list<SSurfaceTreeNode> surfaceTreeNodes;
};

View file

@ -4,6 +4,7 @@
#include "../defines.hpp"
#include "../../wlr-layer-shell-unstable-v1-protocol.h"
#include "../Window.hpp"
#include "SubsurfaceTree.hpp"
struct SLayerSurface {
wlr_layer_surface_v1* layerSurface;
@ -14,9 +15,9 @@ struct SLayerSurface {
DYNLISTENER(unmapLayerSurface);
DYNLISTENER(commitLayerSurface);
DYNLISTENER(newPopup);
DYNLISTENER(newSubsurface);
wlr_box geometry;
Vector2D position;
zwlr_layer_shell_v1_layer layer;
int monitorID = -1;
@ -28,22 +29,6 @@ struct SLayerSurface {
}
};
struct SSubsurface {
wlr_subsurface* subsurface = nullptr;
SLayerSurface* pParentSurface = nullptr;
DYNLISTENER(mapSubsurface);
DYNLISTENER(unmapSubsurface);
DYNLISTENER(destroySubsurface);
DYNLISTENER(commitSubsurface);
DYNLISTENER(newSubsurface);
// For the list lookup
bool operator==(const SSubsurface& rhs) {
return subsurface == rhs.subsurface && pParentSurface == rhs.pParentSurface;
}
};
struct SRenderData {
wlr_output* output;
timespec* when;
@ -68,26 +53,9 @@ struct SKeyboard {
}
};
struct SLayerPopup {
wlr_xdg_popup* popup = nullptr;
SLayerSurface* parentSurface = nullptr;
wlr_xdg_popup* parentPopup = nullptr;
DYNLISTENER(mapPopup);
DYNLISTENER(destroyPopup);
DYNLISTENER(unmapPopup);
DYNLISTENER(commitPopup);
DYNLISTENER(newPopupFromPopup);
// For the list lookup
bool operator==(const SLayerPopup& rhs) {
return popup == rhs.popup;
}
};
struct SXDGPopup {
CWindow* parentWindow = nullptr;
wlr_xdg_popup* parentPopup = nullptr;
SXDGPopup* parentPopup = nullptr;
wlr_xdg_popup* popup = nullptr;
DYNLISTENER(newPopupFromPopupXDG);
@ -95,6 +63,11 @@ struct SXDGPopup {
DYNLISTENER(mapPopupXDG);
DYNLISTENER(unmapPopupXDG);
double* lx;
double* ly;
SSurfaceTreeNode* pSurfaceTree = nullptr;
// For the list lookup
bool operator==(const SXDGPopup& rhs) {
return popup == rhs.popup;