diff --git a/src/renderer/AsyncResourceManager.cpp b/src/renderer/AsyncResourceManager.cpp index 88a66a5..a015e81 100644 --- a/src/renderer/AsyncResourceManager.cpp +++ b/src/renderer/AsyncResourceManager.cpp @@ -44,14 +44,14 @@ ResourceID CAsyncResourceManager::resourceIDForScreencopy(const std::string& por ResourceID CAsyncResourceManager::requestText(const CTextResource::STextResourceData& params, const AWP& widget) { const auto RESOURCEID = resourceIDForTextRequest(params); if (request(RESOURCEID, widget)) { - Debug::log(TRACE, "Reusing text resource \"{}\" (resourceID: {}, widget: 0x{})", params.text, RESOURCEID, (uintptr_t)widget.get()); + Debug::log(TRACE, "Reusing text resource \"{}\" (resourceID: {})", params.text, RESOURCEID, (uintptr_t)widget.get()); return RESOURCEID; } auto resource = makeAtomicShared(CTextResource::STextResourceData{params}); CAtomicSharedPointer resourceGeneric{resource}; - Debug::log(TRACE, "Requesting text resource \"{}\" (resourceID: {}, widget: 0x{})", params.text, RESOURCEID, (uintptr_t)widget.get()); + Debug::log(TRACE, "Requesting text resource \"{}\" (resourceID: {})", params.text, RESOURCEID, (uintptr_t)widget.get()); enqueue(RESOURCEID, resourceGeneric, widget); return RESOURCEID; } @@ -59,14 +59,14 @@ ResourceID CAsyncResourceManager::requestText(const CTextResource::STextResource ResourceID CAsyncResourceManager::requestTextCmd(const CTextResource::STextResourceData& params, size_t revision, const AWP& widget) { const auto RESOURCEID = resourceIDForTextCmdRequest(params, revision); if (request(RESOURCEID, widget)) { - Debug::log(TRACE, "Reusing text cmd resource \"{}\" revision {} (resourceID: {}, widget: 0x{})", params.text, revision, RESOURCEID, (uintptr_t)widget.get()); + Debug::log(TRACE, "Reusing text cmd resource \"{}\" revision {} (resourceID: {})", params.text, revision, RESOURCEID, (uintptr_t)widget.get()); return RESOURCEID; } auto resource = makeAtomicShared(CTextResource::STextResourceData{params}); CAtomicSharedPointer resourceGeneric{resource}; - Debug::log(TRACE, "Requesting text cmd resource \"{}\" revision {} (resourceID: {}, widget: 0x{})", params.text, revision, RESOURCEID, (uintptr_t)widget.get()); + Debug::log(TRACE, "Requesting text cmd resource \"{}\" revision {} (resourceID: {})", params.text, revision, RESOURCEID, (uintptr_t)widget.get()); enqueue(RESOURCEID, resourceGeneric, widget); return RESOURCEID; } @@ -74,14 +74,14 @@ ResourceID CAsyncResourceManager::requestTextCmd(const CTextResource::STextResou ResourceID CAsyncResourceManager::requestImage(const std::string& path, size_t revision, const AWP& widget) { const auto RESOURCEID = resourceIDForImageRequest(path, revision); if (request(RESOURCEID, widget)) { - Debug::log(TRACE, "Reusing image resource {} revision {} (resourceID: {}, widget: 0x{})", path, revision, RESOURCEID, (uintptr_t)widget.get()); + Debug::log(TRACE, "Reusing image resource {} revision {} (resourceID: {})", path, revision, RESOURCEID, (uintptr_t)widget.get()); return RESOURCEID; } auto resource = makeAtomicShared(absolutePath(path, "")); CAtomicSharedPointer resourceGeneric{resource}; - Debug::log(TRACE, "Requesting image resource {} revision {} (resourceID: {}, widget: 0x{})", path, revision, RESOURCEID, (uintptr_t)widget.get()); + Debug::log(TRACE, "Requesting image resource {} revision {} (resourceID: {})", path, revision, RESOURCEID, (uintptr_t)widget.get()); enqueue(RESOURCEID, resourceGeneric, widget); return RESOURCEID; } @@ -248,14 +248,12 @@ bool CAsyncResourceManager::request(ResourceID id, const AWP& widget) { if (m_assets[id].texture) { // Asset already present. Dispatch the asset callback function. const auto& TEXTURE = m_assets[id].texture; + Debug::log(LOG, "onAssetUpdate {}", id); if (widget) - g_pHyprlock->addTimer( - std::chrono::milliseconds(0), - [widget, TEXTURE](auto, auto) { - if (const auto WIDGET = widget.lock(); WIDGET) - WIDGET->onAssetUpdate(TEXTURE); - }, - nullptr); + widget->onAssetUpdate(id, TEXTURE); + + // TODO: add a centalized mechanism to render in one place in the event loop to avoid duplicate render calls + g_pHyprlock->addTimer(std::chrono::milliseconds(0), [](auto, auto) { g_pHyprlock->renderAllOutputs(); }, nullptr); } else if (widget) { // Asset currently in-flight. Add the widget reference to in order for the callback to get dispatched later. m_resourcesMutex.lock(); @@ -335,9 +333,11 @@ void CAsyncResourceManager::onResourceFinished(ResourceID id) { for (const auto& widget : WIDGETS) { if (widget) - widget->onAssetUpdate(texture); + widget->onAssetUpdate(id, texture); } + g_pHyprlock->renderAllOutputs(); + if (!m_gathered && !g_pHyprlock->m_bImmediateRender) { m_resourcesMutex.lock(); if (m_resources.empty()) { diff --git a/src/renderer/widgets/Background.cpp b/src/renderer/widgets/Background.cpp index 54248f1..c938340 100644 --- a/src/renderer/widgets/Background.cpp +++ b/src/renderer/widgets/Background.cpp @@ -250,7 +250,7 @@ bool CBackground::draw(const SRenderData& data) { return crossFadeProgress->isBeingAnimated() || data.opacity < 1.0; } -void CBackground::onAssetUpdate(ASP newAsset) { +void CBackground::onAssetUpdate(ResourceID id, ASP newAsset) { pendingResourceID = 0; if (!newAsset) @@ -278,8 +278,6 @@ void CBackground::onAssetUpdate(ASP newAsset) { } }, true); - - g_pHyprlock->renderOutput(outputPort); } } diff --git a/src/renderer/widgets/Background.hpp b/src/renderer/widgets/Background.hpp index 36608a7..52784a7 100644 --- a/src/renderer/widgets/Background.hpp +++ b/src/renderer/widgets/Background.hpp @@ -24,7 +24,7 @@ class CBackground : public IWidget { virtual void configure(const std::unordered_map& props, const SP& pOutput); virtual bool draw(const SRenderData& data); - virtual void onAssetUpdate(ASP newAsset); + virtual void onAssetUpdate(ResourceID id, ASP newAsset); void reset(); // Unload assets, remove timers, etc. diff --git a/src/renderer/widgets/IWidget.hpp b/src/renderer/widgets/IWidget.hpp index 1db4847..15df364 100644 --- a/src/renderer/widgets/IWidget.hpp +++ b/src/renderer/widgets/IWidget.hpp @@ -20,9 +20,10 @@ class IWidget { virtual ~IWidget() = default; - virtual void configure(const std::unordered_map& prop, const SP& pOutput) = 0; - virtual bool draw(const SRenderData& data) = 0; - virtual void onAssetUpdate(ASP newAsset) = 0; + virtual void configure(const std::unordered_map& prop, const SP& pOutput) = 0; + virtual bool draw(const SRenderData& data) = 0; + // Never render within onAssetUpdate! + virtual void onAssetUpdate(ResourceID id, ASP newAsset) = 0; static Vector2D posFromHVAlign(const Vector2D& viewport, const Vector2D& size, const Vector2D& offset, const std::string& halign, const std::string& valign, const double& ang = 0); diff --git a/src/renderer/widgets/Image.cpp b/src/renderer/widgets/Image.cpp index aceef7a..1846d70 100644 --- a/src/renderer/widgets/Image.cpp +++ b/src/renderer/widgets/Image.cpp @@ -25,6 +25,11 @@ static void onTimer(AWP ref) { } void CImage::onTimerUpdate() { + if (m_pendingResource) { + Debug::log(WARN, "Trying to update image, but a resource is still pending! Skipping update."); + return; + } + const std::string OLDPATH = path; if (!reloadCommand.empty()) { @@ -56,11 +61,10 @@ void CImage::onTimerUpdate() { return; } - if (pendingResourceID > 0) - return; + m_pendingResource = true; AWP widget(m_self); - pendingResourceID = g_asyncResourceManager->requestImage(path, m_imageRevision, widget); + g_asyncResourceManager->requestImage(path, m_imageRevision, widget); } void CImage::plantTimer() { @@ -126,7 +130,7 @@ void CImage::reset() { g_asyncResourceManager->unload(asset); asset = nullptr; - pendingResourceID = 0; + m_pendingResource = false; resourceID = 0; } @@ -205,11 +209,11 @@ bool CImage::draw(const SRenderData& data) { return data.opacity < 1.0; } -void CImage::onAssetUpdate(ASP newAsset) { - pendingResourceID = 0; +void CImage::onAssetUpdate(ResourceID id, ASP newAsset) { + m_pendingResource = false; if (!newAsset) - Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", pendingResourceID); + Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", id); else if (newAsset->m_iType == TEXTURE_INVALID) { g_asyncResourceManager->unload(newAsset); Debug::log(ERR, "New image asset has an invalid texture!"); @@ -218,10 +222,8 @@ void CImage::onAssetUpdate(ASP newAsset) { imageFB.destroyBuffer(); asset = newAsset; - resourceID = pendingResourceID; + resourceID = id; firstRender = true; - - g_pHyprlock->renderOutput(stringPort); } } diff --git a/src/renderer/widgets/Image.hpp b/src/renderer/widgets/Image.hpp index 65447e2..03a3597 100644 --- a/src/renderer/widgets/Image.hpp +++ b/src/renderer/widgets/Image.hpp @@ -24,7 +24,7 @@ class CImage : public IWidget { virtual void configure(const std::unordered_map& props, const SP& pOutput); virtual bool draw(const SRenderData& data); - virtual void onAssetUpdate(ASP newAsset); + virtual void onAssetUpdate(ResourceID id, ASP newAsset); virtual CBox getBoundingBoxWl() const; virtual void onClick(uint32_t button, bool down, const Vector2D& pos); @@ -66,7 +66,7 @@ class CImage : public IWidget { std::string stringPort; ResourceID resourceID = 0; - ResourceID pendingResourceID = 0; + bool m_pendingResource = false; ASP asset = nullptr; CShadowable shadow; diff --git a/src/renderer/widgets/Label.cpp b/src/renderer/widgets/Label.cpp index a48bfcb..f391072 100644 --- a/src/renderer/widgets/Label.cpp +++ b/src/renderer/widgets/Label.cpp @@ -6,6 +6,7 @@ #include "../../helpers/Color.hpp" #include "../../helpers/MiscFunctions.hpp" #include "../../config/ConfigDataValues.hpp" +#include "src/defines.hpp" #include #include @@ -27,6 +28,11 @@ static void onTimer(AWP ref) { } void CLabel::onTimerUpdate() { + if (m_pendingResource) { + Debug::log(WARN, "Trying to update label, but a resource is still pending! Skipping update."); + return; + } + std::string oldFormatted = label.formatted; label = formatString(labelPreFormat); @@ -34,21 +40,17 @@ void CLabel::onTimerUpdate() { if (label.formatted == oldFormatted && !label.alwaysUpdate) return; - if (pendingResourceID > 0) { - Debug::log(WARN, "Trying to update label, but resource {} is still pending! Skipping update.", pendingResourceID); - return; - } - // request new - request.text = label.formatted; + request.text = label.formatted; + m_pendingResource = true; AWP widget(m_self); if (label.cmd) { // Don't increment by one to avoid clashes with multiple widget using the same label command. m_dynamicRevision += label.updateEveryMs; - pendingResourceID = g_asyncResourceManager->requestTextCmd(request, m_dynamicRevision, widget.lock()); + g_asyncResourceManager->requestTextCmd(request, m_dynamicRevision, widget.lock()); } else - pendingResourceID = g_asyncResourceManager->requestText(request, widget.lock()); + g_asyncResourceManager->requestText(request, widget.lock()); } void CLabel::plantTimer() { @@ -120,7 +122,7 @@ void CLabel::reset() { g_asyncResourceManager->unload(asset); asset = nullptr; - pendingResourceID = 0; + m_pendingResource = false; resourceID = 0; } @@ -149,11 +151,12 @@ bool CLabel::draw(const SRenderData& data) { return false; } -void CLabel::onAssetUpdate(ASP newAsset) { - pendingResourceID = 0; +void CLabel::onAssetUpdate(ResourceID id, ASP newAsset) { + Debug::log(LOG, "Label update for resourceID {}", id); + m_pendingResource = false; if (!newAsset) - Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", pendingResourceID); + Debug::log(ERR, "asset update failed, resourceID: {} not available on update!", id); else if (newAsset->m_iType == TEXTURE_INVALID) { g_asyncResourceManager->unload(newAsset); Debug::log(ERR, "New image asset has an invalid texture!"); @@ -161,10 +164,8 @@ void CLabel::onAssetUpdate(ASP newAsset) { // new asset is ready :D g_asyncResourceManager->unload(asset); asset = newAsset; - resourceID = pendingResourceID; + resourceID = id; updateShadow = true; - - g_pHyprlock->renderOutput(outputStringPort); } } diff --git a/src/renderer/widgets/Label.hpp b/src/renderer/widgets/Label.hpp index ff4dfcf..4529432 100644 --- a/src/renderer/widgets/Label.hpp +++ b/src/renderer/widgets/Label.hpp @@ -22,7 +22,7 @@ class CLabel : public IWidget { virtual void configure(const std::unordered_map& prop, const SP& pOutput); virtual bool draw(const SRenderData& data); - virtual void onAssetUpdate(ASP newAsset); + virtual void onAssetUpdate(ResourceID id, ASP newAsset); virtual CBox getBoundingBoxWl() const; virtual void onClick(uint32_t button, bool down, const Vector2D& pos); @@ -49,7 +49,7 @@ class CLabel : public IWidget { double angle; ResourceID resourceID = 0; - ResourceID pendingResourceID = 0; + bool m_pendingResource = false; size_t m_dynamicRevision = 0; diff --git a/src/renderer/widgets/PasswordInputField.cpp b/src/renderer/widgets/PasswordInputField.cpp index f5a8283..e7f63ee 100644 --- a/src/renderer/widgets/PasswordInputField.cpp +++ b/src/renderer/widgets/PasswordInputField.cpp @@ -363,8 +363,8 @@ void CPasswordInputField::updatePlaceholder() { placeholder.resourceID = g_asyncResourceManager->requestText(request, widget); } -void CPasswordInputField::onAssetUpdate(ASP newAsset) { - g_pHyprlock->renderOutput(outputStringPort); +void CPasswordInputField::onAssetUpdate(ResourceID id, ASP newAsset) { + ; } void CPasswordInputField::updateWidth() { diff --git a/src/renderer/widgets/PasswordInputField.hpp b/src/renderer/widgets/PasswordInputField.hpp index d5c0075..ec0aa11 100644 --- a/src/renderer/widgets/PasswordInputField.hpp +++ b/src/renderer/widgets/PasswordInputField.hpp @@ -24,7 +24,7 @@ class CPasswordInputField : public IWidget { virtual void configure(const std::unordered_map& prop, const SP& pOutput); virtual bool draw(const SRenderData& data); - virtual void onAssetUpdate(ASP newAsset); + virtual void onAssetUpdate(ResourceID id, ASP newAsset); virtual void onHover(const Vector2D& pos); virtual CBox getBoundingBoxWl() const; diff --git a/src/renderer/widgets/Shape.cpp b/src/renderer/widgets/Shape.cpp index 6777720..51dfa4a 100644 --- a/src/renderer/widgets/Shape.cpp +++ b/src/renderer/widgets/Shape.cpp @@ -105,7 +105,7 @@ bool CShape::draw(const SRenderData& data) { return data.opacity < 1.0; } -void CShape::onAssetUpdate(ASP newAsset) { +void CShape::onAssetUpdate(ResourceID id, ASP newAsset) { ; } diff --git a/src/renderer/widgets/Shape.hpp b/src/renderer/widgets/Shape.hpp index aaa8a59..b2be862 100644 --- a/src/renderer/widgets/Shape.hpp +++ b/src/renderer/widgets/Shape.hpp @@ -18,7 +18,7 @@ class CShape : public IWidget { virtual void configure(const std::unordered_map& prop, const SP& pOutput); virtual bool draw(const SRenderData& data); - virtual void onAssetUpdate(ASP newAsset); + virtual void onAssetUpdate(ResourceID id, ASP newAsset); virtual CBox getBoundingBoxWl() const; virtual void onClick(uint32_t button, bool down, const Vector2D& pos);