From dc23ed8a4e41938b9448c8e0c7c6de655a0cbc93 Mon Sep 17 00:00:00 2001 From: vaxerski <43317083+vaxerski@users.noreply.github.com> Date: Sun, 4 Dec 2022 20:10:34 +0000 Subject: [PATCH] fix crashes --- src/events/Windows.cpp | 2 + src/protocols/ToplevelExport.cpp | 74 ++++++++++++++++++++------------ src/protocols/ToplevelExport.hpp | 5 ++- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/src/events/Windows.cpp b/src/events/Windows.cpp index 6f524da2..9f44e23c 100644 --- a/src/events/Windows.cpp +++ b/src/events/Windows.cpp @@ -556,6 +556,8 @@ void Events::listener_unmapWindow(void* owner, void* data) { g_pEventManager->postEvent(SHyprIPCEvent{"closewindow", getFormat("%x", PWINDOW)}); + g_pProtocolManager->m_pToplevelExportProtocolManager->onWindowUnmap(PWINDOW); + if (!PWINDOW->m_bIsX11) { Debug::log(LOG, "Unregistered late callbacks XDG"); PWINDOW->hyprListener_commitWindow.removeCallback(); diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index ca798da3..458171d0 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -77,14 +77,16 @@ SToplevelFrame* frameFromResource(wl_resource* resource) { return (SToplevelFrame*)wl_resource_get_user_data(resource); } -void CToplevelExportProtocolManager::removeClient(SToplevelClient* client) { - if (!client || client->ref <= 0) - return; +void CToplevelExportProtocolManager::removeClient(SToplevelClient* client, bool force) { + if (!force) { + if (!client || client->ref <= 0) + return; - if (--client->ref != 0) - return; + if (--client->ref != 0) + return; + } - m_lClients.remove(*client); + m_lClients.remove(*client); // TODO: this doesn't get cleaned up after sharing app exits??? } void handleManagerResourceDestroy(wl_resource* resource) { @@ -119,13 +121,15 @@ void handleFrameResourceDestroy(wl_resource* resource) { g_pProtocolManager->m_pToplevelExportProtocolManager->removeFrame(PFRAME); } -void CToplevelExportProtocolManager::removeFrame(SToplevelFrame* frame) { +void CToplevelExportProtocolManager::removeFrame(SToplevelFrame* frame, bool force) { if (!frame) return; + std::erase_if(m_vFramesAwaitingWrite, [&] (const auto& other) { return other == frame; }); + wl_resource_set_user_data(frame->resource, nullptr); wlr_buffer_unlock(frame->buffer); - removeClient(frame->client); + removeClient(frame->client, force); m_lFrames.remove(*frame); } @@ -134,24 +138,26 @@ void CToplevelExportProtocolManager::captureToplevel(wl_client* client, wl_resou const auto PWINDOW = g_pCompositor->getWindowFromHandle(handle); - if (!PWINDOW) { - Debug::log(ERR, "Client requested sharing of window handle %x which does not exist!", handle); - hyprland_toplevel_export_frame_v1_send_failed(resource); - return; - } - - if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden()) { - Debug::log(ERR, "Client requested sharing of window handle %x which is not shareable!", handle); - hyprland_toplevel_export_frame_v1_send_failed(resource); - return; - } - // create a frame const auto PFRAME = &m_lFrames.emplace_back(); PFRAME->overlayCursor = !!overlay_cursor; PFRAME->resource = wl_resource_create(client, &hyprland_toplevel_export_frame_v1_interface, wl_resource_get_version(resource), frame); PFRAME->pWindow = PWINDOW; + if (!PWINDOW) { + Debug::log(ERR, "Client requested sharing of window handle %x which does not exist!", handle); + hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource); + removeFrame(PFRAME); + return; + } + + if (!PWINDOW->m_bIsMapped || PWINDOW->isHidden()) { + Debug::log(ERR, "Client requested sharing of window handle %x which is not shareable!", handle); + hyprland_toplevel_export_frame_v1_send_failed(PFRAME->resource); + removeFrame(PFRAME); + return; + } + if (!PFRAME->resource) { Debug::log(ERR, "Couldn't alloc frame for sharing! (no memory)"); m_lFrames.remove(*PFRAME); @@ -264,9 +270,15 @@ void CToplevelExportProtocolManager::onMonitorRender(CMonitor* pMonitor) { if (m_vFramesAwaitingWrite.empty()) return; // nothing to share + std::vector framesToRemove; // share frame if correct output for (auto& f : m_vFramesAwaitingWrite) { + if (!f->pWindow) { + framesToRemove.push_back(f); + continue; + } + wlr_box geometry = { f->pWindow->m_vRealPosition.vec().x, f->pWindow->m_vRealPosition.vec().y, f->pWindow->m_vRealSize.vec().x, f->pWindow->m_vRealSize.vec().y }; @@ -274,18 +286,22 @@ void CToplevelExportProtocolManager::onMonitorRender(CMonitor* pMonitor) { continue; shareFrame(f); + + framesToRemove.push_back(f); + } + + for (auto& f : framesToRemove) { + removeFrame(f); } } void CToplevelExportProtocolManager::shareFrame(SToplevelFrame* frame) { - if (!frame->buffer) + if (!frame->buffer) { return; + } // TODO: damage - // remove this frame from awaiting. - std::erase_if(m_vFramesAwaitingWrite, [&] (const SToplevelFrame* other) { return other == frame; }); - timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -293,13 +309,11 @@ void CToplevelExportProtocolManager::shareFrame(SToplevelFrame* frame) { if (frame->bufferCap == WLR_BUFFER_CAP_DMABUF) { if (!copyFrameDmabuf(frame)) { hyprland_toplevel_export_frame_v1_send_failed(frame->resource); - removeFrame(frame); return; } } else { if (!copyFrameShm(frame, &now)) { hyprland_toplevel_export_frame_v1_send_failed(frame->resource); - removeFrame(frame); return; } } @@ -309,7 +323,6 @@ void CToplevelExportProtocolManager::shareFrame(SToplevelFrame* frame) { uint32_t tvSecHi = (sizeof(now.tv_sec) > 4) ? now.tv_sec >> 32 : 0; uint32_t tvSecLo = now.tv_sec & 0xFFFFFFFF; hyprland_toplevel_export_frame_v1_send_ready(frame->resource, tvSecHi, tvSecLo, now.tv_nsec); - removeFrame(frame); } bool CToplevelExportProtocolManager::copyFrameShm(SToplevelFrame* frame, timespec* now) { @@ -359,4 +372,11 @@ bool CToplevelExportProtocolManager::copyFrameDmabuf(SToplevelFrame* frame) { // todo Debug::log(ERR, "DMABUF copying not impl'd!"); return false; +} + +void CToplevelExportProtocolManager::onWindowUnmap(CWindow* pWindow) { + for (auto& f : m_lFrames) { + if (f.pWindow == pWindow) + f.pWindow = nullptr; + } } \ No newline at end of file diff --git a/src/protocols/ToplevelExport.hpp b/src/protocols/ToplevelExport.hpp index c4320b00..bdf5cfd6 100644 --- a/src/protocols/ToplevelExport.hpp +++ b/src/protocols/ToplevelExport.hpp @@ -46,12 +46,13 @@ public: void bindManager(wl_client* client, void* data, uint32_t version, uint32_t id); void captureToplevel(wl_client* client, wl_resource* resource, uint32_t frame, int32_t overlay_cursor, uint32_t handle); - void removeClient(SToplevelClient* client); - void removeFrame(SToplevelFrame* frame); + void removeClient(SToplevelClient* client, bool force = false); + void removeFrame(SToplevelFrame* frame, bool force = false); void copyFrame(wl_client* client, wl_resource* resource, wl_resource* buffer, int32_t ignore_damage); void onMonitorRender(CMonitor* pMonitor); void displayDestroy(); + void onWindowUnmap(CWindow* pWindow); private: wl_global* m_pGlobal = nullptr;