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
This commit is contained in:
Vaxry 2025-05-17 18:03:35 +01:00 committed by GitHub
parent bb9aa79b21
commit bb5cd5b2dd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 64 additions and 29 deletions

View File

@ -187,19 +187,11 @@ void CScreencopyFrame::share() {
callback(copyShm());
}
void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) {
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY);
void CScreencopyFrame::renderMon() {
auto TEXTURE = makeShared<CTexture>(m_monitor->m_output->state->state().buffer);
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
if (!g_pHyprRenderer->beginRender(m_monitor.lock(), fakeDamage, RENDER_MODE_TO_BUFFER, m_buffer.m_buffer, nullptr, true)) {
LOGM(ERR, "Can't copy: failed to begin rendering to dma frame");
callback(false);
return;
}
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);
@ -211,6 +203,43 @@ void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) {
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<void(bool)> callback) {
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY);
CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX};
if (!g_pHyprRenderer->beginRender(m_monitor.lock(), fakeDamage, RENDER_MODE_TO_BUFFER, m_buffer.m_buffer, nullptr, true)) {
LOGM(ERR, "Can't copy: failed to begin rendering to dma frame");
callback(false);
return;
}
if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) {
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 {
@ -229,7 +258,6 @@ void CScreencopyFrame::copyDmabuf(std::function<void(bool)> callback) {
bool CScreencopyFrame::copyShm() {
const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(m_resource->client(), PERMISSION_TYPE_SCREENCOPY);
auto TEXTURE = makeShared<CTexture>(m_monitor->m_output->state->state().buffer);
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.

View File

@ -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 <aquamarine/buffer/Buffer.hpp>
@ -72,9 +73,14 @@ class CScreencopyFrame {
int m_shmStride = 0;
CBox m_box = {};
// if we have a pending perm, hold the buffer.
CFramebuffer m_tempFb;
void copy(CZwlrScreencopyFrameV1* pFrame, wl_resource* buffer);
void copyDmabuf(std::function<void(bool)> callback);
bool copyShm();
void renderMon();
void storeTempFB();
void share();
friend class CScreencopyProtocol;