diff --git a/src/core/PortalManager.cpp b/src/core/PortalManager.cpp index 1dd872f..6a4c9d4 100644 --- a/src/core/PortalManager.cpp +++ b/src/core/PortalManager.cpp @@ -235,8 +235,7 @@ void CPortalManager::onGlobal(void* data, struct wl_registry* registry, uint32_t m_sWaylandConnection.shm = (wl_shm*)wl_registry_bind(registry, name, &wl_shm_interface, version); else if (INTERFACE == zwlr_foreign_toplevel_manager_v1_interface.name) - m_sHelpers.toplevel = - std::make_unique((zwlr_foreign_toplevel_manager_v1*)wl_registry_bind(registry, name, &zwlr_foreign_toplevel_manager_v1_interface, version)); + m_sHelpers.toplevel = std::make_unique(registry, name, version); } void CPortalManager::onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name) { diff --git a/src/portals/Screencopy.cpp b/src/portals/Screencopy.cpp index 5f58eec..f0f7a77 100644 --- a/src/portals/Screencopy.cpp +++ b/src/portals/Screencopy.cpp @@ -285,6 +285,8 @@ static const hyprland_toplevel_export_frame_v1_listener hyprlandFrameListener = void CScreencopyPortal::onCreateSession(sdbus::MethodCall& call) { sdbus::ObjectPath requestHandle, sessionHandle; + g_pPortalManager->m_sHelpers.toplevel->activate(); + call >> requestHandle; call >> sessionHandle; @@ -307,6 +309,9 @@ void CScreencopyPortal::onCreateSession(sdbus::MethodCall& call) { } PSESSION->session.release(); Debug::log(LOG, "[screencopy] Session destroyed"); + + // deactivate toplevel so it doesn't listen and waste battery + g_pPortalManager->m_sHelpers.toplevel->deactivate(); }; PSESSION->request = createDBusRequest(requestHandle); PSESSION->request->onDestroy = [PSESSION]() { PSESSION->request.release(); }; @@ -1085,7 +1090,7 @@ uint32_t CPipewireConnection::buildFormatsFor(spa_pod_builder* b[2], const spa_p paramCount = 2; params[0] = build_format(b[0], pwFromDrmFourcc(stream->pSession->sharingData.frameInfoDMA.fmt), stream->pSession->sharingData.frameInfoDMA.w, - stream->pSession->sharingData.frameInfoDMA.h, stream->pSession->sharingData.framerate, modifiers, modCount); + stream->pSession->sharingData.frameInfoDMA.h, stream->pSession->sharingData.framerate, modifiers, modCount); assert(params[0] != NULL); params[1] = build_format(b[1], pwFromDrmFourcc(stream->pSession->sharingData.frameInfoSHM.fmt), stream->pSession->sharingData.frameInfoSHM.w, stream->pSession->sharingData.frameInfoSHM.h, stream->pSession->sharingData.framerate, NULL, 0); @@ -1095,7 +1100,7 @@ uint32_t CPipewireConnection::buildFormatsFor(spa_pod_builder* b[2], const spa_p paramCount = 1; params[0] = build_format(b[0], pwFromDrmFourcc(stream->pSession->sharingData.frameInfoSHM.fmt), stream->pSession->sharingData.frameInfoSHM.w, - stream->pSession->sharingData.frameInfoSHM.h, stream->pSession->sharingData.framerate, NULL, 0); + stream->pSession->sharingData.frameInfoSHM.h, stream->pSession->sharingData.framerate, NULL, 0); } if (modifiers) diff --git a/src/shared/ToplevelManager.cpp b/src/shared/ToplevelManager.cpp index 86cfe01..880bdcd 100644 --- a/src/shared/ToplevelManager.cpp +++ b/src/shared/ToplevelManager.cpp @@ -1,5 +1,6 @@ #include "ToplevelManager.hpp" #include "../helpers/Log.hpp" +#include "../core/PortalManager.hpp" static void toplevelTitle(void* data, zwlr_foreign_toplevel_handle_v1* zwlr_foreign_toplevel_handle_v1, const char* title) { const auto PTL = (SToplevelHandle*)data; @@ -81,11 +82,6 @@ inline const zwlr_foreign_toplevel_manager_v1_listener managerListener = { .finished = managerFinished, }; -CToplevelManager::CToplevelManager(zwlr_foreign_toplevel_manager_v1* mgr) { - m_pManager = mgr; - zwlr_foreign_toplevel_manager_v1_add_listener(mgr, &managerListener, this); -} - bool CToplevelManager::exists(zwlr_foreign_toplevel_handle_v1* handle) { for (auto& h : m_vToplevels) { if (h->handle == handle) @@ -93,4 +89,39 @@ bool CToplevelManager::exists(zwlr_foreign_toplevel_handle_v1* handle) { } return false; +} + +CToplevelManager::CToplevelManager(wl_registry* registry, uint32_t name, uint32_t version) { + m_sWaylandConnection = {registry, name, version}; +} + +void CToplevelManager::activate() { + m_iActivateLocks++; + + Debug::log(LOG, "[toplevel] (activate) locks: {}", m_iActivateLocks); + + if (m_pManager || m_iActivateLocks < 1) + return; + + m_pManager = (zwlr_foreign_toplevel_manager_v1*)wl_registry_bind(m_sWaylandConnection.registry, m_sWaylandConnection.name, &zwlr_foreign_toplevel_manager_v1_interface, + m_sWaylandConnection.version); + zwlr_foreign_toplevel_manager_v1_add_listener(m_pManager, &managerListener, this); + wl_display_roundtrip(g_pPortalManager->m_sWaylandConnection.display); + + Debug::log(LOG, "[toplevel] Activated, bound to {:x}, toplevels: {}", (uintptr_t)m_pManager, m_vToplevels.size()); +} + +void CToplevelManager::deactivate() { + m_iActivateLocks--; + + Debug::log(LOG, "[toplevel] (deactivate) locks: {}", m_iActivateLocks); + + if (!m_pManager || m_iActivateLocks > 0) + return; + + zwlr_foreign_toplevel_manager_v1_destroy(m_pManager); + m_pManager = nullptr; + m_vToplevels.clear(); + + Debug::log(LOG, "[toplevel] unbound manager"); } \ No newline at end of file diff --git a/src/shared/ToplevelManager.hpp b/src/shared/ToplevelManager.hpp index bbf5049..de447ee 100644 --- a/src/shared/ToplevelManager.hpp +++ b/src/shared/ToplevelManager.hpp @@ -17,12 +17,23 @@ struct SToplevelHandle { class CToplevelManager { public: - CToplevelManager(zwlr_foreign_toplevel_manager_v1* mgr); + CToplevelManager(wl_registry* registry, uint32_t name, uint32_t version); + + void activate(); + void deactivate(); bool exists(zwlr_foreign_toplevel_handle_v1* handle); std::vector> m_vToplevels; private: - zwlr_foreign_toplevel_manager_v1* m_pManager; + zwlr_foreign_toplevel_manager_v1* m_pManager = nullptr; + + int64_t m_iActivateLocks = 0; + + struct { + wl_registry* registry = nullptr; + uint32_t name = 0; + uint32_t version = 0; + } m_sWaylandConnection; }; \ No newline at end of file