diff --git a/src/renderer/AsyncResourceManager.cpp b/src/renderer/AsyncResourceManager.cpp index 987c52c..88a66a5 100644 --- a/src/renderer/AsyncResourceManager.cpp +++ b/src/renderer/AsyncResourceManager.cpp @@ -29,12 +29,12 @@ ResourceID CAsyncResourceManager::resourceIDForTextRequest(const CTextResource:: return scopeResourceID(1, H1 ^ (H2 << 1) ^ (H3 << 2) ^ (H4 << 3)); } -ResourceID CAsyncResourceManager::resourceIDForTextCmdRequest(const CTextResource::STextResourceData& s) { - return scopeResourceID(2, resourceIDForTextRequest(s) ^ std::hash{}(std::chrono::system_clock::now().time_since_epoch().count())); +ResourceID CAsyncResourceManager::resourceIDForTextCmdRequest(const CTextResource::STextResourceData& s, size_t revision) { + return scopeResourceID(2, resourceIDForTextRequest(s) ^ (revision << 32)); } ResourceID CAsyncResourceManager::resourceIDForImageRequest(const std::string& path, size_t revision) { - return scopeResourceID(3, std::hash{}(path) ^ std::hash{}(revision)); + return scopeResourceID(3, std::hash{}(path) ^ (revision << 32)); } ResourceID CAsyncResourceManager::resourceIDForScreencopy(const std::string& port) { @@ -44,29 +44,29 @@ 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, "Text resource \"{}\" (resourceID: {}) already requested!", params.text, RESOURCEID); + Debug::log(TRACE, "Reusing text resource \"{}\" (resourceID: {}, widget: 0x{})", params.text, RESOURCEID, (uintptr_t)widget.get()); return RESOURCEID; } auto resource = makeAtomicShared(CTextResource::STextResourceData{params}); CAtomicSharedPointer resourceGeneric{resource}; - Debug::log(LOG, "Requesting text resource \"{}\" (resourceID: {})", params.text, RESOURCEID); + Debug::log(TRACE, "Requesting text resource \"{}\" (resourceID: {}, widget: 0x{})", params.text, RESOURCEID, (uintptr_t)widget.get()); enqueue(RESOURCEID, resourceGeneric, widget); return RESOURCEID; } -ResourceID CAsyncResourceManager::requestTextCmd(const CTextResource::STextResourceData& params, const AWP& widget) { - const auto RESOURCEID = resourceIDForTextCmdRequest(params); +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, "Text cmd resource \"{}\" (resourceID: {}) already requested!", params.text, RESOURCEID); + Debug::log(TRACE, "Reusing text cmd resource \"{}\" revision {} (resourceID: {}, widget: 0x{})", params.text, revision, RESOURCEID, (uintptr_t)widget.get()); return RESOURCEID; } auto resource = makeAtomicShared(CTextResource::STextResourceData{params}); CAtomicSharedPointer resourceGeneric{resource}; - Debug::log(LOG, "Enqueued text cmd resource `{}` (resourceID: {})", params.text, RESOURCEID); + Debug::log(TRACE, "Requesting text cmd resource \"{}\" revision {} (resourceID: {}, widget: 0x{})", 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, "Image resource {} revision {} (resourceID: {}) already requested!", path, revision, RESOURCEID); + Debug::log(TRACE, "Reusing image resource {} revision {} (resourceID: {}, widget: 0x{})", path, revision, RESOURCEID, (uintptr_t)widget.get()); return RESOURCEID; } auto resource = makeAtomicShared(absolutePath(path, "")); CAtomicSharedPointer resourceGeneric{resource}; - Debug::log(LOG, "Image resource {} revision {} (resourceID: {})", path, revision, RESOURCEID); + Debug::log(TRACE, "Requesting image resource {} revision {} (resourceID: {}, widget: 0x{})", path, revision, RESOURCEID, (uintptr_t)widget.get()); enqueue(RESOURCEID, resourceGeneric, widget); return RESOURCEID; } @@ -139,7 +139,11 @@ void CAsyncResourceManager::enqueueScreencopyFrames() { } void CAsyncResourceManager::screencopyToTexture(const CScreencopyFrame& scFrame) { - RASSERT(scFrame.m_ready && m_assets.contains(scFrame.m_resourceID), "Logic error in screencopy gathering."); + if (!scFrame.m_ready || !m_assets.contains(scFrame.m_resourceID)) { + Debug::log(ERR, "Bogus call to CAsyncResourceManager::screencopyToTexture. This is a bug!"); + return; + } + m_assets[scFrame.m_resourceID].texture = scFrame.m_asset; Debug::log(TRACE, "Done sc frame {}", scFrame.m_resourceID); @@ -147,7 +151,7 @@ void CAsyncResourceManager::screencopyToTexture(const CScreencopyFrame& scFrame) std::erase_if(m_scFrames, [&scFrame](const auto& f) { return f.get() == &scFrame; }); if (m_scFrames.empty()) { - Debug::log(TRACE, "Gathered all screencopy frames - removing dmabuf listeners"); + Debug::log(LOG, "Gathered all screencopy frames - removing dmabuf listeners"); g_pHyprlock->removeDmabufListener(); } } diff --git a/src/renderer/AsyncResourceManager.hpp b/src/renderer/AsyncResourceManager.hpp index bb502a7..78c892e 100644 --- a/src/renderer/AsyncResourceManager.hpp +++ b/src/renderer/AsyncResourceManager.hpp @@ -27,7 +27,8 @@ class CAsyncResourceManager { // Those are hash functions that return the id for a requested resource. static ResourceID resourceIDForTextRequest(const CTextResource::STextResourceData& s); - static ResourceID resourceIDForTextCmdRequest(const CTextResource::STextResourceData& s); + // Consumer needs to increment the revision parameter to get a new command evaluation. + static ResourceID resourceIDForTextCmdRequest(const CTextResource::STextResourceData& s, size_t revision); // Image paths may be file system links, thus this function supports a revision parameter that gets factored into the resource id. static ResourceID resourceIDForImageRequest(const std::string& path, size_t revision); static ResourceID resourceIDForScreencopy(const std::string& port); @@ -42,7 +43,7 @@ class CAsyncResourceManager { ResourceID requestText(const CTextResource::STextResourceData& params, const AWP& widget); // Same as requestText but substitute the text with what launching sh -c request.text returns. - ResourceID requestTextCmd(const CTextResource::STextResourceData& params, const AWP& widget); + ResourceID requestTextCmd(const CTextResource::STextResourceData& params, size_t revision, const AWP& widget); ResourceID requestImage(const std::string& path, size_t revision, const AWP& widget); ASP getAssetByID(ResourceID id); diff --git a/src/renderer/widgets/Label.cpp b/src/renderer/widgets/Label.cpp index 1c3e500..a48bfcb 100644 --- a/src/renderer/widgets/Label.cpp +++ b/src/renderer/widgets/Label.cpp @@ -43,7 +43,12 @@ void CLabel::onTimerUpdate() { request.text = label.formatted; AWP widget(m_self); - pendingResourceID = (label.cmd) ? g_asyncResourceManager->requestTextCmd(request, widget.lock()) : g_asyncResourceManager->requestText(request, widget.lock()); + 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()); + } else + pendingResourceID = g_asyncResourceManager->requestText(request, widget.lock()); } void CLabel::plantTimer() { @@ -94,7 +99,10 @@ void CLabel::configure(const std::unordered_map& props, c pos = configPos; // Label size not known yet - resourceID = (label.cmd) ? g_asyncResourceManager->requestTextCmd(request, nullptr) : g_asyncResourceManager->requestText(request, nullptr); + if (label.cmd) { + resourceID = g_asyncResourceManager->requestTextCmd(request, m_dynamicRevision, nullptr); + } else + resourceID = g_asyncResourceManager->requestText(request, nullptr); plantTimer(); } diff --git a/src/renderer/widgets/Label.hpp b/src/renderer/widgets/Label.hpp index d980fc1..ff4dfcf 100644 --- a/src/renderer/widgets/Label.hpp +++ b/src/renderer/widgets/Label.hpp @@ -51,6 +51,8 @@ class CLabel : public IWidget { ResourceID resourceID = 0; ResourceID pendingResourceID = 0; + size_t m_dynamicRevision = 0; + ASP asset = nullptr; std::string outputStringPort;