From bb5cd5b2ddcb2dbe58613aa41fa2062208208339 Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Sat, 17 May 2025 18:03:35 +0100 Subject: [PATCH] screencopy: store a fb before permission popup if the permission is pending (#10455) stops rendering the permission popup on stuff like grim when it asks --- src/protocols/Screencopy.cpp | 79 ++++++++++++++++++++++++------------ src/protocols/Screencopy.hpp | 14 +++++-- 2 files changed, 64 insertions(+), 29 deletions(-) diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index 1afa477f..5fa7c84e 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -187,9 +187,43 @@ void CScreencopyFrame::share() { callback(copyShm()); } +void CScreencopyFrame::renderMon() { + auto TEXTURE = makeShared(m_monitor->m_output->state->state().buffer); + + CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; + + CBox monbox = CBox{0, 0, m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y} + .translate({-m_box.x, -m_box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. + .transform(wlTransformToHyprutils(invertTransform(m_monitor->m_transform)), m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y); + g_pHyprOpenGL->setMonitorTransformEnabled(true); + g_pHyprOpenGL->setRenderModifEnabled(false); + g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); + g_pHyprOpenGL->setRenderModifEnabled(true); + g_pHyprOpenGL->setMonitorTransformEnabled(false); + if (m_overlayCursor) + g_pPointerManager->renderSoftwareCursorsFor(m_monitor.lock(), Time::steadyNow(), fakeDamage, + g_pInputManager->getMouseCoordsInternal() - m_monitor->m_position - m_box.pos(), true); +} + +void CScreencopyFrame::storeTempFB() { + g_pHyprRenderer->makeEGLCurrent(); + + m_tempFb.alloc(m_box.w, m_box.h); + + CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; + + if (!g_pHyprRenderer->beginRender(m_monitor.lock(), fakeDamage, RENDER_MODE_FULL_FAKE, nullptr, &m_tempFb, true)) { + LOGM(ERR, "Can't copy: failed to begin rendering to temp fb"); + return; + } + + renderMon(); + + g_pHyprRenderer->endRender(); +} + void CScreencopyFrame::copyDmabuf(std::function callback) { - const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY); - auto TEXTURE = makeShared(m_monitor->m_output->state->state().buffer); + const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY); CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; @@ -200,17 +234,12 @@ void CScreencopyFrame::copyDmabuf(std::function callback) { } if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) { - CBox monbox = CBox{0, 0, m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y} - .translate({-m_box.x, -m_box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. - .transform(wlTransformToHyprutils(invertTransform(m_monitor->m_transform)), m_monitor->m_pixelSize.x, m_monitor->m_pixelSize.y); - g_pHyprOpenGL->setMonitorTransformEnabled(true); - g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); - g_pHyprOpenGL->setRenderModifEnabled(true); - g_pHyprOpenGL->setMonitorTransformEnabled(false); - if (m_overlayCursor) - g_pPointerManager->renderSoftwareCursorsFor(m_monitor.lock(), Time::steadyNow(), fakeDamage, - g_pInputManager->getMouseCoordsInternal() - m_monitor->m_position - m_box.pos(), true); + if (m_tempFb.isAllocated()) { + CBox texbox = {{}, m_box.size()}; + g_pHyprOpenGL->renderTexture(m_tempFb.getTexture(), texbox, 1); + m_tempFb.release(); + } else + renderMon(); } else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) g_pHyprOpenGL->clear(Colors::BLACK); else { @@ -228,8 +257,7 @@ void CScreencopyFrame::copyDmabuf(std::function callback) { } bool CScreencopyFrame::copyShm() { - const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY); - auto TEXTURE = makeShared(m_monitor->m_output->state->state().buffer); + const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY); auto shm = m_buffer->shm(); auto [pixelData, fmt, bufLen] = m_buffer->beginDataPtr(0); // no need for end, cuz it's shm @@ -247,15 +275,12 @@ bool CScreencopyFrame::copyShm() { } if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) { - CBox monbox = CBox{0, 0, m_monitor->m_transformedSize.x, m_monitor->m_transformedSize.y}.translate({-m_box.x, -m_box.y}); - g_pHyprOpenGL->setMonitorTransformEnabled(true); - g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); - g_pHyprOpenGL->setRenderModifEnabled(true); - g_pHyprOpenGL->setMonitorTransformEnabled(false); - if (m_overlayCursor) - g_pPointerManager->renderSoftwareCursorsFor(m_monitor.lock(), Time::steadyNow(), fakeDamage, - g_pInputManager->getMouseCoordsInternal() - m_monitor->m_position - m_box.pos(), true); + if (m_tempFb.isAllocated()) { + CBox texbox = {{}, m_box.size()}; + g_pHyprOpenGL->renderTexture(m_tempFb.getTexture(), texbox, 1); + m_tempFb.release(); + } else + renderMon(); } else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) g_pHyprOpenGL->clear(Colors::BLACK); else { @@ -420,8 +445,12 @@ void CScreencopyProtocol::onOutputCommit(PHLMONITOR pMonitor) { // check permissions const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(f->m_resource->client(), PERMISSION_TYPE_SCREENCOPY); - if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) + if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) { + if (!f->m_tempFb.isAllocated()) + f->storeTempFB(); // make a snapshot before the popup + continue; // pending an answer, don't do anything yet. + } // otherwise share. If it's denied, it will be black. diff --git a/src/protocols/Screencopy.hpp b/src/protocols/Screencopy.hpp index ead8b2ed..665fede1 100644 --- a/src/protocols/Screencopy.hpp +++ b/src/protocols/Screencopy.hpp @@ -10,6 +10,7 @@ #include "../managers/HookSystemManager.hpp" #include "../helpers/time/Timer.hpp" #include "../helpers/time/Time.hpp" +#include "../render/Framebuffer.hpp" #include "../managers/eventLoop/EventLoopTimer.hpp" #include @@ -72,10 +73,15 @@ class CScreencopyFrame { int m_shmStride = 0; CBox m_box = {}; - void copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer); - void copyDmabuf(std::function callback); - bool copyShm(); - void share(); + // if we have a pending perm, hold the buffer. + CFramebuffer m_tempFb; + + void copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer); + void copyDmabuf(std::function callback); + bool copyShm(); + void renderMon(); + void storeTempFB(); + void share(); friend class CScreencopyProtocol; };