Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

core: improve dynamic output handling #386

Merged
merged 9 commits into from
Jul 1, 2024
4 changes: 1 addition & 3 deletions src/core/Output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ static void handleDone(void* data, wl_output* output) {
const auto POUTPUT = (COutput*)data;
Debug::log(LOG, "output {} done", POUTPUT->name);
if (g_pHyprlock->m_bLocked && !POUTPUT->sessionLockSurface) {
// if we are already locked, create a surface dynamically after a small timeout
// we also need to request a dma frame for screenshots
// if we are already locked, create a surface dynamically
Debug::log(LOG, "Creating a surface dynamically for output as we are already locked");
POUTPUT->sessionLockSurface = std::make_unique<CSessionLockSurface>(POUTPUT);
g_pRenderer->asyncResourceGatherer->recheckDMAFramesFor(POUTPUT);
}
}

Expand Down
47 changes: 25 additions & 22 deletions src/core/hyprlock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,11 @@ void CHyprlock::onGlobal(void* data, struct wl_registry* registry, uint32_t name

void CHyprlock::onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name) {
Debug::log(LOG, " | removed iface {}", name);
std::erase_if(m_vOutputs, [name](const auto& other) { return other->name == name; });
auto outputIt = std::find_if(m_vOutputs.begin(), m_vOutputs.end(), [name](const auto& other) { return other->name == name; });
if (outputIt != m_vOutputs.end()) {
g_pRenderer->removeWidgetsFor(outputIt->get()->sessionLockSurface.get());
m_vOutputs.erase(outputIt);
}
}

// end wl_registry
Expand Down Expand Up @@ -570,9 +574,7 @@ void CHyprlock::unlock() {
m_tFadeEnds = std::chrono::system_clock::now() + std::chrono::milliseconds(500);
m_bFadeStarted = true;

for (auto& o : m_vOutputs) {
o->sessionLockSurface->render();
}
renderAllOutputs();
}

// wl_seat
Expand Down Expand Up @@ -758,9 +760,7 @@ static const ext_session_lock_v1_listener sessionLockListener = {
static void displayFailTextTimerCallback(std::shared_ptr<CTimer> self, void* data) {
g_pAuth->m_bDisplayFailText = false;

for (auto& o : g_pHyprlock->m_vOutputs) {
o->sessionLockSurface->render();
}
g_pHyprlock->renderAllOutputs();
}

void CHyprlock::onPasswordCheckTimer() {
Expand All @@ -779,9 +779,7 @@ void CHyprlock::onPasswordCheckTimer() {

g_pAuth->start();

for (auto& o : m_vOutputs) {
o->sessionLockSurface->render();
}
renderAllOutputs();
}
}

Expand All @@ -790,9 +788,8 @@ void CHyprlock::clearPasswordBuffer() {
return;

m_sPasswordState.passBuffer = "";
for (auto& o : m_vOutputs) {
o->sessionLockSurface->render();
}

renderAllOutputs();
}

void CHyprlock::renderOutput(const std::string& stringPort) {
Expand All @@ -803,9 +800,21 @@ void CHyprlock::renderOutput(const std::string& stringPort) {

const auto PMONITOR = MON->get();

if (!PMONITOR->sessionLockSurface)
return;

PMONITOR->sessionLockSurface->render();
}

void CHyprlock::renderAllOutputs() {
for (auto& o : m_vOutputs) {
if (!o->sessionLockSurface)
continue;

o->sessionLockSurface->render();
}
}

void CHyprlock::startKeyRepeat(xkb_keysym_t sym) {
if (m_pKeyRepeatTimer) {
m_pKeyRepeatTimer->cancel();
Expand All @@ -830,9 +839,7 @@ void CHyprlock::repeatKey(xkb_keysym_t sym) {
m_pKeyRepeatTimer = addTimer(
std::chrono::milliseconds(m_iKeebRepeatRate), [sym](std::shared_ptr<CTimer> self, void* data) { g_pHyprlock->repeatKey(sym); }, nullptr);

for (auto& o : m_vOutputs) {
o->sessionLockSurface->render();
}
renderAllOutputs();
}

void CHyprlock::onKey(uint32_t key, bool down) {
Expand Down Expand Up @@ -863,9 +870,7 @@ void CHyprlock::onKey(uint32_t key, bool down) {
}

if (g_pAuth->checkWaiting()) {
for (auto& o : m_vOutputs) {
o->sessionLockSurface->render();
}
renderAllOutputs();
return;
}

Expand All @@ -881,9 +886,7 @@ void CHyprlock::onKey(uint32_t key, bool down) {
startKeyRepeat(SYM);
}

for (auto& o : m_vOutputs) {
o->sessionLockSurface->render();
}
renderAllOutputs();
}

void CHyprlock::handleKeySym(xkb_keysym_t sym) {
Expand Down
1 change: 1 addition & 0 deletions src/core/hyprlock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class CHyprlock {
std::optional<std::string> passwordLastFailReason();

void renderOutput(const std::string& stringPort);
void renderAllOutputs();

size_t getPasswordBufferLen();
size_t getPasswordBufferDisplayLen();
Expand Down
26 changes: 1 addition & 25 deletions src/renderer/AsyncResourceGatherer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,30 +56,6 @@ CAsyncResourceGatherer::CAsyncResourceGatherer() {
}
}

void CAsyncResourceGatherer::recheckDMAFramesFor(COutput* output) {
const auto CWIDGETS = g_pConfigManager->getWidgetConfigs();

bool shouldMake = false;

for (auto& c : CWIDGETS) {
if (c.type != "background")
continue;

if (std::string{std::any_cast<Hyprlang::STRING>(c.values.at("path"))} != "screenshot")
continue;

if (c.monitor.empty() || c.monitor == output->stringPort || output->stringDesc.starts_with(c.monitor)) {
shouldMake = true;
break;
}
}

if (!shouldMake)
return;

dmas.emplace_back(std::make_unique<CDMAFrame>(output));
}

SPreloadedAsset* CAsyncResourceGatherer::getAssetByID(const std::string& id) {
for (auto& a : assets) {
if (a.first == id)
Expand All @@ -94,7 +70,7 @@ SPreloadedAsset* CAsyncResourceGatherer::getAssetByID(const std::string& id) {
};

for (auto& dma : dmas) {
if (id == "dma:" + dma->name)
if (id == dma->resourceID)
return dma->asset.ready ? &dma->asset : nullptr;
}

Expand Down
1 change: 0 additions & 1 deletion src/renderer/AsyncResourceGatherer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ class CAsyncResourceGatherer {
void unloadAsset(SPreloadedAsset* asset);
void notify();
void await();
void recheckDMAFramesFor(COutput* output);

private:
std::thread asyncLoopThread;
Expand Down
11 changes: 7 additions & 4 deletions src/renderer/DMAFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,12 @@ static const zwlr_screencopy_frame_v1_listener wlrFrameListener = {
.buffer_done = wlrOnBufferDone,
};

CDMAFrame::CDMAFrame(COutput* output_) : output(output_) {
std::string CDMAFrame::getResourceId(COutput* output) {
return std::format("dma:{}-{}x{}", output->stringPort, output->size.x, output->size.y);
}

CDMAFrame::CDMAFrame(COutput* output_) {
resourceID = getResourceId(output_);

if (!glEGLImageTargetTexture2DOES) {
glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
Expand All @@ -100,13 +105,11 @@ CDMAFrame::CDMAFrame(COutput* output_) : output(output_) {
eglQueryDmaBufModifiersEXT = (PFNEGLQUERYDMABUFMODIFIERSEXTPROC)eglGetProcAddress("eglQueryDmaBufModifiersEXT");

// firstly, plant a listener for the frame
frameCb = zwlr_screencopy_manager_v1_capture_output(g_pHyprlock->getScreencopy(), false, output->output);
frameCb = zwlr_screencopy_manager_v1_capture_output(g_pHyprlock->getScreencopy(), false, output_->output);

scdata.frame = this;

zwlr_screencopy_frame_v1_add_listener(frameCb, &wlrFrameListener, &scdata);

name = output->stringPort;
}

CDMAFrame::~CDMAFrame() {
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/DMAFrame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ struct SScreencopyData {

class CDMAFrame {
public:
static std::string getResourceId(COutput* output);

CDMAFrame(COutput* mon);
~CDMAFrame();

Expand All @@ -27,7 +29,7 @@ class CDMAFrame {

wl_buffer* wlBuffer = nullptr;

std::string name;
std::string resourceID;

SPreloadedAsset asset;

Expand All @@ -42,7 +44,5 @@ class CDMAFrame {
zwlr_screencopy_frame_v1* frameCb = nullptr;
SScreencopyData scdata;

COutput* output = nullptr;

EGLImage image = nullptr;
};
17 changes: 14 additions & 3 deletions src/renderer/Renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "../helpers/Color.hpp"
#include "../core/Output.hpp"
#include "../core/hyprlock.hpp"
#include "../renderer/DMAFrame.hpp"
#include "mtx.hpp"

#include <GLES3/gl32.h>
Expand Down Expand Up @@ -320,9 +321,15 @@ std::vector<std::unique_ptr<IWidget>>* CRenderer::getOrCreateWidgetsFor(const CS
const std::string PATH = std::any_cast<Hyprlang::STRING>(c.values.at("path"));

std::string resourceID = "";
if (PATH == "screenshot")
resourceID = "dma:" + surf->output->stringPort;
else if (!PATH.empty())
if (PATH == "screenshot") {
resourceID = CDMAFrame::getResourceId(surf->output);
// When the initial gather of the asyncResourceGatherer is completed (ready), all DMAFrames are available.
// Dynamic ones are tricky, because a screencopy would copy hyprlock itself.
if (asyncResourceGatherer->ready) {
if (!asyncResourceGatherer->getAssetByID(resourceID))
resourceID = ""; // Fallback to solid color (background:color)
}
} else if (!PATH.empty())
resourceID = "background:" + PATH;

widgets[surf].emplace_back(std::make_unique<CBackground>(surf->size, surf->output, resourceID, c.values, PATH == "screenshot"));
Expand Down Expand Up @@ -512,3 +519,7 @@ void CRenderer::popFb() {
boundFBs.pop_back();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundFBs.empty() ? 0 : boundFBs.back());
}

void CRenderer::removeWidgetsFor(const CSessionLockSurface* surf) {
widgets.erase(surf);
}
2 changes: 2 additions & 0 deletions src/renderer/Renderer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class CRenderer {
void pushFb(GLint fb);
void popFb();

void removeWidgetsFor(const CSessionLockSurface* surf);

private:
widgetMap_t widgets;

Expand Down
Loading