diff options
| author | Vaxry <vaxry@vaxry.net> | 2024-04-29 16:43:24 +0100 |
|---|---|---|
| committer | Vaxry <vaxry@vaxry.net> | 2024-04-29 16:43:24 +0100 |
| commit | 86133983a94a6ad52933e0577b6098dd8e98ed8c (patch) | |
| tree | 1e67217491872e660d0ced50f34f085920edd8a1 /src/protocols/XDGActivation.cpp | |
| parent | 39595aaca3c16cc483dcaacdebaecc24c952246b (diff) | |
xdg-activation: move to new impl
Diffstat (limited to 'src/protocols/XDGActivation.cpp')
| -rw-r--r-- | src/protocols/XDGActivation.cpp | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/protocols/XDGActivation.cpp b/src/protocols/XDGActivation.cpp new file mode 100644 index 00000000..6e2e32fb --- /dev/null +++ b/src/protocols/XDGActivation.cpp @@ -0,0 +1,103 @@ +#include "XDGActivation.hpp" +#include "../managers/TokenManager.hpp" +#include "../Compositor.hpp" +#include <algorithm> + +#define LOGM PROTO::activation->protoLog + +CXDGActivationToken::CXDGActivationToken(SP<CXdgActivationTokenV1> resource_) : resource(resource_) { + if (!resource_->resource()) + return; + + resource->setDestroy([this](CXdgActivationTokenV1* r) { PROTO::activation->destroyToken(this); }); + resource->setOnDestroy([this](CXdgActivationTokenV1* r) { PROTO::activation->destroyToken(this); }); + + resource->setSetSerial([this](CXdgActivationTokenV1* r, uint32_t serial_, wl_resource* seat) { serial = serial_; }); + + resource->setSetAppId([this](CXdgActivationTokenV1* r, const char* appid) { appID = appid; }); + + resource->setCommit([this](CXdgActivationTokenV1* r) { + // TODO: should we send a protocol error of already_used here + // if it was used? the protocol spec doesn't say _when_ it should be sent... + if (committed) { + LOGM(WARN, "possible protocol error, two commits from one token. Ignoring."); + return; + } + + committed = true; + // send done with a new token + token = g_pTokenManager->registerNewToken({}, std::chrono::months{12}); + + LOGM(LOG, "assigned new xdg-activation token {}", token); + + resource->sendDone(token.c_str()); + }); +} + +CXDGActivationToken::~CXDGActivationToken() { + if (committed) + g_pTokenManager->removeToken(g_pTokenManager->getToken(token)); +} + +bool CXDGActivationToken::good() { + return resource->resource(); +} + +CXDGActivationProtocol::CXDGActivationProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { + ; +} + +void CXDGActivationProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { + const auto RESOURCE = m_vManagers.emplace_back(std::make_unique<CXdgActivationV1>(client, ver, id)).get(); + RESOURCE->setOnDestroy([this](CXdgActivationV1* p) { this->onManagerResourceDestroy(p->resource()); }); + + RESOURCE->setDestroy([this](CXdgActivationV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); + RESOURCE->setGetActivationToken([this](CXdgActivationV1* pMgr, uint32_t id) { this->onGetToken(pMgr, id); }); + RESOURCE->setActivate([this](CXdgActivationV1* pMgr, const char* token, wl_resource* surface) { + const auto TOKEN = std::find_if(m_vTokens.begin(), m_vTokens.end(), [token](const auto& t) { return t->committed && t->token == token; }); + + if (TOKEN == m_vTokens.end()) { + LOGM(WARN, "activate event for non-existent token {}??", token); + return; + } + + auto xdgToken = TOKEN->get(); + + if (xdgToken->used) { + LOGM(WARN, "activate event for already used token {}, ignoring", token); + return; + } + + xdgToken->used = true; + + wlr_surface* surf = wlr_surface_from_resource(surface); + const auto PWINDOW = g_pCompositor->getWindowFromSurface(surf); + + if (!PWINDOW) { + LOGM(WARN, "activate event for non-window or gone surface with token {}, ignoring", token); + return; + } + + PWINDOW->activate(); + }); +} + +void CXDGActivationProtocol::onManagerResourceDestroy(wl_resource* res) { + std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; }); +} + +void CXDGActivationProtocol::destroyToken(CXDGActivationToken* token) { + std::erase_if(m_vTokens, [&](const auto& other) { return other.get() == token; }); +} + +void CXDGActivationProtocol::onGetToken(CXdgActivationV1* pMgr, uint32_t id) { + const auto CLIENT = wl_resource_get_client(pMgr->resource()); + const auto RESOURCE = + m_vTokens.emplace_back(std::make_unique<CXDGActivationToken>(std::make_shared<CXdgActivationTokenV1>(CLIENT, wl_resource_get_version(pMgr->resource()), id))).get(); + + if (!RESOURCE->good()) { + wl_resource_post_no_memory(pMgr->resource()); + m_vTokens.pop_back(); + return; + } +}
\ No newline at end of file |
