summaryrefslogtreecommitdiff
path: root/src/helpers
diff options
context:
space:
mode:
authorvaxerski <43317083+vaxerski@users.noreply.github.com>2022-03-27 17:25:20 +0200
committervaxerski <43317083+vaxerski@users.noreply.github.com>2022-03-27 17:25:20 +0200
commitad36a9dc9ed032e6e34c06f78995bca0045f85b0 (patch)
tree933cfc71255a9cfbe1211f187d7d101a4e30ffc8 /src/helpers
parent4c3b9ae207967bf06b973cc6b49db58887f1af6b (diff)
rework popups completely
Diffstat (limited to 'src/helpers')
-rw-r--r--src/helpers/SubsurfaceTree.cpp163
-rw-r--r--src/helpers/SubsurfaceTree.hpp50
-rw-r--r--src/helpers/WLClasses.hpp43
3 files changed, 221 insertions, 35 deletions
diff --git a/src/helpers/SubsurfaceTree.cpp b/src/helpers/SubsurfaceTree.cpp
new file mode 100644
index 00000000..cdadbe75
--- /dev/null
+++ b/src/helpers/SubsurfaceTree.cpp
@@ -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);
+} \ No newline at end of file
diff --git a/src/helpers/SubsurfaceTree.hpp b/src/helpers/SubsurfaceTree.hpp
new file mode 100644
index 00000000..df92033a
--- /dev/null
+++ b/src/helpers/SubsurfaceTree.hpp
@@ -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;
+};
diff --git a/src/helpers/WLClasses.hpp b/src/helpers/WLClasses.hpp
index 791e69f2..985e62af 100644
--- a/src/helpers/WLClasses.hpp
+++ b/src/helpers/WLClasses.hpp
@@ -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;