From 42fd366046d67c52449001b6a6e9b64427aee712 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Thu, 2 Jan 2025 03:53:57 -0800 Subject: protocols: fix alpha-modifier noncompliance (#8929) Also fixes small issues with hyprland-surface opacity < 1.0 while surface alpha = 1.0. --- src/protocols/AlphaModifier.cpp | 128 +++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 62 deletions(-) (limited to 'src/protocols/AlphaModifier.cpp') diff --git a/src/protocols/AlphaModifier.cpp b/src/protocols/AlphaModifier.cpp index 13597fa9..d695b58f 100644 --- a/src/protocols/AlphaModifier.cpp +++ b/src/protocols/AlphaModifier.cpp @@ -1,66 +1,62 @@ #include "AlphaModifier.hpp" -#include #include "../desktop/WLSurface.hpp" #include "../render/Renderer.hpp" +#include "alpha-modifier-v1.hpp" #include "core/Compositor.hpp" -CAlphaModifier::CAlphaModifier(SP resource_, SP surface_) : resource(resource_), pSurface(surface_) { - if (!resource->resource()) - return; +CAlphaModifier::CAlphaModifier(SP resource, SP surface) : m_pSurface(surface) { + setResource(std::move(resource)); +} - resource->setDestroy([this](CWpAlphaModifierSurfaceV1* pMgr) { - PROTO::alphaModifier->destroyModifier(this); - setSurfaceAlpha(1.F); - }); - resource->setOnDestroy([this](CWpAlphaModifierSurfaceV1* pMgr) { - PROTO::alphaModifier->destroyModifier(this); - setSurfaceAlpha(1.F); - }); +bool CAlphaModifier::good() { + return m_pResource->resource(); +} - listeners.destroySurface = pSurface->events.destroy.registerListener([this](std::any d) { onSurfaceDestroy(); }); +void CAlphaModifier::setResource(SP resource) { + m_pResource = std::move(resource); + + if (!m_pResource->resource()) + return; - resource->setSetMultiplier([this](CWpAlphaModifierSurfaceV1* mod, uint32_t alpha) { - if (!pSurface) { - LOGM(ERR, "Resource {:x} tried to setMultiplier but surface is gone", (uintptr_t)mod->resource()); - mod->error(WP_ALPHA_MODIFIER_SURFACE_V1_ERROR_NO_SURFACE, "Surface is gone"); + m_pResource->setDestroy([this](CWpAlphaModifierSurfaceV1* resource) { destroy(); }); + m_pResource->setOnDestroy([this](CWpAlphaModifierSurfaceV1* resource) { destroy(); }); + + m_pResource->setSetMultiplier([this](CWpAlphaModifierSurfaceV1* resource, uint32_t alpha) { + if (!m_pSurface) { + m_pResource->error(WP_ALPHA_MODIFIER_SURFACE_V1_ERROR_NO_SURFACE, "set_multiplier called for destroyed wl_surface"); return; } - float a = alpha / (float)UINT32_MAX; - - setSurfaceAlpha(a); + m_fAlpha = alpha / (float)UINT32_MAX; }); -} - -CAlphaModifier::~CAlphaModifier() { - ; -} - -bool CAlphaModifier::good() { - return resource->resource(); -} -SP CAlphaModifier::getSurface() { - return pSurface.lock(); -} + listeners.surfaceCommitted = m_pSurface->events.commit.registerListener([this](std::any data) { + auto surface = CWLSurface::fromResource(m_pSurface.lock()); -void CAlphaModifier::setSurfaceAlpha(float a) { - auto surf = CWLSurface::fromResource(pSurface.lock()); + if (surface && surface->m_fAlphaModifier != m_fAlpha) { + surface->m_fAlphaModifier = m_fAlpha; + auto box = surface->getSurfaceBoxGlobal(); - if (!surf) { - LOGM(ERR, "CAlphaModifier::setSurfaceAlpha: No CWLSurface for given surface??"); - return; - } + if (box.has_value()) + g_pHyprRenderer->damageBox(&*box); - surf->m_pAlphaModifier = a; + if (!m_pResource) + PROTO::alphaModifier->destroyAlphaModifier(this); + } + }); - auto SURFBOX = surf->getSurfaceBoxGlobal(); - if (SURFBOX.has_value()) - g_pHyprRenderer->damageBox(&*SURFBOX); + listeners.surfaceDestroyed = m_pSurface->events.destroy.registerListener([this](std::any data) { + if (!m_pResource) + PROTO::alphaModifier->destroyAlphaModifier(this); + }); } -void CAlphaModifier::onSurfaceDestroy() { - pSurface.reset(); +void CAlphaModifier::destroy() { + m_pResource.reset(); + m_fAlpha = 1.F; + + if (!m_pSurface) + PROTO::alphaModifier->destroyAlphaModifier(this); } CAlphaModifierProtocol::CAlphaModifierProtocol(const wl_interface* iface, const int& ver, const std::string& name) : IWaylandProtocol(iface, ver, name) { @@ -69,33 +65,41 @@ CAlphaModifierProtocol::CAlphaModifierProtocol(const wl_interface* iface, const void CAlphaModifierProtocol::bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id) { const auto RESOURCE = m_vManagers.emplace_back(std::make_unique(client, ver, id)).get(); - RESOURCE->setOnDestroy([this](CWpAlphaModifierV1* p) { this->onManagerResourceDestroy(p->resource()); }); + RESOURCE->setOnDestroy([this](CWpAlphaModifierV1* manager) { destroyManager(manager); }); - RESOURCE->setDestroy([this](CWpAlphaModifierV1* pMgr) { this->onManagerResourceDestroy(pMgr->resource()); }); - RESOURCE->setGetSurface([this](CWpAlphaModifierV1* pMgr, uint32_t id, wl_resource* surface) { this->onGetSurface(pMgr, id, CWLSurfaceResource::fromResource(surface)); }); + RESOURCE->setDestroy([this](CWpAlphaModifierV1* manager) { destroyManager(manager); }); + RESOURCE->setGetSurface([this](CWpAlphaModifierV1* manager, uint32_t id, wl_resource* surface) { getSurface(manager, id, CWLSurfaceResource::fromResource(surface)); }); } -void CAlphaModifierProtocol::onManagerResourceDestroy(wl_resource* res) { - std::erase_if(m_vManagers, [&](const auto& other) { return other->resource() == res; }); +void CAlphaModifierProtocol::destroyManager(CWpAlphaModifierV1* manager) { + std::erase_if(m_vManagers, [&](const auto& p) { return p.get() == manager; }); } -void CAlphaModifierProtocol::destroyModifier(CAlphaModifier* modifier) { - std::erase_if(m_mAlphaModifiers, [](const auto& e) { return e.first.expired(); }); +void CAlphaModifierProtocol::destroyAlphaModifier(CAlphaModifier* modifier) { + std::erase_if(m_mAlphaModifiers, [&](const auto& entry) { return entry.second.get() == modifier; }); } -void CAlphaModifierProtocol::onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, SP surface) { - if (std::find_if(m_mAlphaModifiers.begin(), m_mAlphaModifiers.end(), [surface](const auto& e) { return e.first == surface; }) != m_mAlphaModifiers.end()) { - LOGM(ERR, "AlphaModifier already present for surface {:x}", (uintptr_t)surface.get()); - pMgr->error(WP_ALPHA_MODIFIER_V1_ERROR_ALREADY_CONSTRUCTED, "AlphaModifier already present"); - return; - } +void CAlphaModifierProtocol::getSurface(CWpAlphaModifierV1* manager, uint32_t id, SP surface) { + CAlphaModifier* alphaModifier = nullptr; + auto iter = std::find_if(m_mAlphaModifiers.begin(), m_mAlphaModifiers.end(), [&](const auto& entry) { return entry.second->m_pSurface == surface; }); - const auto RESOURCE = m_mAlphaModifiers.emplace(surface, std::make_unique(makeShared(pMgr->client(), pMgr->version(), id), surface)) - .first->second.get(); + if (iter != m_mAlphaModifiers.end()) { + if (iter->second->m_pResource) { + LOGM(ERR, "AlphaModifier already present for surface {:x}", (uintptr_t)surface.get()); + manager->error(WP_ALPHA_MODIFIER_V1_ERROR_ALREADY_CONSTRUCTED, "AlphaModifier already present"); + return; + } else { + iter->second->setResource(makeShared(manager->client(), manager->version(), id)); + alphaModifier = iter->second.get(); + } + } else { + alphaModifier = + m_mAlphaModifiers.emplace(surface, std::make_unique(makeShared(manager->client(), manager->version(), id), surface)) + .first->second.get(); + } - if (!RESOURCE->good()) { - pMgr->noMemory(); + if (!alphaModifier->good()) { + manager->noMemory(); m_mAlphaModifiers.erase(surface); - return; } } -- cgit v1.2.3