From 260d8e1f71b1dc6f3f354747debdc87d96b9e99f Mon Sep 17 00:00:00 2001 From: Vaxry <43317083+vaxerski@users.noreply.github.com> Date: Tue, 8 Apr 2025 19:39:53 +0200 Subject: Permission Manager: add permission management for screencopy (#9930) --- src/protocols/Screencopy.cpp | 65 +++++++++++++++++++++++++++++----------- src/protocols/ToplevelExport.cpp | 48 ++++++++++++++++++++--------- 2 files changed, 81 insertions(+), 32 deletions(-) (limited to 'src/protocols') diff --git a/src/protocols/Screencopy.cpp b/src/protocols/Screencopy.cpp index c124e6d2..afa61f36 100644 --- a/src/protocols/Screencopy.cpp +++ b/src/protocols/Screencopy.cpp @@ -3,6 +3,7 @@ #include "../managers/eventLoop/EventLoopManager.hpp" #include "../managers/PointerManager.hpp" #include "../managers/EventManager.hpp" +#include "../managers/permissions/DynamicPermissionManager.hpp" #include "../render/Renderer.hpp" #include "../render/OpenGL.hpp" #include "../helpers/Monitor.hpp" @@ -196,9 +197,10 @@ void CScreencopyFrame::share() { } void CScreencopyFrame::copyDmabuf(std::function callback) { - auto TEXTURE = makeShared(pMonitor->output->state->state().buffer); + const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(resource->client(), PERMISSION_TYPE_SCREENCOPY); + auto TEXTURE = makeShared(pMonitor->output->state->state().buffer); - CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; + CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; if (!g_pHyprRenderer->beginRender(pMonitor.lock(), fakeDamage, RENDER_MODE_TO_BUFFER, buffer.buffer, nullptr, true)) { LOGM(ERR, "Can't copy: failed to begin rendering to dma frame"); @@ -206,14 +208,23 @@ void CScreencopyFrame::copyDmabuf(std::function callback) { return; } - CBox monbox = CBox{0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y} - .translate({-box.x, -box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. - .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); - g_pHyprOpenGL->setMonitorTransformEnabled(true); - g_pHyprOpenGL->setRenderModifEnabled(false); - g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); - g_pHyprOpenGL->setRenderModifEnabled(true); - g_pHyprOpenGL->setMonitorTransformEnabled(false); + if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) { + CBox monbox = CBox{0, 0, pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y} + .translate({-box.x, -box.y}) // vvvv kinda ass-backwards but that's how I designed the renderer... sigh. + .transform(wlTransformToHyprutils(invertTransform(pMonitor->transform)), pMonitor->vecPixelSize.x, pMonitor->vecPixelSize.y); + g_pHyprOpenGL->setMonitorTransformEnabled(true); + g_pHyprOpenGL->setRenderModifEnabled(false); + g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); + g_pHyprOpenGL->setRenderModifEnabled(true); + g_pHyprOpenGL->setMonitorTransformEnabled(false); + } else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) + g_pHyprOpenGL->clear(Colors::BLACK); + else { + g_pHyprOpenGL->clear(Colors::BLACK); + CBox texbox = + CBox{pMonitor->vecTransformedSize / 2.F, g_pHyprOpenGL->m_pScreencopyDeniedTexture->m_vSize}.translate(-g_pHyprOpenGL->m_pScreencopyDeniedTexture->m_vSize / 2.F); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pScreencopyDeniedTexture, texbox, 1); + } g_pHyprOpenGL->m_RenderData.blockScreenShader = true; g_pHyprRenderer->endRender(); @@ -233,9 +244,10 @@ void CScreencopyFrame::copyDmabuf(std::function callback) { } bool CScreencopyFrame::copyShm() { - auto TEXTURE = makeShared(pMonitor->output->state->state().buffer); + const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(resource->client(), PERMISSION_TYPE_SCREENCOPY); + auto TEXTURE = makeShared(pMonitor->output->state->state().buffer); - auto shm = buffer->shm(); + auto shm = buffer->shm(); auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); // no need for end, cuz it's shm CRegion fakeDamage = {0, 0, INT16_MAX, INT16_MAX}; @@ -250,12 +262,21 @@ bool CScreencopyFrame::copyShm() { return false; } - CBox monbox = CBox{0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}.translate({-box.x, -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 (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) { + CBox monbox = CBox{0, 0, pMonitor->vecTransformedSize.x, pMonitor->vecTransformedSize.y}.translate({-box.x, -box.y}); + g_pHyprOpenGL->setMonitorTransformEnabled(true); + g_pHyprOpenGL->setRenderModifEnabled(false); + g_pHyprOpenGL->renderTexture(TEXTURE, monbox, 1); + g_pHyprOpenGL->setRenderModifEnabled(true); + g_pHyprOpenGL->setMonitorTransformEnabled(false); + } else if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) + g_pHyprOpenGL->clear(Colors::BLACK); + else { + g_pHyprOpenGL->clear(Colors::BLACK); + CBox texbox = + CBox{pMonitor->vecTransformedSize / 2.F, g_pHyprOpenGL->m_pScreencopyDeniedTexture->m_vSize}.translate(-g_pHyprOpenGL->m_pScreencopyDeniedTexture->m_vSize / 2.F); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pScreencopyDeniedTexture, texbox, 1); + } #ifndef GLES2 glBindFramebuffer(GL_READ_FRAMEBUFFER, fb.getFBID()); @@ -430,6 +451,14 @@ void CScreencopyProtocol::onOutputCommit(PHLMONITOR pMonitor) { if (!f) continue; + // check permissions + const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(f->resource->client(), PERMISSION_TYPE_SCREENCOPY); + + if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) + continue; // pending an answer, don't do anything yet. + + // otherwise share. If it's denied, it will be black. + if (!f->pMonitor || !f->buffer) { framesToRemove.emplace_back(f); continue; diff --git a/src/protocols/ToplevelExport.cpp b/src/protocols/ToplevelExport.cpp index 66e74164..8f18afbc 100644 --- a/src/protocols/ToplevelExport.cpp +++ b/src/protocols/ToplevelExport.cpp @@ -8,6 +8,7 @@ #include "../helpers/Format.hpp" #include "../managers/EventManager.hpp" #include "../managers/input/InputManager.hpp" +#include "../managers/permissions/DynamicPermissionManager.hpp" #include "../render/Renderer.hpp" #include @@ -231,7 +232,8 @@ void CToplevelExportFrame::share() { } bool CToplevelExportFrame::copyShm(timespec* now) { - auto shm = buffer->shm(); + const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(resource->client(), PERMISSION_TYPE_SCREENCOPY); + auto shm = buffer->shm(); auto [pixelData, fmt, bufLen] = buffer->beginDataPtr(0); // no need for end, cuz it's shm // render the client @@ -256,12 +258,18 @@ bool CToplevelExportFrame::copyShm(timespec* now) { g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 1.0)); // render client at 0,0 - g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible - g_pHyprRenderer->renderWindow(pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); - g_pHyprRenderer->m_bBlockSurfaceFeedback = false; - - if (overlayCursor) - g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition->value()); + if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) { + g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible + g_pHyprRenderer->renderWindow(pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); + g_pHyprRenderer->m_bBlockSurfaceFeedback = false; + + if (overlayCursor) + g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition->value()); + } else if (PERM == PERMISSION_RULE_ALLOW_MODE_DENY) { + CBox texbox = + CBox{PMONITOR->vecTransformedSize / 2.F, g_pHyprOpenGL->m_pScreencopyDeniedTexture->m_vSize}.translate(-g_pHyprOpenGL->m_pScreencopyDeniedTexture->m_vSize / 2.F); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pScreencopyDeniedTexture, texbox, 1); + } const auto PFORMAT = NFormatUtils::getPixelFormatFromDRM(shm.format); if (!PFORMAT) { @@ -322,6 +330,7 @@ bool CToplevelExportFrame::copyShm(timespec* now) { } bool CToplevelExportFrame::copyDmabuf(timespec* now) { + const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(resource->client(), PERMISSION_TYPE_SCREENCOPY); const auto PMONITOR = pWindow->m_pMonitor.lock(); CRegion fakeDamage{0, 0, INT16_MAX, INT16_MAX}; @@ -337,13 +346,18 @@ bool CToplevelExportFrame::copyDmabuf(timespec* now) { return false; g_pHyprOpenGL->clear(CHyprColor(0, 0, 0, 1.0)); - - g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible - g_pHyprRenderer->renderWindow(pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); - g_pHyprRenderer->m_bBlockSurfaceFeedback = false; - - if (overlayCursor) - g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition->value()); + if (PERM == PERMISSION_RULE_ALLOW_MODE_ALLOW) { + g_pHyprRenderer->m_bBlockSurfaceFeedback = g_pHyprRenderer->shouldRenderWindow(pWindow); // block the feedback to avoid spamming the surface if it's visible + g_pHyprRenderer->renderWindow(pWindow, PMONITOR, now, false, RENDER_PASS_ALL, true, true); + g_pHyprRenderer->m_bBlockSurfaceFeedback = false; + + if (overlayCursor) + g_pPointerManager->renderSoftwareCursorsFor(PMONITOR->self.lock(), now, fakeDamage, g_pInputManager->getMouseCoordsInternal() - pWindow->m_vRealPosition->value()); + } else if (PERM == PERMISSION_RULE_ALLOW_MODE_DENY) { + CBox texbox = + CBox{PMONITOR->vecTransformedSize / 2.F, g_pHyprOpenGL->m_pScreencopyDeniedTexture->m_vSize}.translate(-g_pHyprOpenGL->m_pScreencopyDeniedTexture->m_vSize / 2.F); + g_pHyprOpenGL->renderTexture(g_pHyprOpenGL->m_pScreencopyDeniedTexture, texbox, 1); + } g_pHyprOpenGL->m_RenderData.blockScreenShader = true; g_pHyprRenderer->endRender(); @@ -417,6 +431,12 @@ void CToplevelExportProtocol::onOutputCommit(PHLMONITOR pMonitor) { if (!f) continue; + // check permissions + const auto PERM = g_pDynamicPermissionManager->clientPermissionMode(f->resource->client(), PERMISSION_TYPE_SCREENCOPY); + + if (PERM == PERMISSION_RULE_ALLOW_MODE_PENDING) + continue; // pending an answer, don't do anything yet. + if (!validMapped(f->pWindow)) { framesToRemove.emplace_back(f); continue; -- cgit v1.2.3