screenshare: improve destroy logic of objects (#13554)

This commit is contained in:
Ikalco 2026-03-05 08:06:55 -06:00 committed by GitHub
parent 34c7cc7d38
commit 803e81ac39
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 24 additions and 46 deletions

View file

@ -145,17 +145,13 @@ WP<CScreenshareSession> CScreenshareManager::getManagedSession(eScreenshareType
auto& session = *it;
session->stoppedListener = session->m_session->m_events.stopped.listen([session = WP<SManagedSession>(session)]() {
std::erase_if(Screenshare::mgr()->m_managedSessions, [&](const auto& s) { return !s || session.expired() || s->m_session == session->m_session; });
if (!session.expired())
std::erase_if(Screenshare::mgr()->m_managedSessions, [&](const auto& s) { return s && s->m_session.get() == session->m_session.get(); });
});
return session->m_session;
}
void CScreenshareManager::destroyClientSessions(wl_client* client) {
LOGM(Log::TRACE, "Destroy client sessions for {:x}", (uintptr_t)client);
std::erase_if(m_managedSessions, [&](const auto& session) { return !session || session->m_session->m_client == client; });
}
bool CScreenshareManager::isOutputBeingSSd(PHLMONITOR monitor) {
return std::ranges::any_of(m_pendingFrames, [monitor](const auto& f) {
if (!f || !f->m_session)

View file

@ -206,8 +206,6 @@ namespace Screenshare {
UP<CCursorshareSession> newCursorSession(wl_client* client, WP<CWLPointerResource> pointer);
void destroyClientSessions(wl_client* client);
void onOutputCommit(PHLMONITOR monitor);
bool isOutputBeingSSd(PHLMONITOR monitor);

View file

@ -39,7 +39,8 @@ CScreenshareSession::CScreenshareSession(PHLMONITOR monitor, CBox captureRegion,
CScreenshareSession::~CScreenshareSession() {
stop();
LOGM(Log::TRACE, "Destroyed screenshare session for ({}): {}", m_type, m_name);
uintptr_t ptr = m_type == SHARE_WINDOW && !m_window.expired() ? (uintptr_t)m_window.get() : (m_monitor.expired() ? (uintptr_t)nullptr : (uintptr_t)m_monitor.get());
LOGM(Log::TRACE, "Destroyed screenshare session for ({}): {}, {:x}", m_type, m_name, ptr);
}
void CScreenshareSession::stop() {
@ -52,6 +53,9 @@ void CScreenshareSession::stop() {
}
void CScreenshareSession::init() {
uintptr_t ptr = m_type == SHARE_WINDOW && !m_window.expired() ? (uintptr_t)m_window.get() : (m_monitor.expired() ? (uintptr_t)nullptr : (uintptr_t)m_monitor.get());
LOGM(Log::TRACE, "Created screenshare session for ({}): {}, {:x}", m_type, m_name, ptr);
m_shareStopTimer = makeShared<CEventLoopTimer>(
std::chrono::milliseconds(500),
[this](SP<CEventLoopTimer> self, void* data) {
@ -121,7 +125,7 @@ void CScreenshareSession::screenshareEvents(bool startSharing) {
m_sharing = true;
g_pEventManager->postEvent(SHyprIPCEvent{.event = "screencast", .data = std::format("1,{}", m_type)});
g_pEventManager->postEvent(SHyprIPCEvent{.event = "screencastv2", .data = std::format("1,{},{}", m_type, m_name)});
LOGM(Log::INFO, "New screenshare session for ({}): {}", m_type, m_name);
LOGM(Log::INFO, "Started screenshare session for ({}): {}", m_type, m_name);
Event::bus()->m_events.screenshare.state.emit(true, m_type, m_name);
} else if (!startSharing && m_sharing) {

View file

@ -13,10 +13,7 @@ CScreencopyClient::CScreencopyClient(SP<CZwlrScreencopyManagerV1> resource_) : m
return;
m_resource->setDestroy([this](CZwlrScreencopyManagerV1* pMgr) { PROTO::screencopy->destroyResource(this); });
m_resource->setOnDestroy([this](CZwlrScreencopyManagerV1* pMgr) {
Screenshare::mgr()->destroyClientSessions(m_savedClient);
PROTO::screencopy->destroyResource(this);
});
m_resource->setOnDestroy([this](CZwlrScreencopyManagerV1* pMgr) { PROTO::screencopy->destroyResource(this); });
m_resource->setCaptureOutput(
[this](CZwlrScreencopyManagerV1* pMgr, uint32_t frame, int32_t overlayCursor, wl_resource* output) { captureOutput(frame, overlayCursor, output, {}); });
m_resource->setCaptureOutputRegion([this](CZwlrScreencopyManagerV1* pMgr, uint32_t frame, int32_t overlayCursor, wl_resource* output, int32_t x, int32_t y, int32_t w,
@ -25,10 +22,6 @@ CScreencopyClient::CScreencopyClient(SP<CZwlrScreencopyManagerV1> resource_) : m
m_savedClient = m_resource->client();
}
CScreencopyClient::~CScreencopyClient() {
Screenshare::mgr()->destroyClientSessions(m_savedClient);
}
void CScreencopyClient::captureOutput(uint32_t frame, int32_t overlayCursor_, wl_resource* output, CBox box) {
const auto PMONITORRES = CWLOutputResource::fromResource(output);
if (!PMONITORRES || !PMONITORRES->m_monitor) {
@ -69,11 +62,6 @@ CScreencopyFrame::CScreencopyFrame(SP<CZwlrScreencopyFrameV1> resource_, WP<CScr
m_resource->setCopy([this](CZwlrScreencopyFrameV1* pFrame, wl_resource* res) { shareFrame(pFrame, res, false); });
m_resource->setCopyWithDamage([this](CZwlrScreencopyFrameV1* pFrame, wl_resource* res) { shareFrame(pFrame, res, true); });
m_listeners.stopped = m_session->m_events.stopped.listen([this]() {
if (good())
m_resource->sendFailed();
});
m_frame = m_session->nextFrame(overlayCursor);
auto formats = m_session->allowedFormats();
@ -111,6 +99,12 @@ void CScreencopyFrame::shareFrame(CZwlrScreencopyFrameV1* pFrame, wl_resource* b
return;
}
if UNLIKELY (m_session.expired() || !m_session->monitor()) {
LOGM(Log::ERR, "Session stopped for frame {:x}", (uintptr_t)this);
m_resource->sendFailed();
return;
}
if UNLIKELY (m_buffer) {
LOGM(Log::ERR, "Buffer used in {:x}", (uintptr_t)this);
m_resource->error(ZWLR_SCREENCOPY_FRAME_V1_ERROR_ALREADY_USED, "frame already used");

View file

@ -19,7 +19,6 @@ namespace Screenshare {
class CScreencopyClient {
public:
CScreencopyClient(SP<CZwlrScreencopyManagerV1> resource_);
~CScreencopyClient();
bool good();
@ -52,10 +51,7 @@ class CScreencopyFrame {
Time::steady_tp m_timestamp;
bool m_overlayCursor = true;
struct {
CHyprSignalListener stopped;
} m_listeners;
//
void shareFrame(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer, bool withDamage);
friend class CScreencopyProtocol;

View file

@ -13,10 +13,7 @@ CToplevelExportClient::CToplevelExportClient(SP<CHyprlandToplevelExportManagerV1
if UNLIKELY (!good())
return;
m_resource->setOnDestroy([this](CHyprlandToplevelExportManagerV1* pMgr) {
Screenshare::mgr()->destroyClientSessions(m_savedClient);
PROTO::toplevelExport->destroyResource(this);
});
m_resource->setOnDestroy([this](CHyprlandToplevelExportManagerV1* pMgr) { PROTO::toplevelExport->destroyResource(this); });
m_resource->setDestroy([this](CHyprlandToplevelExportManagerV1* pMgr) { PROTO::toplevelExport->destroyResource(this); });
m_resource->setCaptureToplevel([this](CHyprlandToplevelExportManagerV1* pMgr, uint32_t frame, int32_t overlayCursor, uint32_t handle) {
captureToplevel(frame, overlayCursor, g_pCompositor->getWindowFromHandle(handle));
@ -28,10 +25,6 @@ CToplevelExportClient::CToplevelExportClient(SP<CHyprlandToplevelExportManagerV1
m_savedClient = m_resource->client();
}
CToplevelExportClient::~CToplevelExportClient() {
Screenshare::mgr()->destroyClientSessions(m_savedClient);
}
void CToplevelExportClient::captureToplevel(uint32_t frame, int32_t overlayCursor_, PHLWINDOW handle) {
auto session = Screenshare::mgr()->getManagedSession(m_resource->client(), handle);
@ -63,11 +56,6 @@ CToplevelExportFrame::CToplevelExportFrame(SP<CHyprlandToplevelExportFrameV1> re
m_resource->setDestroy([this](CHyprlandToplevelExportFrameV1* pFrame) { PROTO::toplevelExport->destroyResource(this); });
m_resource->setCopy([this](CHyprlandToplevelExportFrameV1* pFrame, wl_resource* res, int32_t ignoreDamage) { shareFrame(res, !!ignoreDamage); });
m_listeners.stopped = m_session->m_events.stopped.listen([this]() {
if (good())
m_resource->sendFailed();
});
m_frame = m_session->nextFrame(overlayCursor);
auto formats = m_session->allowedFormats();
@ -100,6 +88,12 @@ void CToplevelExportFrame::shareFrame(wl_resource* buffer, bool ignoreDamage) {
return;
}
if UNLIKELY (m_session.expired() || !m_session->monitor()) {
LOGM(Log::ERR, "Session stopped for frame {:x}", (uintptr_t)this);
m_resource->sendFailed();
return;
}
if UNLIKELY (m_buffer) {
LOGM(Log::ERR, "Buffer used in {:x}", (uintptr_t)this);
m_resource->error(HYPRLAND_TOPLEVEL_EXPORT_FRAME_V1_ERROR_ALREADY_USED, "frame already used");

View file

@ -18,7 +18,6 @@ namespace Screenshare {
class CToplevelExportClient {
public:
CToplevelExportClient(SP<CHyprlandToplevelExportManagerV1> resource_);
~CToplevelExportClient();
bool good();
@ -50,10 +49,7 @@ class CToplevelExportFrame {
CHLBufferReference m_buffer;
Time::steady_tp m_timestamp;
struct {
CHyprSignalListener stopped;
} m_listeners;
//
void shareFrame(wl_resource* buffer, bool ignoreDamage);
friend class CToplevelExportProtocol;