summaryrefslogtreecommitdiff
path: root/src/protocols/SessionLock.cpp
diff options
context:
space:
mode:
authorVaxry <vaxry@vaxry.net>2024-04-30 16:32:05 +0100
committerVaxry <vaxry@vaxry.net>2024-04-30 16:34:09 +0100
commit90e1411315065ead5b5a7873be4109bdfb9f5470 (patch)
tree3e55d49559d1e77ae655a7c5ea4d4d73f8054180 /src/protocols/SessionLock.cpp
parentd7a48cf47816041c5cb705c9de218c3395635822 (diff)
session-lock: move to new impl
Diffstat (limited to 'src/protocols/SessionLock.cpp')
-rw-r--r--src/protocols/SessionLock.cpp202
1 files changed, 202 insertions, 0 deletions
diff --git a/src/protocols/SessionLock.cpp b/src/protocols/SessionLock.cpp
new file mode 100644
index 00000000..4c4b1846
--- /dev/null
+++ b/src/protocols/SessionLock.cpp
@@ -0,0 +1,202 @@
+#include "SessionLock.hpp"
+#include "../Compositor.hpp"
+
+#define LOGM PROTO::sessionLock->protoLog
+
+CSessionLockSurface::CSessionLockSurface(SP<CExtSessionLockSurfaceV1> resource_, wlr_surface* surface_, CMonitor* pMonitor_, WP<CSessionLock> owner_) :
+ resource(resource_), sessionLock(owner_), pSurface(surface_), pMonitor(pMonitor_) {
+ if (!resource->resource())
+ return;
+
+ resource->setDestroy([this](CExtSessionLockSurfaceV1* r) {
+ events.destroy.emit();
+ PROTO::sessionLock->destroyResource(this);
+ });
+ resource->setOnDestroy([this](CExtSessionLockSurfaceV1* r) {
+ events.destroy.emit();
+ PROTO::sessionLock->destroyResource(this);
+ });
+
+ resource->setAckConfigure([this](CExtSessionLockSurfaceV1* r, uint32_t serial) { ackdConfigure = true; });
+
+ hyprListener_surfaceCommit.initCallback(
+ &pSurface->events.commit,
+ [this](void* owner, void* data) {
+ if (!pSurface->current.buffer) {
+ LOGM(ERR, "SessionLock attached a null buffer");
+ wl_resource_post_error(resource->resource(), EXT_SESSION_LOCK_SURFACE_V1_ERROR_NULL_BUFFER, "Null buffer attached");
+ return;
+ }
+
+ if (!ackdConfigure) {
+ LOGM(ERR, "SessionLock committed without an ack");
+ wl_resource_post_error(resource->resource(), EXT_SESSION_LOCK_SURFACE_V1_ERROR_COMMIT_BEFORE_FIRST_ACK, "Committed surface before first ack");
+ return;
+ }
+
+ if (committed)
+ events.commit.emit();
+ else
+ events.map.emit();
+ committed = true;
+ },
+ this, "SessionLockSurface");
+
+ hyprListener_surfaceDestroy.initCallback(
+ &pSurface->events.destroy,
+ [this](void* owner, void* data) {
+ LOGM(WARN, "SessionLockSurface object remains but surface is being destroyed???");
+ hyprListener_surfaceCommit.removeCallback();
+ hyprListener_surfaceDestroy.removeCallback();
+ pSurface = nullptr;
+ },
+ this, "SessionLockSurface");
+
+ sendConfigure();
+
+ listeners.monitorMode = pMonitor->events.modeChanged.registerListener([this](std::any data) { sendConfigure(); });
+}
+
+CSessionLockSurface::~CSessionLockSurface() {
+ hyprListener_surfaceCommit.removeCallback();
+ hyprListener_surfaceDestroy.removeCallback();
+ events.destroy.emit(); // just in case.
+}
+
+void CSessionLockSurface::sendConfigure() {
+ const auto CLIENT = wl_resource_get_client(resource->resource());
+ const auto SERIAL = wlr_seat_client_next_serial(wlr_seat_client_for_wl_client(g_pCompositor->m_sSeat.seat, CLIENT));
+ resource->sendConfigure(SERIAL, pMonitor->vecSize.x, pMonitor->vecSize.y);
+}
+
+bool CSessionLockSurface::good() {
+ return resource->resource();
+}
+
+bool CSessionLockSurface::inert() {
+ return sessionLock.expired();
+}
+
+CMonitor* CSessionLockSurface::monitor() {
+ return pMonitor;
+}
+
+wlr_surface* CSessionLockSurface::surface() {
+ return pSurface;
+}
+
+CSessionLock::CSessionLock(SP<CExtSessionLockV1> resource_) : resource(resource_) {
+ if (!resource->resource())
+ return;
+
+ resource->setDestroy([this](CExtSessionLockV1* r) { PROTO::sessionLock->destroyResource(this); });
+ resource->setOnDestroy([this](CExtSessionLockV1* r) { PROTO::sessionLock->destroyResource(this); });
+
+ resource->setGetLockSurface([this](CExtSessionLockV1* r, uint32_t id, wl_resource* surf, wl_resource* output) {
+ if (inert) {
+ LOGM(ERR, "Lock is trying to send getLockSurface after it's inert");
+ return;
+ }
+
+ PROTO::sessionLock->onGetLockSurface(r, id, surf, output);
+ });
+
+ resource->setUnlockAndDestroy([this](CExtSessionLockV1* r) {
+ events.unlockAndDestroy.emit();
+ inert = true;
+ PROTO::sessionLock->locked = false;
+ PROTO::sessionLock->destroyResource(this);
+ });
+}
+
+CSessionLock::~CSessionLock() {
+ events.destroyed.emit();
+}
+
+void CSessionLock::sendLocked() {
+ resource->sendLocked();
+}
+
+bool CSessionLock::good() {
+ return resource->resource();
+}
+
+CSessionLockProtocol::CSessionLockProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) {
+ ;
+}
+
+void CSessionLockProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) {
+ const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CExtSessionLockManagerV1>(client, ver, id)).get();
+ RESOURCE->setOnDestroy([this](CExtSessionLockManagerV1* p) { this->onManagerResourceDestroy(p->resource()); });
+
+ RESOURCE->setDestroy([this](CExtSessionLockManagerV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); });
+ RESOURCE->setLock([this](CExtSessionLockManagerV1* pMgr, uint32_t id) { this->onLock(pMgr, id); });
+}
+
+void CSessionLockProtocol::onManagerResourceDestroy(wl_resource* res) {
+ std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; });
+}
+
+void CSessionLockProtocol::destroyResource(CSessionLock* lock) {
+ std::erase_if(m_vLocks, [&](const auto& other) { return other.get() == lock; });
+}
+
+void CSessionLockProtocol::destroyResource(CSessionLockSurface* surf) {
+ std::erase_if(m_vLockSurfaces, [&](const auto& other) { return other.get() == surf; });
+}
+
+void CSessionLockProtocol::onLock(CExtSessionLockManagerV1* pMgr, uint32_t id) {
+
+ LOGM(LOG, "New sessionLock with id {}", id);
+
+ const auto CLIENT = wl_resource_get_client(pMgr->resource());
+ const auto RESOURCE = m_vLocks.emplace_back(std::make_unique<CSessionLock>(std::make_shared<CExtSessionLockV1>(CLIENT, wl_resource_get_version(pMgr->resource()), id)));
+
+ if (!RESOURCE->good()) {
+ wl_resource_post_no_memory(pMgr->resource());
+ m_vLocks.pop_back();
+ return;
+ }
+
+ if (m_vLocks.size() > 1) {
+ LOGM(ERR, "Tried to lock a locked session");
+ RESOURCE->resource->sendFinished();
+ RESOURCE->inert = true;
+ return;
+ }
+
+ locked = true;
+
+ events.newLock.emit(RESOURCE);
+}
+
+void CSessionLockProtocol::onGetLockSurface(CExtSessionLockV1* lock, uint32_t id, wl_resource* surface, wl_resource* output) {
+ LOGM(LOG, "New sessionLockSurface with id {}", id);
+
+ auto PSURFACE = wlr_surface_from_resource(surface);
+ auto PMONITOR = g_pCompositor->getMonitorFromOutput(wlr_output_from_resource(output));
+
+ SP<CSessionLock> sessionLock;
+ for (auto& l : m_vLocks) {
+ if (l->resource.get() == lock) {
+ sessionLock = l;
+ break;
+ }
+ }
+
+ const auto CLIENT = wl_resource_get_client(lock->resource());
+ const auto RESOURCE = m_vLockSurfaces.emplace_back(
+ std::make_unique<CSessionLockSurface>(std::make_shared<CExtSessionLockSurfaceV1>(CLIENT, wl_resource_get_version(lock->resource()), id), PSURFACE, PMONITOR, sessionLock));
+
+ if (!RESOURCE->good()) {
+ wl_resource_post_no_memory(lock->resource());
+ m_vLockSurfaces.pop_back();
+ return;
+ }
+
+ sessionLock->events.newLockSurface.emit(RESOURCE);
+}
+
+bool CSessionLockProtocol::isLocked() {
+ return locked;
+} \ No newline at end of file