diff --git a/src/desktop/WLSurface.hpp b/src/desktop/WLSurface.hpp index 346fc935..07af13df 100644 --- a/src/desktop/WLSurface.hpp +++ b/src/desktop/WLSurface.hpp @@ -84,7 +84,7 @@ class CWLSurface { static SP fromResource(SP pSurface); // used by the alpha-modifier protocol - float m_pAlphaModifier = 1.F; + float m_fAlphaModifier = 1.F; // used by the hyprland-surface protocol float m_fOverallOpacity = 1.F; 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; - - resource->setDestroy([this](CWpAlphaModifierSurfaceV1* pMgr) { - PROTO::alphaModifier->destroyModifier(this); - setSurfaceAlpha(1.F); - }); - resource->setOnDestroy([this](CWpAlphaModifierSurfaceV1* pMgr) { - PROTO::alphaModifier->destroyModifier(this); - setSurfaceAlpha(1.F); - }); - - listeners.destroySurface = pSurface->events.destroy.registerListener([this](std::any d) { onSurfaceDestroy(); }); - - 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"); - return; - } - - float a = alpha / (float)UINT32_MAX; - - setSurfaceAlpha(a); - }); -} - -CAlphaModifier::~CAlphaModifier() { - ; +CAlphaModifier::CAlphaModifier(SP resource, SP surface) : m_pSurface(surface) { + setResource(std::move(resource)); } bool CAlphaModifier::good() { - return resource->resource(); + return m_pResource->resource(); } -SP CAlphaModifier::getSurface() { - return pSurface.lock(); -} +void CAlphaModifier::setResource(SP resource) { + m_pResource = std::move(resource); -void CAlphaModifier::setSurfaceAlpha(float a) { - auto surf = CWLSurface::fromResource(pSurface.lock()); - - if (!surf) { - LOGM(ERR, "CAlphaModifier::setSurfaceAlpha: No CWLSurface for given surface??"); + if (!m_pResource->resource()) return; - } - surf->m_pAlphaModifier = a; + m_pResource->setDestroy([this](CWpAlphaModifierSurfaceV1* resource) { destroy(); }); + m_pResource->setOnDestroy([this](CWpAlphaModifierSurfaceV1* resource) { destroy(); }); - auto SURFBOX = surf->getSurfaceBoxGlobal(); - if (SURFBOX.has_value()) - g_pHyprRenderer->damageBox(&*SURFBOX); + 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; + } + + m_fAlpha = alpha / (float)UINT32_MAX; + }); + + listeners.surfaceCommitted = m_pSurface->events.commit.registerListener([this](std::any data) { + auto surface = CWLSurface::fromResource(m_pSurface.lock()); + + if (surface && surface->m_fAlphaModifier != m_fAlpha) { + surface->m_fAlphaModifier = m_fAlpha; + auto box = surface->getSurfaceBoxGlobal(); + + if (box.has_value()) + g_pHyprRenderer->damageBox(&*box); + + if (!m_pResource) + PROTO::alphaModifier->destroyAlphaModifier(this); + } + }); + + 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; }); + + 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(); } - const auto RESOURCE = m_mAlphaModifiers.emplace(surface, std::make_unique(makeShared(pMgr->client(), pMgr->version(), id), surface)) - .first->second.get(); - - if (!RESOURCE->good()) { - pMgr->noMemory(); + if (!alphaModifier->good()) { + manager->noMemory(); m_mAlphaModifiers.erase(surface); - return; } } diff --git a/src/protocols/AlphaModifier.hpp b/src/protocols/AlphaModifier.hpp index 1bb9cf23..43f78bef 100644 --- a/src/protocols/AlphaModifier.hpp +++ b/src/protocols/AlphaModifier.hpp @@ -8,25 +8,28 @@ #include "../helpers/signal/Signal.hpp" class CWLSurfaceResource; +class CAlphaModifierProtocol; class CAlphaModifier { public: CAlphaModifier(SP resource_, SP surface); - ~CAlphaModifier(); - bool good(); - SP getSurface(); - void onSurfaceDestroy(); + bool good(); + void setResource(SP resource); private: - SP resource; - WP pSurface; + SP m_pResource; + WP m_pSurface; + float m_fAlpha = 1.0; - void setSurfaceAlpha(float a); + void destroy(); struct { - CHyprSignalListener destroySurface; + CHyprSignalListener surfaceCommitted; + CHyprSignalListener surfaceDestroyed; } listeners; + + friend class CAlphaModifierProtocol; }; class CAlphaModifierProtocol : public IWaylandProtocol { @@ -36,13 +39,13 @@ class CAlphaModifierProtocol : public IWaylandProtocol { virtual void bindManager(wl_client* client, void* data, uint32_t ver, uint32_t id); private: - void onManagerResourceDestroy(wl_resource* res); - void destroyModifier(CAlphaModifier* decoration); - void onGetSurface(CWpAlphaModifierV1* pMgr, uint32_t id, SP surface); + void destroyManager(CWpAlphaModifierV1* res); + void destroyAlphaModifier(CAlphaModifier* surface); + void getSurface(CWpAlphaModifierV1* manager, uint32_t id, SP surface); // std::vector> m_vManagers; - std::unordered_map, UP> m_mAlphaModifiers; // xdg_toplevel -> deco + std::unordered_map, UP> m_mAlphaModifiers; friend class CAlphaModifier; }; diff --git a/src/render/pass/SurfacePassElement.cpp b/src/render/pass/SurfacePassElement.cpp index 89d4301c..bdb21338 100644 --- a/src/render/pass/SurfacePassElement.cpp +++ b/src/render/pass/SurfacePassElement.cpp @@ -58,7 +58,7 @@ void CSurfacePassElement::draw(const CRegion& damage) { auto PSURFACE = CWLSurface::fromResource(data.surface); - const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F); + const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_fAlphaModifier : 1.F); const float OVERALL_ALPHA = PSURFACE ? PSURFACE->m_fOverallOpacity : 1.F; const bool BLUR = data.blur && (!TEXTURE->m_bOpaque || ALPHA < 1.F || OVERALL_ALPHA < 1.F); @@ -96,7 +96,7 @@ void CSurfacePassElement::draw(const CRegion& damage) { rounding = 0; const bool WINDOWOPAQUE = data.pWindow && data.pWindow->m_pWLSurface->resource() == data.surface ? data.pWindow->opaque() : false; - const bool CANDISABLEBLEND = ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE; + const bool CANDISABLEBLEND = ALPHA >= 1.f && OVERALL_ALPHA >= 1.f && rounding == 0 && WINDOWOPAQUE; if (CANDISABLEBLEND) g_pHyprOpenGL->blend(false); @@ -176,7 +176,7 @@ CBox CSurfacePassElement::getTexBox() { bool CSurfacePassElement::needsLiveBlur() { auto PSURFACE = CWLSurface::fromResource(data.surface); - const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F); + const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_fAlphaModifier * PSURFACE->m_fOverallOpacity : 1.F); const bool BLUR = data.blur && (!data.texture || !data.texture->m_bOpaque || ALPHA < 1.F); if (!data.pLS && !data.pWindow) @@ -190,7 +190,7 @@ bool CSurfacePassElement::needsLiveBlur() { bool CSurfacePassElement::needsPrecomputeBlur() { auto PSURFACE = CWLSurface::fromResource(data.surface); - const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F); + const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_fAlphaModifier * PSURFACE->m_fOverallOpacity : 1.F); const bool BLUR = data.blur && (!data.texture || !data.texture->m_bOpaque || ALPHA < 1.F); if (!data.pLS && !data.pWindow) @@ -208,7 +208,7 @@ std::optional CSurfacePassElement::boundingBox() { CRegion CSurfacePassElement::opaqueRegion() { auto PSURFACE = CWLSurface::fromResource(data.surface); - const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_pAlphaModifier : 1.F); + const float ALPHA = data.alpha * data.fadeAlpha * (PSURFACE ? PSURFACE->m_fAlphaModifier * PSURFACE->m_fOverallOpacity : 1.F); if (ALPHA < 1.F) return {};