From 8455fc8ca6432a72313cd285488333ba5977fbe5 Mon Sep 17 00:00:00 2001 From: ojafuenf <50103673+ojafuenf@users.noreply.github.com> Date: Wed, 4 Jun 2025 08:14:11 +0200 Subject: [PATCH 1/8] core: interpret touch as click (#788) --- src/core/Seat.cpp | 11 ++++++++++- src/core/Seat.hpp | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/core/Seat.cpp b/src/core/Seat.cpp index 408e64d..a3f811c 100644 --- a/src/core/Seat.cpp +++ b/src/core/Seat.cpp @@ -5,6 +5,7 @@ #include #include #include +#include CSeatManager::~CSeatManager() { if (m_pXKBState) @@ -76,7 +77,15 @@ void CSeatManager::registerSeat(SP seat) { g_pHyprlock->onClick(button, state == WL_POINTER_BUTTON_STATE_PRESSED, g_pHyprlock->m_vMouseLocation); }); } - + if (caps & WL_SEAT_CAPABILITY_TOUCH) { + m_pTouch = makeShared(r->sendGetTouch()); + m_pTouch->setDown([](CCWlTouch* r, uint32_t serial, uint32_t time, wl_proxy* surface, int32_t id, wl_fixed_t x, wl_fixed_t y) { + g_pHyprlock->onClick(BTN_LEFT, true, {wl_fixed_to_double(x), wl_fixed_to_double(y)}); + }); + m_pTouch->setUp([](CCWlTouch* r, uint32_t serial, uint32_t time, int32_t id) { + g_pHyprlock->onClick(BTN_LEFT, false, {0, 0}); + }); + }; if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { m_pKeeb = makeShared(r->sendGetKeyboard()); diff --git a/src/core/Seat.hpp b/src/core/Seat.hpp index bf6a7a0..804e062 100644 --- a/src/core/Seat.hpp +++ b/src/core/Seat.hpp @@ -17,6 +17,7 @@ class CSeatManager { SP m_pKeeb; SP m_pPointer; + SP m_pTouch; UP m_pCursorShape; From 1303bb4b7edde4632130dff4acde5e3b6f92f347 Mon Sep 17 00:00:00 2001 From: TioBill Date: Thu, 5 Jun 2025 17:22:14 -0300 Subject: [PATCH 2/8] cmake: Add check for libpam using pkg_check_modules (#795) --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9319294..2613d67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,7 @@ pkg_check_modules( pangocairo libdrm gbm + pam hyprutils>=0.5.0 sdbus-c++>=2.0.0 hyprgraphics) From f9d8dfab7ae0aec625e7814e16f626fabec3641b Mon Sep 17 00:00:00 2001 From: Friday Date: Thu, 5 Jun 2025 22:21:01 +0100 Subject: [PATCH 3/8] nix: use gcc15 also updated dependencies --- flake.lock | 30 +++++++++++++++--------------- nix/overlays.nix | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/flake.lock b/flake.lock index d8ad58a..507f5d2 100644 --- a/flake.lock +++ b/flake.lock @@ -13,11 +13,11 @@ ] }, "locked": { - "lastModified": 1743953322, - "narHash": "sha256-prQ5JKopXtzCMX2eT3dXbaVvGmzjMRE2bXStQDdazpM=", + "lastModified": 1749145600, + "narHash": "sha256-v2kY5RDk9oyo1x9m8u83GdklC96xlJ7ka1rrvZoYL78=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "9d7f2687c84c729afbc3b13f7937655570f2978d", + "rev": "80b754e38e836777ad3a9d5d1ffc3491b0332471", "type": "github" }, "original": { @@ -39,11 +39,11 @@ ] }, "locked": { - "lastModified": 1744468525, - "narHash": "sha256-9HySx+EtsbbKlZDlY+naqqOV679VdxP6x6fP3wxDXJk=", + "lastModified": 1749145882, + "narHash": "sha256-qr0KXeczF8Sma3Ae7+dR2NHhvG7YeLBJv19W4oMu6ZE=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "f1000c54d266e6e4e9d646df0774fac5b8a652df", + "rev": "1bfb84f54d50c7ae6558c794d3cfd5f6a7e6e676", "type": "github" }, "original": { @@ -62,11 +62,11 @@ ] }, "locked": { - "lastModified": 1743950287, - "narHash": "sha256-/6IAEWyb8gC/NKZElxiHChkouiUOrVYNq9YqG0Pzm4Y=", + "lastModified": 1749135356, + "narHash": "sha256-Q8mAKMDsFbCEuq7zoSlcTuxgbIBVhfIYpX0RjE32PS0=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "f2dc70e448b994cef627a157ee340135bd68fbc6", + "rev": "e36db00dfb3a3d3fdcc4069cb292ff60d2699ccb", "type": "github" }, "original": { @@ -85,11 +85,11 @@ ] }, "locked": { - "lastModified": 1739870480, - "narHash": "sha256-SiDN5BGxa/1hAsqhgJsS03C3t2QrLgBT8u+ENJ0Qzwc=", + "lastModified": 1749145760, + "narHash": "sha256-IHaGWpGrv7seFWdw/1A+wHtTsPlOGIKMrk1TUIYJEFI=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "206367a08dc5ac4ba7ad31bdca391d098082e64b", + "rev": "817918315ea016cc2d94004bfb3223b5fd9dfcc6", "type": "github" }, "original": { @@ -100,11 +100,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1744463964, - "narHash": "sha256-LWqduOgLHCFxiTNYi3Uj5Lgz0SR+Xhw3kr/3Xd0GPTM=", + "lastModified": 1748929857, + "narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "2631b0b7abcea6e640ce31cd78ea58910d31e650", + "rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4", "type": "github" }, "original": { diff --git a/nix/overlays.nix b/nix/overlays.nix index afedab6..e386942 100644 --- a/nix/overlays.nix +++ b/nix/overlays.nix @@ -21,7 +21,7 @@ in { inputs.self.overlays.sdbuscpp (final: prev: { hyprlock = prev.callPackage ./default.nix { - stdenv = prev.gcc14Stdenv; + stdenv = prev.gcc15Stdenv; version = version + "+date=" + (mkDate (inputs.self.lastModifiedDate or "19700101")) + "_" + (inputs.self.shortRev or "dirty"); inherit (final) hyprlang; shortRev = self.sourceInfo.shortRev or "dirty"; From e67036e8ccc02af62aa8e885ad7620aa1c2291c7 Mon Sep 17 00:00:00 2001 From: Mihai Fufezan Date: Fri, 20 Jun 2025 01:25:12 +0300 Subject: [PATCH 4/8] CI/Nix: add cache-nix-action Use nixbuild/nix-quick-install-action which pairs well with nix-community/cache-nix-action. Should help with build times by reducing the number of packages needing to be re-downloaded on each run. Parameters are taken from https://github.com/nix-community/cache-nix-action and may be tweaked later. --- .github/workflows/nix.yml | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 4d99cee..9409146 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -7,7 +7,35 @@ jobs: steps: - uses: actions/checkout@v3 - - uses: DeterminateSystems/nix-installer-action@main + - name: Install Nix + uses: nixbuild/nix-quick-install-action@v31 + with: + nix_conf: | + keep-env-derivations = true + keep-outputs = true + + - name: Restore and save Nix store + uses: nix-community/cache-nix-action@v6 + with: + # restore and save a cache using this key + primary-key: nix-${{ runner.os }}-${{ hashFiles('**/*.nix', '**/flake.lock') }} + # if there's no cache hit, restore a cache by this prefix + restore-prefixes-first-match: nix-${{ runner.os }}- + # collect garbage until the Nix store size (in bytes) is at most this number + # before trying to save a new cache + # 1G = 1073741824 + gc-max-store-size-linux: 1G + # do purge caches + purge: true + # purge all versions of the cache + purge-prefixes: nix-${{ runner.os }}- + # created more than this number of seconds ago + purge-created: 0 + # or, last accessed more than this number of seconds ago + # relative to the start of the `Post Restore and save Nix store` phase + purge-last-accessed: 0 + # except any version with the key that is the same as the `primary-key` + purge-primary-key: never # not needed (yet) # - uses: cachix/cachix-action@v12 From a9638986c31ab74fd95e83057f7cdd5187747ec7 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sun, 22 Jun 2025 09:24:39 +0200 Subject: [PATCH 5/8] core: use a screenshot for fade in/out (#726) --- src/core/hyprlock.cpp | 48 ++++- src/core/hyprlock.hpp | 2 - src/renderer/AsyncResourceGatherer.cpp | 78 ++++--- src/renderer/AsyncResourceGatherer.hpp | 6 +- src/renderer/Framebuffer.cpp | 6 +- src/renderer/Framebuffer.hpp | 22 +- src/renderer/Renderer.cpp | 7 +- src/renderer/Renderer.hpp | 2 +- src/renderer/Screencopy.cpp | 2 +- src/renderer/Screencopy.hpp | 3 +- src/renderer/widgets/Background.cpp | 276 ++++++++++++------------- src/renderer/widgets/Background.hpp | 25 +-- src/renderer/widgets/Image.cpp | 4 +- 13 files changed, 252 insertions(+), 229 deletions(-) diff --git a/src/core/hyprlock.cpp b/src/core/hyprlock.cpp index b330262..6cbec21 100644 --- a/src/core/hyprlock.cpp +++ b/src/core/hyprlock.cpp @@ -6,6 +6,7 @@ #include "../auth/Auth.hpp" #include "../auth/Fingerprint.hpp" #include "Egl.hpp" +#include #include #include #include @@ -313,18 +314,52 @@ void CHyprlock::run() { Debug::log(LOG, "Running on {}", m_sCurrentDesktop); - // Hyprland violates the protocol a bit to allow for this. - if (m_sCurrentDesktop != "Hyprland") { + if (!g_pHyprlock->m_bImmediateRender) { + // Gather background resources and screencopy frames before locking the screen. + // We need to do this because as soon as we lock the screen, workspaces frames can no longer be captured. It either won't work at all, or we will capture hyprlock itself. + // Bypass with --immediate-render (can cause the background first rendering a solid color and missing or inaccurate screencopy frames) + const auto MAXDELAYMS = 2000; // 2 Seconds + const auto STARTGATHERTP = std::chrono::system_clock::now(); + + int fdcount = 1; + pollfd pollfds[2]; + pollfds[0] = { + .fd = wl_display_get_fd(m_sWaylandState.display), + .events = POLLIN, + }; + + if (g_pRenderer->asyncResourceGatherer->gatheredEventfd.isValid()) { + pollfds[1] = { + .fd = g_pRenderer->asyncResourceGatherer->gatheredEventfd.get(), + .events = POLLIN, + }; + + fdcount++; + } + while (!g_pRenderer->asyncResourceGatherer->gathered) { wl_display_flush(m_sWaylandState.display); if (wl_display_prepare_read(m_sWaylandState.display) == 0) { + if (poll(pollfds, fdcount, /* 100ms timeout */ 100) < 0) { + RASSERT(errno == EINTR, "[core] Polling fds failed with {}", errno); + wl_display_cancel_read(m_sWaylandState.display); + continue; + } wl_display_read_events(m_sWaylandState.display); wl_display_dispatch_pending(m_sWaylandState.display); } else { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); wl_display_dispatch(m_sWaylandState.display); } - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + + if (std::chrono::duration_cast(std::chrono::system_clock::now() - STARTGATHERTP).count() > MAXDELAYMS) { + Debug::log(WARN, "Gathering resources timed out after {} milliseconds. Backgrounds may be delayed and render `background:color` at first.", MAXDELAYMS); + break; + } } + + Debug::log(LOG, "Resources gathered after {} milliseconds", + std::chrono::duration_cast(std::chrono::system_clock::now() - STARTGATHERTP).count()); } // Failed to lock the session @@ -499,16 +534,13 @@ void CHyprlock::unlock() { return; } - const bool IMMEDIATE = m_sCurrentDesktop != "Hyprland"; - - g_pRenderer->startFadeOut(true, IMMEDIATE); - m_bUnlockedCalled = true; + g_pRenderer->startFadeOut(true); renderAllOutputs(); } bool CHyprlock::isUnlocked() { - return m_bUnlockedCalled || m_bTerminate; + return !m_bLocked; } void CHyprlock::clearPasswordBuffer() { diff --git a/src/core/hyprlock.hpp b/src/core/hyprlock.hpp index 0d4f1cf..fd2f989 100644 --- a/src/core/hyprlock.hpp +++ b/src/core/hyprlock.hpp @@ -158,8 +158,6 @@ class CHyprlock { bool timerEvent = false; } m_sLoopState; - bool m_bUnlockedCalled = false; - std::vector> m_vTimers; std::vector m_vPressedKeys; diff --git a/src/renderer/AsyncResourceGatherer.cpp b/src/renderer/AsyncResourceGatherer.cpp index b1a52de..f9c0864 100644 --- a/src/renderer/AsyncResourceGatherer.cpp +++ b/src/renderer/AsyncResourceGatherer.cpp @@ -1,16 +1,19 @@ #include "AsyncResourceGatherer.hpp" #include "../config/ConfigManager.hpp" #include "../core/Egl.hpp" -#include -#include -#include -#include #include "../core/hyprlock.hpp" +#include "../helpers/Color.hpp" +#include "../helpers/Log.hpp" #include "../helpers/MiscFunctions.hpp" -#include "src/helpers/Color.hpp" -#include "src/helpers/Log.hpp" +#include +#include +#include +#include +#include #include +#include using namespace Hyprgraphics; +using namespace Hyprutils::OS; CAsyncResourceGatherer::CAsyncResourceGatherer() { if (g_pHyprlock->getScreencopy()) @@ -18,45 +21,39 @@ CAsyncResourceGatherer::CAsyncResourceGatherer() { initialGatherThread = std::thread([this]() { this->gather(); }); asyncLoopThread = std::thread([this]() { this->asyncAssetSpinLock(); }); + + gatheredEventfd = CFileDescriptor{eventfd(0, EFD_CLOEXEC)}; + if (!gatheredEventfd.isValid()) + Debug::log(ERR, "Failed to create eventfd: {}", strerror(errno)); } void CAsyncResourceGatherer::enqueueScreencopyFrames() { - // some things can't be done async :( - // gather background textures when needed + const auto FADEINCFG = g_pConfigManager->m_AnimationTree.getConfig("fadeIn"); + const auto FADEOUTCFG = g_pConfigManager->m_AnimationTree.getConfig("fadeOut"); + const auto BGSCREENSHOT = std::ranges::any_of(g_pConfigManager->getWidgetConfigs(), [](const auto& w) { // + return w.type == "background" && std::string{std::any_cast(w.values.at("path"))} == "screenshot"; + }); - const auto CWIDGETS = g_pConfigManager->getWidgetConfigs(); + // No screenshot background AND no fade in AND no fade out -> we don't need screencopy + if (!BGSCREENSHOT && (!FADEINCFG->pValues || !FADEINCFG->pValues->internalEnabled) && // + (!FADEOUTCFG->pValues || !FADEOUTCFG->pValues->internalEnabled)) + return; - std::vector mons; - - for (auto& c : CWIDGETS) { - if (c.type != "background") - continue; - - if (std::string{std::any_cast(c.values.at("path"))} != "screenshot") - continue; - - // mamma mia - if (c.monitor.empty()) { - mons.clear(); - for (auto& m : g_pHyprlock->m_vOutputs) { - mons.push_back(m->stringPort); - } - break; - } else - mons.push_back(c.monitor); - } - - for (auto& mon : mons) { - const auto MON = std::ranges::find_if(g_pHyprlock->m_vOutputs, [mon](const auto& other) { return other->stringPort == mon || other->stringDesc.starts_with(mon); }); - - if (MON == g_pHyprlock->m_vOutputs.end()) - continue; - - scframes.emplace_back(makeUnique(*MON)); + for (const auto& MON : g_pHyprlock->m_vOutputs) { + scframes.emplace_back(makeUnique(MON)); } } SPreloadedAsset* CAsyncResourceGatherer::getAssetByID(const std::string& id) { + if (id.contains(CScreencopyFrame::RESOURCEIDPREFIX)) { + for (auto& frame : scframes) { + if (id == frame->m_resourceID) + return frame->m_asset.ready ? &frame->m_asset : nullptr; + } + + return nullptr; + } + for (auto& a : assets) { if (a.first == id) return &a.second; @@ -69,16 +66,10 @@ SPreloadedAsset* CAsyncResourceGatherer::getAssetByID(const std::string& id) { } }; - for (auto& frame : scframes) { - if (id == frame->m_resourceID) - return frame->m_asset.ready ? &frame->m_asset : nullptr; - } - return nullptr; } static SP getCairoSurfaceFromImageFile(const std::filesystem::path& path) { - auto image = CImage(path); if (!image.success()) { Debug::log(ERR, "Image {} could not be loaded: {}", path.string(), image.getError()); @@ -131,6 +122,9 @@ void CAsyncResourceGatherer::gather() { } gathered = true; + // wake hyprlock from poll + if (gatheredEventfd.isValid()) + eventfd_write(gatheredEventfd.get(), 1); } bool CAsyncResourceGatherer::apply() { diff --git a/src/renderer/AsyncResourceGatherer.hpp b/src/renderer/AsyncResourceGatherer.hpp index 24aedd6..002f948 100644 --- a/src/renderer/AsyncResourceGatherer.hpp +++ b/src/renderer/AsyncResourceGatherer.hpp @@ -9,13 +9,15 @@ #include #include "Shared.hpp" #include +#include class CAsyncResourceGatherer { public: CAsyncResourceGatherer(); - std::atomic gathered = false; + std::atomic gathered = false; + Hyprutils::OS::CFileDescriptor gatheredEventfd; - std::atomic progress = 0; + std::atomic progress = 0; /* only call from ogl thread */ SPreloadedAsset* getAssetByID(const std::string& id); diff --git a/src/renderer/Framebuffer.cpp b/src/renderer/Framebuffer.cpp index 714e8db..306721a 100644 --- a/src/renderer/Framebuffer.cpp +++ b/src/renderer/Framebuffer.cpp @@ -1,6 +1,8 @@ #include "Framebuffer.hpp" #include "../helpers/Log.hpp" +#include #include +#include static uint32_t drmFormatToGL(uint32_t drm) { switch (drm) { @@ -97,7 +99,7 @@ void CFramebuffer::bind() const { glViewport(0, 0, m_vSize.x, m_vSize.y); } -void CFramebuffer::release() { +void CFramebuffer::destroyBuffer() { if (m_iFb != (uint32_t)-1 && m_iFb) glDeleteFramebuffers(1, &m_iFb); @@ -114,7 +116,7 @@ void CFramebuffer::release() { } CFramebuffer::~CFramebuffer() { - release(); + destroyBuffer(); } bool CFramebuffer::isAllocated() const { diff --git a/src/renderer/Framebuffer.hpp b/src/renderer/Framebuffer.hpp index d23ed50..136f643 100644 --- a/src/renderer/Framebuffer.hpp +++ b/src/renderer/Framebuffer.hpp @@ -8,17 +8,19 @@ class CFramebuffer { public: ~CFramebuffer(); - bool alloc(int w, int h, bool highres = false); - void addStencil(); - void bind() const; - void release(); - void reset(); - bool isAllocated() const; + bool alloc(int w, int h, bool highres = false); + void addStencil(); + void bind() const; + void destroyBuffer(); + bool isAllocated() const; - Vector2D m_vSize; + Vector2D m_vSize; - CTexture m_cTex; - GLuint m_iFb = -1; + CTexture m_cTex; + GLuint m_iFb = -1; - CTexture* m_pStencilTex = nullptr; + CTexture* m_pStencilTex = nullptr; + + CFramebuffer& operator=(CFramebuffer&&) = delete; + CFramebuffer& operator=(const CFramebuffer&) = delete; }; diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index b2b4217..103763d 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -613,11 +613,8 @@ void CRenderer::startFadeIn() { opacity->setCallbackOnEnd([this](auto) { opacity->setConfig(g_pConfigManager->m_AnimationTree.getConfig("fadeOut")); }, true); } -void CRenderer::startFadeOut(bool unlock, bool immediate) { - if (immediate) - opacity->setValueAndWarp(0.f); - else - *opacity = 0.f; +void CRenderer::startFadeOut(bool unlock) { + *opacity = 0.f; if (unlock) opacity->setCallbackOnEnd([](auto) { g_pHyprlock->releaseSessionLock(); }, true); diff --git a/src/renderer/Renderer.hpp b/src/renderer/Renderer.hpp index 91921f6..a638736 100644 --- a/src/renderer/Renderer.hpp +++ b/src/renderer/Renderer.hpp @@ -47,7 +47,7 @@ class CRenderer { void reconfigureWidgetsFor(OUTPUTID id); void startFadeIn(); - void startFadeOut(bool unlock = false, bool immediate = true); + void startFadeOut(bool unlock = false); std::vector>& getOrCreateWidgetsFor(const CSessionLockSurface& surf); private: diff --git a/src/renderer/Screencopy.cpp b/src/renderer/Screencopy.cpp index ef84c04..54375d0 100644 --- a/src/renderer/Screencopy.cpp +++ b/src/renderer/Screencopy.cpp @@ -24,7 +24,7 @@ static PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullpt // std::string CScreencopyFrame::getResourceId(SP pOutput) { - return std::format("screencopy:{}-{}x{}", pOutput->stringPort, pOutput->size.x, pOutput->size.y); + return RESOURCEIDPREFIX + std::format(":{}-{}x{}", pOutput->stringPort, pOutput->size.x, pOutput->size.y); } CScreencopyFrame::CScreencopyFrame(SP pOutput) : m_outputRef(pOutput) { diff --git a/src/renderer/Screencopy.hpp b/src/renderer/Screencopy.hpp index 7c0987b..c316f45 100644 --- a/src/renderer/Screencopy.hpp +++ b/src/renderer/Screencopy.hpp @@ -22,7 +22,8 @@ class ISCFrame { class CScreencopyFrame { public: - static std::string getResourceId(SP pOutput); + static std::string getResourceId(SP pOutput); + static constexpr const std::string RESOURCEIDPREFIX = "screencopy"; CScreencopyFrame(SP pOutput); ~CScreencopyFrame() = default; diff --git a/src/renderer/widgets/Background.cpp b/src/renderer/widgets/Background.cpp index 2971159..2299601 100644 --- a/src/renderer/widgets/Background.cpp +++ b/src/renderer/widgets/Background.cpp @@ -1,14 +1,23 @@ #include "Background.hpp" #include "../Renderer.hpp" +#include "../Framebuffer.hpp" +#include "../Shared.hpp" #include "../../core/hyprlock.hpp" #include "../../helpers/Log.hpp" #include "../../helpers/MiscFunctions.hpp" +#include "../../core/AnimationManager.hpp" +#include "../../config/ConfigManager.hpp" #include #include #include #include #include +CBackground::CBackground() { + blurredFB = makeUnique(); + pendingBlurredFB = makeUnique(); +} + CBackground::~CBackground() { reset(); } @@ -32,7 +41,6 @@ void CBackground::configure(const std::unordered_map& pro path = std::any_cast(props.at("path")); reloadCommand = std::any_cast(props.at("reload_cmd")); reloadTime = std::any_cast(props.at("reload_time")); - crossFadeTime = std::any_cast(props.at("crossfade_time")); } catch (const std::bad_any_cast& e) { RASSERT(false, "Failed to construct CBackground: {}", e.what()); // @@ -42,12 +50,15 @@ void CBackground::configure(const std::unordered_map& pro isScreenshot = path == "screenshot"; - viewport = pOutput->getViewport(); - outputPort = pOutput->stringPort; - transform = isScreenshot ? wlTransformToHyprutils(invertTransform(pOutput->transform)) : HYPRUTILS_TRANSFORM_NORMAL; + viewport = pOutput->getViewport(); + outputPort = pOutput->stringPort; + transform = isScreenshot ? wlTransformToHyprutils(invertTransform(pOutput->transform)) : HYPRUTILS_TRANSFORM_NORMAL; + scResourceID = CScreencopyFrame::getResourceId(pOutput); + + g_pAnimationManager->createAnimation(0.f, crossFadeProgress, g_pConfigManager->m_AnimationTree.getConfig("fadeIn")); if (isScreenshot) { - resourceID = CScreencopyFrame::getResourceId(pOutput); + resourceID = scResourceID; // 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 (g_pRenderer->asyncResourceGatherer->gathered) { @@ -78,13 +89,8 @@ void CBackground::reset() { reloadTimer.reset(); } - if (fade) { - if (fade->crossFadeTimer) { - fade->crossFadeTimer->cancel(); - fade->crossFadeTimer.reset(); - } - fade.reset(); - } + blurredFB->destroyBuffer(); + pendingBlurredFB->destroyBuffer(); } void CBackground::renderRect(CHyprColor color) { @@ -99,98 +105,26 @@ static void onReloadTimer(WP ref) { } } -static void onCrossFadeTimer(WP ref) { - if (auto PBG = ref.lock(); PBG) - PBG->onCrossFadeTimerUpdate(); -} - static void onAssetCallback(WP ref) { if (auto PBG = ref.lock(); PBG) - PBG->startCrossFadeOrUpdateRender(); + PBG->startCrossFade(); } -bool CBackground::draw(const SRenderData& data) { +void CBackground::renderBlur(const CTexture& tex, CFramebuffer& fb) { + if (firstRender) + firstRender = false; - if (resourceID.empty()) { - CHyprColor col = color; - col.a *= data.opacity; - renderRect(col); - return data.opacity < 1.0; + // make it brah + Vector2D size = asset->texture.m_vSize; + if (transform % 2 == 1 && isScreenshot) { + size.x = asset->texture.m_vSize.y; + size.y = asset->texture.m_vSize.x; } - if (!asset) - asset = g_pRenderer->asyncResourceGatherer->getAssetByID(resourceID); + CBox texbox = {{}, size}; - if (!asset) { - CHyprColor col = color; - col.a *= data.opacity; - renderRect(col); - return true; - } - - if (asset->texture.m_iType == TEXTURE_INVALID) { - g_pRenderer->asyncResourceGatherer->unloadAsset(asset); - resourceID = ""; - return true; - } - - if (fade || ((blurPasses > 0 || isScreenshot) && (!blurredFB.isAllocated() || firstRender))) { - - if (firstRender) - firstRender = false; - - // make it brah - Vector2D size = asset->texture.m_vSize; - if (transform % 2 == 1 && isScreenshot) { - size.x = asset->texture.m_vSize.y; - size.y = asset->texture.m_vSize.x; - } - - CBox texbox = {{}, size}; - - float scaleX = viewport.x / size.x; - float scaleY = viewport.y / size.y; - - texbox.w *= std::max(scaleX, scaleY); - texbox.h *= std::max(scaleX, scaleY); - - if (scaleX > scaleY) - texbox.y = -(texbox.h - viewport.y) / 2.f; - else - texbox.x = -(texbox.w - viewport.x) / 2.f; - texbox.round(); - - if (!blurredFB.isAllocated()) - blurredFB.alloc(viewport.x, viewport.y); // TODO 10 bit - - blurredFB.bind(); - - if (fade) - g_pRenderer->renderTextureMix(texbox, asset->texture, pendingAsset->texture, 1.0, - std::chrono::duration_cast(std::chrono::system_clock::now() - fade->start).count() / (1000 * crossFadeTime), 0, - transform); - else - g_pRenderer->renderTexture(texbox, asset->texture, 1.0, 0, transform); - - if (blurPasses > 0) - g_pRenderer->blurFB(blurredFB, - CRenderer::SBlurParams{.size = blurSize, - .passes = blurPasses, - .noise = noise, - .contrast = contrast, - .brightness = brightness, - .vibrancy = vibrancy, - .vibrancy_darkness = vibrancy_darkness}); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - } - - CTexture* tex = blurredFB.isAllocated() ? &blurredFB.m_cTex : &asset->texture; - - CBox texbox = {{}, tex->m_vSize}; - - Vector2D size = tex->m_vSize; - float scaleX = viewport.x / tex->m_vSize.x; - float scaleY = viewport.y / tex->m_vSize.y; + float scaleX = viewport.x / size.x; + float scaleY = viewport.y / size.y; texbox.w *= std::max(scaleX, scaleY); texbox.h *= std::max(scaleX, scaleY); @@ -200,9 +134,94 @@ bool CBackground::draw(const SRenderData& data) { else texbox.x = -(texbox.w - viewport.x) / 2.f; texbox.round(); - g_pRenderer->renderTexture(texbox, *tex, data.opacity, 0, HYPRUTILS_TRANSFORM_FLIPPED_180); - return fade || data.opacity < 1.0; // actively render during fading + if (!fb.isAllocated()) + fb.alloc(viewport.x, viewport.y); // TODO 10 bit + + fb.bind(); + + g_pRenderer->renderTexture(texbox, tex, 1.0, 0, transform); + + if (blurPasses > 0) + g_pRenderer->blurFB(fb, + CRenderer::SBlurParams{.size = blurSize, + .passes = blurPasses, + .noise = noise, + .contrast = contrast, + .brightness = brightness, + .vibrancy = vibrancy, + .vibrancy_darkness = vibrancy_darkness}); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); +} + +static CBox getScaledBoxForTexture(const CTexture& tex, const Vector2D& viewport) { + CBox texbox = {{}, tex.m_vSize}; + + Vector2D size = tex.m_vSize; + float scaleX = viewport.x / tex.m_vSize.x; + float scaleY = viewport.y / tex.m_vSize.y; + + texbox.w *= std::max(scaleX, scaleY); + texbox.h *= std::max(scaleX, scaleY); + + if (scaleX > scaleY) + texbox.y = -(texbox.h - viewport.y) / 2.f; + else + texbox.x = -(texbox.w - viewport.x) / 2.f; + texbox.round(); + + return texbox; +} + +bool CBackground::draw(const SRenderData& data) { + if (!asset && !resourceID.empty()) + asset = g_pRenderer->asyncResourceGatherer->getAssetByID(resourceID); + + // path=screenshot -> scAsset = asset + if (!scAsset) + scAsset = (asset && isScreenshot) ? asset : g_pRenderer->asyncResourceGatherer->getAssetByID(scResourceID); + + if (!asset || resourceID.empty()) { + // fade in/out with a solid color + if (data.opacity < 1.0 && scAsset) { + const auto SCTEXBOX = getScaledBoxForTexture(scAsset->texture, viewport); + g_pRenderer->renderTexture(SCTEXBOX, scAsset->texture, 1, 0, HYPRUTILS_TRANSFORM_FLIPPED_180); + CHyprColor col = color; + col.a *= data.opacity; + renderRect(col); + return true; + } + + renderRect(color); + return !asset && !resourceID.empty(); // resource not ready + } + + if (asset->texture.m_iType == TEXTURE_INVALID) { + g_pRenderer->asyncResourceGatherer->unloadAsset(asset); + resourceID = ""; + renderRect(color); + return false; + } + + if (asset && (blurPasses > 0 || isScreenshot) && (!blurredFB->isAllocated() || firstRender)) + renderBlur(asset->texture, *blurredFB); + + // For crossfading a new asset + if (pendingAsset && blurPasses > 0 && !pendingBlurredFB->isAllocated()) + renderBlur(pendingAsset->texture, *pendingBlurredFB); + + const auto& TEX = blurredFB->isAllocated() ? blurredFB->m_cTex : asset->texture; + const auto TEXBOX = getScaledBoxForTexture(TEX, viewport); + + if (data.opacity < 1.0 && scAsset) + g_pRenderer->renderTextureMix(TEXBOX, scAsset->texture, TEX, 1.0, data.opacity, 0); + else if (crossFadeProgress->isBeingAnimated()) { + const auto& PENDINGTEX = pendingBlurredFB->isAllocated() ? pendingBlurredFB->m_cTex : pendingAsset->texture; + g_pRenderer->renderTextureMix(TEXBOX, TEX, PENDINGTEX, 1.0, crossFadeProgress->value(), 0); + } else + g_pRenderer->renderTexture(TEXBOX, TEX, 1, 0, HYPRUTILS_TRANSFORM_FLIPPED_180); + + return crossFadeProgress->isBeingAnimated() || data.opacity < 1.0; } void CBackground::plantReloadTimer() { @@ -213,27 +232,6 @@ void CBackground::plantReloadTimer() { reloadTimer = g_pHyprlock->addTimer(std::chrono::seconds(reloadTime), [REF = m_self](auto, auto) { onReloadTimer(REF); }, nullptr, true); } -void CBackground::onCrossFadeTimerUpdate() { - - // Animation done: Unload previous asset, deinitialize the fade and pass the asset - - if (fade) { - fade->crossFadeTimer.reset(); - fade.reset(); - } - - if (blurPasses <= 0 && !isScreenshot) - blurredFB.release(); - - asset = pendingAsset; - resourceID = pendingResourceID; - pendingResourceID = ""; - pendingAsset = nullptr; - firstRender = true; - - g_pHyprlock->renderOutput(outputPort); -} - void CBackground::onReloadTimerUpdate() { const std::string OLDPATH = path; @@ -279,37 +277,37 @@ void CBackground::onReloadTimerUpdate() { g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request); } -void CBackground::startCrossFadeOrUpdateRender() { +void CBackground::startCrossFade() { auto newAsset = g_pRenderer->asyncResourceGatherer->getAssetByID(pendingResourceID); if (newAsset) { if (newAsset->texture.m_iType == TEXTURE_INVALID) { g_pRenderer->asyncResourceGatherer->unloadAsset(newAsset); Debug::log(ERR, "New asset had an invalid texture!"); + pendingResourceID = ""; } else if (resourceID != pendingResourceID) { pendingAsset = newAsset; - if (crossFadeTime > 0) { - // Start a fade - if (!fade) - fade = makeUnique(std::chrono::system_clock::now(), 0, nullptr); - else { - // Maybe we where already fading so reset it just in case, but should'nt be happening. - if (fade->crossFadeTimer) { - fade->crossFadeTimer->cancel(); - fade->crossFadeTimer.reset(); + crossFadeProgress->setValueAndWarp(0); + *crossFadeProgress = 1.0; + + crossFadeProgress->setCallbackOnEnd( + [REF = m_self](auto) { + if (const auto PSELF = REF.lock()) { + PSELF->asset = PSELF->pendingAsset; + PSELF->pendingAsset = nullptr; + g_pRenderer->asyncResourceGatherer->unloadAsset(PSELF->pendingAsset); + PSELF->resourceID = PSELF->pendingResourceID; + PSELF->pendingResourceID = ""; + + PSELF->blurredFB->destroyBuffer(); + PSELF->blurredFB = std::move(PSELF->pendingBlurredFB); } - } - fade->start = std::chrono::system_clock::now(); - fade->a = 0; - fade->crossFadeTimer = - g_pHyprlock->addTimer(std::chrono::milliseconds((int)(1000.0 * crossFadeTime)), [REF = m_self](auto, auto) { onCrossFadeTimer(REF); }, nullptr); - } else { - onCrossFadeTimerUpdate(); - } + }, + true); + + g_pHyprlock->renderOutput(outputPort); } } else if (!pendingResourceID.empty()) { Debug::log(WARN, "Asset {} not available after the asyncResourceGatherer's callback!", pendingResourceID); g_pHyprlock->addTimer(std::chrono::milliseconds(100), [REF = m_self](auto, auto) { onAssetCallback(REF); }, nullptr); } - - g_pHyprlock->renderOutput(outputPort); } diff --git a/src/renderer/widgets/Background.hpp b/src/renderer/widgets/Background.hpp index 5563002..3884aa6 100644 --- a/src/renderer/widgets/Background.hpp +++ b/src/renderer/widgets/Background.hpp @@ -1,6 +1,7 @@ #pragma once #include "IWidget.hpp" +#include "../../helpers/AnimatedVariable.hpp" #include "../../helpers/Color.hpp" #include "../../helpers/Math.hpp" #include "../../core/Timer.hpp" @@ -16,15 +17,9 @@ struct SPreloadedAsset; class COutput; -struct SFade { - std::chrono::system_clock::time_point start; - float a = 0; - std::shared_ptr crossFadeTimer = nullptr; -}; - class CBackground : public IWidget { public: - CBackground() = default; + CBackground(); ~CBackground(); void registerSelf(const SP& self); @@ -36,16 +31,18 @@ class CBackground : public IWidget { void renderRect(CHyprColor color); + void renderBlur(const CTexture& text, CFramebuffer& fb); + void onReloadTimerUpdate(); - void onCrossFadeTimerUpdate(); void plantReloadTimer(); - void startCrossFadeOrUpdateRender(); + void startCrossFade(); private: WP m_self; // if needed - CFramebuffer blurredFB; + UP blurredFB; + UP pendingBlurredFB; int blurSize = 10; int blurPasses = 3; @@ -61,18 +58,18 @@ class CBackground : public IWidget { Hyprutils::Math::eTransform transform; std::string resourceID; + std::string scResourceID; std::string pendingResourceID; - float crossFadeTime = -1.0; + PHLANIMVAR crossFadeProgress; CHyprColor color; SPreloadedAsset* asset = nullptr; - bool isScreenshot = false; + SPreloadedAsset* scAsset = nullptr; SPreloadedAsset* pendingAsset = nullptr; + bool isScreenshot = false; bool firstRender = true; - UP fade; - int reloadTime = -1; std::string reloadCommand; CAsyncResourceGatherer::SPreloadRequest request; diff --git a/src/renderer/widgets/Image.cpp b/src/renderer/widgets/Image.cpp index c777f53..82a0829 100644 --- a/src/renderer/widgets/Image.cpp +++ b/src/renderer/widgets/Image.cpp @@ -125,7 +125,7 @@ void CImage::reset() { if (g_pHyprlock->m_bTerminate) return; - imageFB.release(); + imageFB.destroyBuffer(); if (asset && reloadTime > -1) // Don't unload asset if it's a static image g_pRenderer->asyncResourceGatherer->unloadAsset(asset); @@ -217,7 +217,7 @@ void CImage::renderUpdate() { g_pRenderer->asyncResourceGatherer->unloadAsset(newAsset); } else if (resourceID != pendingResourceID) { g_pRenderer->asyncResourceGatherer->unloadAsset(asset); - imageFB.release(); + imageFB.destroyBuffer(); asset = newAsset; resourceID = pendingResourceID; From 7999f448d71f673dc83c372f338ae7db8e290d7a Mon Sep 17 00:00:00 2001 From: davc0n Date: Thu, 26 Jun 2025 09:35:25 +0200 Subject: [PATCH 6/8] core: replace grace option with --grace cli argument (#802) * core: replace grace option with --grace cli argument * core: remove --immediate option not necessary anymore, grace is not a configuration option * Revert "core: remove --immediate option" This reverts commit 0c9989915712b03f2d3aee4ac565cef87c48ee9a. * core: add --immediate and grace option deprecation warnings * core: review fixes for --immediate and --grace * core: review fixes for grace deprecation --- src/config/ConfigManager.cpp | 1 - src/core/hyprlock.cpp | 9 ++++----- src/core/hyprlock.hpp | 2 +- src/main.cpp | 29 +++++++++++++++++++++++------ 4 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 20d4941..00365d7 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -214,7 +214,6 @@ void CConfigManager::init() { m_config.addConfigValue("general:text_trim", Hyprlang::INT{1}); m_config.addConfigValue("general:hide_cursor", Hyprlang::INT{0}); - m_config.addConfigValue("general:grace", Hyprlang::INT{0}); m_config.addConfigValue("general:ignore_empty_input", Hyprlang::INT{0}); m_config.addConfigValue("general:immediate_render", Hyprlang::INT{0}); m_config.addConfigValue("general:fractional_scaling", Hyprlang::INT{2}); diff --git a/src/core/hyprlock.cpp b/src/core/hyprlock.cpp index 6cbec21..53c2472 100644 --- a/src/core/hyprlock.cpp +++ b/src/core/hyprlock.cpp @@ -36,7 +36,7 @@ static void setMallocThreshold() { #endif } -CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediate, const bool immediateRender) { +CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediateRender, const int graceSeconds) { setMallocThreshold(); m_sWaylandState.display = wl_display_connect(wlDisplay.empty() ? nullptr : wlDisplay.c_str()); @@ -44,10 +44,9 @@ CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediate, const b g_pEGL = makeUnique(m_sWaylandState.display); - if (!immediate) { - static const auto GRACE = g_pConfigManager->getValue("general:grace"); - m_tGraceEnds = *GRACE ? std::chrono::system_clock::now() + std::chrono::seconds(*GRACE) : std::chrono::system_clock::from_time_t(0); - } else + if (graceSeconds > 0) + m_tGraceEnds = std::chrono::system_clock::now() + std::chrono::seconds(graceSeconds); + else m_tGraceEnds = std::chrono::system_clock::from_time_t(0); static const auto IMMEDIATERENDER = g_pConfigManager->getValue("general:immediate_render"); diff --git a/src/core/hyprlock.hpp b/src/core/hyprlock.hpp index fd2f989..eb3187b 100644 --- a/src/core/hyprlock.hpp +++ b/src/core/hyprlock.hpp @@ -29,7 +29,7 @@ struct SDMABUFModifier { class CHyprlock { public: - CHyprlock(const std::string& wlDisplay, const bool immediate, const bool immediateRender); + CHyprlock(const std::string& wlDisplay, const bool immediateRender, const int gracePeriod); ~CHyprlock(); void run(); diff --git a/src/main.cpp b/src/main.cpp index 3217da5..d71a59a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,7 +13,7 @@ void help() { " -q, --quiet - Disable logging\n" " -c FILE, --config FILE - Specify config file to use\n" " --display NAME - Specify the Wayland display to connect to\n" - " --immediate - Lock immediately, ignoring any configured grace period\n" + " --grace SECONDS - Set grace period in seconds before requiring authentication\n" " --immediate-render - Do not wait for resources before drawing the background\n" " --no-fade-in - Disable the fade-in animation when the lock screen appears\n" " -V, --version - Show version information\n" @@ -40,9 +40,9 @@ static void printVersion() { int main(int argc, char** argv, char** envp) { std::string configPath; std::string wlDisplay; - bool immediate = false; bool immediateRender = false; bool noFadeIn = false; + int graceSeconds = 0; std::vector args(argv, argv + argc); @@ -77,8 +77,25 @@ int main(int argc, char** argv, char** envp) { else return 1; - } else if (arg == "--immediate") - immediate = true; + } else if (arg == "--grace" && i + 1 < (std::size_t)argc) { + if (auto value = parseArg(args, arg, i); value) { + try { + graceSeconds = std::stoi(*value); + if (graceSeconds < 0) { + std::println(stderr, "Error: Grace period must be non-negative."); + return 1; + } + } catch (const std::exception&) { + std::println(stderr, "Error: Invalid grace period value: {}", *value); + return 1; + } + } else + return 1; + + } else if (arg == "--immediate") { + graceSeconds = 0; + Debug::log(WARN, R"("--immediate" is deprecated. Use the "--grace" option instead.)"); + } else if (arg == "--immediate-render") immediateRender = true; @@ -107,11 +124,11 @@ int main(int argc, char** argv, char** envp) { return 1; } - if (noFadeIn || immediate) + if (noFadeIn) g_pConfigManager->m_AnimationTree.setConfigForNode("fadeIn", false, 0.f, "default"); try { - g_pHyprlock = makeUnique(wlDisplay, immediate, immediateRender); + g_pHyprlock = makeUnique(wlDisplay, immediateRender, graceSeconds); g_pHyprlock->run(); } catch (const std::exception& ex) { Debug::log(CRIT, "Hyprlock threw: {}", ex.what()); From d84b44e695260755939a39eb488ce8fa067af009 Mon Sep 17 00:00:00 2001 From: Maximilian Seidler <78690852+PaideiaDilemma@users.noreply.github.com> Date: Sat, 28 Jun 2025 11:01:28 +0200 Subject: [PATCH 7/8] core: use hyprutils atomic pointers (#808) * widgets: move references to hyprutils atomic shared * core: move std::shared_pointers to hyprutils atomic shared pointers * Nix: bump hyprutils input * clang-format * cmake: bump hyprutils to v0.8.0 * and bump nix again --- CMakeLists.txt | 2 +- flake.lock | 6 +-- src/auth/Auth.cpp | 6 +-- src/auth/Auth.hpp | 2 +- src/auth/Fingerprint.cpp | 2 +- src/core/Seat.cpp | 4 +- src/core/Timer.cpp | 4 +- src/core/Timer.hpp | 15 +++--- src/core/hyprlock.cpp | 15 +++--- src/core/hyprlock.hpp | 55 ++++++++++----------- src/defines.hpp | 4 ++ src/renderer/Renderer.cpp | 6 +-- src/renderer/Renderer.hpp | 4 +- src/renderer/widgets/Background.cpp | 6 +-- src/renderer/widgets/Background.hpp | 6 +-- src/renderer/widgets/Image.cpp | 8 +-- src/renderer/widgets/Image.hpp | 6 +-- src/renderer/widgets/Label.cpp | 8 +-- src/renderer/widgets/Label.hpp | 6 +-- src/renderer/widgets/PasswordInputField.cpp | 6 +-- src/renderer/widgets/PasswordInputField.hpp | 52 +++++++++---------- src/renderer/widgets/Shadowable.cpp | 2 +- src/renderer/widgets/Shadowable.hpp | 14 +++--- src/renderer/widgets/Shape.cpp | 4 +- src/renderer/widgets/Shape.hpp | 4 +- 25 files changed, 124 insertions(+), 123 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2613d67..7880f6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,7 +87,7 @@ pkg_check_modules( libdrm gbm pam - hyprutils>=0.5.0 + hyprutils>=0.8.0 sdbus-c++>=2.0.0 hyprgraphics) diff --git a/flake.lock b/flake.lock index 507f5d2..3ca8ec1 100644 --- a/flake.lock +++ b/flake.lock @@ -62,11 +62,11 @@ ] }, "locked": { - "lastModified": 1749135356, - "narHash": "sha256-Q8mAKMDsFbCEuq7zoSlcTuxgbIBVhfIYpX0RjE32PS0=", + "lastModified": 1750966151, + "narHash": "sha256-SlIgrGlF/MDl8DcAiz0Xg2dK+N+Sy03gHxMhzbBK8vY=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "e36db00dfb3a3d3fdcc4069cb292ff60d2699ccb", + "rev": "1eb6759ae7a53cff9a9f80e1e6db88235e0c7648", "type": "github" }, "original": { diff --git a/src/auth/Auth.cpp b/src/auth/Auth.cpp index 5d7eeff..15824ac 100644 --- a/src/auth/Auth.cpp +++ b/src/auth/Auth.cpp @@ -76,7 +76,7 @@ void CAuth::terminate() { } } -static void unlockCallback(std::shared_ptr self, void* data) { +static void unlockCallback(ASP self, void* data) { g_pHyprlock->unlock(); } @@ -84,7 +84,7 @@ void CAuth::enqueueUnlock() { g_pHyprlock->addTimer(std::chrono::milliseconds(0), unlockCallback, nullptr); } -static void passwordFailCallback(std::shared_ptr self, void* data) { +static void passwordFailCallback(ASP self, void* data) { g_pAuth->m_bDisplayFailText = true; g_pHyprlock->enqueueForceUpdateTimers(); @@ -92,7 +92,7 @@ static void passwordFailCallback(std::shared_ptr self, void* data) { g_pHyprlock->renderAllOutputs(); } -static void displayFailTimeoutCallback(std::shared_ptr self, void* data) { +static void displayFailTimeoutCallback(ASP self, void* data) { if (g_pAuth->m_bDisplayFailText) { g_pAuth->m_bDisplayFailText = false; g_pHyprlock->renderAllOutputs(); diff --git a/src/auth/Auth.hpp b/src/auth/Auth.hpp index ed41c78..40c902b 100644 --- a/src/auth/Auth.hpp +++ b/src/auth/Auth.hpp @@ -61,7 +61,7 @@ class CAuth { } m_sCurrentFail; std::vector> m_vImpls; - std::shared_ptr m_resetDisplayFailTimer; + ASP m_resetDisplayFailTimer; }; inline UP g_pAuth; diff --git a/src/auth/Fingerprint.cpp b/src/auth/Fingerprint.cpp index 2063252..db4bba7 100644 --- a/src/auth/Fingerprint.cpp +++ b/src/auth/Fingerprint.cpp @@ -158,7 +158,7 @@ void CFingerprint::handleVerifyStatus(const std::string& result, bool done) { } else { done = false; static const auto RETRYDELAY = g_pConfigManager->getValue("auth:fingerprint:retry_delay"); - g_pHyprlock->addTimer(std::chrono::milliseconds(*RETRYDELAY), [](std::shared_ptr self, void* data) { ((CFingerprint*)data)->startVerify(true); }, this); + g_pHyprlock->addTimer(std::chrono::milliseconds(*RETRYDELAY), [](ASP self, void* data) { ((CFingerprint*)data)->startVerify(true); }, this); m_sFailureReason = "Fingerprint did not match"; } break; diff --git a/src/core/Seat.cpp b/src/core/Seat.cpp index a3f811c..02d3aa5 100644 --- a/src/core/Seat.cpp +++ b/src/core/Seat.cpp @@ -82,9 +82,7 @@ void CSeatManager::registerSeat(SP seat) { m_pTouch->setDown([](CCWlTouch* r, uint32_t serial, uint32_t time, wl_proxy* surface, int32_t id, wl_fixed_t x, wl_fixed_t y) { g_pHyprlock->onClick(BTN_LEFT, true, {wl_fixed_to_double(x), wl_fixed_to_double(y)}); }); - m_pTouch->setUp([](CCWlTouch* r, uint32_t serial, uint32_t time, int32_t id) { - g_pHyprlock->onClick(BTN_LEFT, false, {0, 0}); - }); + m_pTouch->setUp([](CCWlTouch* r, uint32_t serial, uint32_t time, int32_t id) { g_pHyprlock->onClick(BTN_LEFT, false, {0, 0}); }); }; if (caps & WL_SEAT_CAPABILITY_KEYBOARD) { m_pKeeb = makeShared(r->sendGetKeyboard()); diff --git a/src/core/Timer.cpp b/src/core/Timer.cpp index 95f25af..cf86c4b 100644 --- a/src/core/Timer.cpp +++ b/src/core/Timer.cpp @@ -1,6 +1,6 @@ #include "Timer.hpp" -CTimer::CTimer(std::chrono::system_clock::duration timeout, std::function self, void* data)> cb_, void* data_, bool force) : +CTimer::CTimer(std::chrono::system_clock::duration timeout, std::function self, void* data)> cb_, void* data_, bool force) : cb(cb_), data(data_), allowForceUpdate(force) { expires = std::chrono::system_clock::now() + timeout; } @@ -17,7 +17,7 @@ bool CTimer::cancelled() { return wasCancelled; } -void CTimer::call(std::shared_ptr self) { +void CTimer::call(ASP self) { cb(self, data); } diff --git a/src/core/Timer.hpp b/src/core/Timer.hpp index a7a5a3d..d66b73d 100644 --- a/src/core/Timer.hpp +++ b/src/core/Timer.hpp @@ -2,10 +2,11 @@ #include #include +#include "../defines.hpp" class CTimer { public: - CTimer(std::chrono::system_clock::duration timeout, std::function self, void* data)> cb_, void* data_, bool force); + CTimer(std::chrono::system_clock::duration timeout, std::function self, void* data)> cb_, void* data_, bool force); void cancel(); bool passed(); @@ -14,12 +15,12 @@ class CTimer { float leftMs(); bool cancelled(); - void call(std::shared_ptr self); + void call(ASP self); private: - std::function self, void* data)> cb; - void* data = nullptr; - std::chrono::system_clock::time_point expires; - bool wasCancelled = false; - bool allowForceUpdate = false; + std::function self, void* data)> cb; + void* data = nullptr; + std::chrono::system_clock::time_point expires; + bool wasCancelled = false; + bool allowForceUpdate = false; }; diff --git a/src/core/hyprlock.cpp b/src/core/hyprlock.cpp index 53c2472..0b5fa69 100644 --- a/src/core/hyprlock.cpp +++ b/src/core/hyprlock.cpp @@ -481,7 +481,7 @@ void CHyprlock::run() { auto timerscpy = m_vTimers; m_sLoopState.timersMutex.unlock(); - std::vector> passed; + std::vector> passed; for (auto& t : timerscpy) { if (t->passed() && !t->cancelled()) { @@ -586,7 +586,7 @@ void CHyprlock::startKeyRepeat(xkb_keysym_t sym) { if (m_iKeebRepeatDelay <= 0) return; - m_pKeyRepeatTimer = addTimer(std::chrono::milliseconds(m_iKeebRepeatDelay), [sym](std::shared_ptr self, void* data) { g_pHyprlock->repeatKey(sym); }, nullptr); + m_pKeyRepeatTimer = addTimer(std::chrono::milliseconds(m_iKeebRepeatDelay), [sym](ASP self, void* data) { g_pHyprlock->repeatKey(sym); }, nullptr); } void CHyprlock::repeatKey(xkb_keysym_t sym) { @@ -597,7 +597,7 @@ void CHyprlock::repeatKey(xkb_keysym_t sym) { // This condition is for backspace and delete keys, but should also be ok for other keysyms since our buffer won't be empty anyways if (bool CONTINUE = m_sPasswordState.passBuffer.length() > 0; CONTINUE) - m_pKeyRepeatTimer = addTimer(std::chrono::milliseconds(m_iKeebRepeatRate), [sym](std::shared_ptr self, void* data) { g_pHyprlock->repeatKey(sym); }, nullptr); + m_pKeyRepeatTimer = addTimer(std::chrono::milliseconds(m_iKeebRepeatRate), [sym](ASP self, void* data) { g_pHyprlock->repeatKey(sym); }, nullptr); renderAllOutputs(); } @@ -876,23 +876,22 @@ size_t CHyprlock::getPasswordBufferDisplayLen() { return std::count_if(m_sPasswordState.passBuffer.begin(), m_sPasswordState.passBuffer.end(), [](char c) { return (c & 0xc0) != 0x80; }); } -std::shared_ptr CHyprlock::addTimer(const std::chrono::system_clock::duration& timeout, std::function self, void* data)> cb_, void* data, - bool force) { +ASP CHyprlock::addTimer(const std::chrono::system_clock::duration& timeout, std::function self, void* data)> cb_, void* data, bool force) { std::lock_guard lg(m_sLoopState.timersMutex); - const auto T = m_vTimers.emplace_back(std::make_shared(timeout, cb_, data, force)); + const auto T = m_vTimers.emplace_back(makeAtomicShared(timeout, cb_, data, force)); m_sLoopState.timerEvent = true; m_sLoopState.timerCV.notify_all(); return T; } -std::vector> CHyprlock::getTimers() { +std::vector> CHyprlock::getTimers() { return m_vTimers; } void CHyprlock::enqueueForceUpdateTimers() { addTimer( std::chrono::milliseconds(1), - [](std::shared_ptr self, void* data) { + [](ASP self, void* data) { for (auto& t : g_pHyprlock->getTimers()) { if (t->canForceUpdate()) { t->call(t); diff --git a/src/core/hyprlock.hpp b/src/core/hyprlock.hpp index eb3187b..25ca572 100644 --- a/src/core/hyprlock.hpp +++ b/src/core/hyprlock.hpp @@ -32,38 +32,37 @@ class CHyprlock { CHyprlock(const std::string& wlDisplay, const bool immediateRender, const int gracePeriod); ~CHyprlock(); - void run(); + void run(); - void unlock(); - bool isUnlocked(); + void unlock(); + bool isUnlocked(); - std::shared_ptr addTimer(const std::chrono::system_clock::duration& timeout, std::function self, void* data)> cb_, void* data, - bool force = false); + ASP addTimer(const std::chrono::system_clock::duration& timeout, std::function self, void* data)> cb_, void* data, bool force = false); - void enqueueForceUpdateTimers(); + void enqueueForceUpdateTimers(); - void onLockLocked(); - void onLockFinished(); + void onLockLocked(); + void onLockFinished(); - bool acquireSessionLock(); - void releaseSessionLock(); + bool acquireSessionLock(); + void releaseSessionLock(); - void onKey(uint32_t key, bool down); - void onClick(uint32_t button, bool down, const Vector2D& pos); - void onHover(const Vector2D& pos); - void startKeyRepeat(xkb_keysym_t sym); - void repeatKey(xkb_keysym_t sym); - void handleKeySym(xkb_keysym_t sym, bool compose); - void onPasswordCheckTimer(); - void clearPasswordBuffer(); - bool passwordCheckWaiting(); - std::optional passwordLastFailReason(); + void onKey(uint32_t key, bool down); + void onClick(uint32_t button, bool down, const Vector2D& pos); + void onHover(const Vector2D& pos); + void startKeyRepeat(xkb_keysym_t sym); + void repeatKey(xkb_keysym_t sym); + void handleKeySym(xkb_keysym_t sym, bool compose); + void onPasswordCheckTimer(); + void clearPasswordBuffer(); + bool passwordCheckWaiting(); + std::optional passwordLastFailReason(); - void renderOutput(const std::string& stringPort); - void renderAllOutputs(); + void renderOutput(const std::string& stringPort); + void renderAllOutputs(); - size_t getPasswordBufferLen(); - size_t getPasswordBufferDisplayLen(); + size_t getPasswordBufferLen(); + size_t getPasswordBufferDisplayLen(); SP getSessionLockMgr(); SP getSessionLock(); @@ -99,10 +98,10 @@ class CHyprlock { Vector2D m_vMouseLocation = {}; - std::shared_ptr m_pKeyRepeatTimer = nullptr; + ASP m_pKeyRepeatTimer = nullptr; std::vector> m_vOutputs; - std::vector> getTimers(); + std::vector> getTimers(); struct { SP linuxDmabuf = nullptr; @@ -158,9 +157,9 @@ class CHyprlock { bool timerEvent = false; } m_sLoopState; - std::vector> m_vTimers; + std::vector> m_vTimers; - std::vector m_vPressedKeys; + std::vector m_vPressedKeys; }; inline UP g_pHyprlock; diff --git a/src/defines.hpp b/src/defines.hpp index 5715805..dd0f1bb 100644 --- a/src/defines.hpp +++ b/src/defines.hpp @@ -2,6 +2,7 @@ #include #include +#include #include using namespace Hyprutils::Memory; @@ -10,5 +11,8 @@ using namespace Hyprgraphics; #define WP CWeakPointer #define UP CUniquePointer +#define ASP CAtomicSharedPointer +#define AWP CAtomicWeakPointer + typedef int64_t OUTPUTID; constexpr OUTPUTID OUTPUT_INVALID = -1; diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index 103763d..41bdb0a 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -388,13 +388,13 @@ void CRenderer::renderTextureMix(const CBox& box, const CTexture& tex, const CTe } template -static void createWidget(std::vector>& widgets) { - const auto W = makeShared(); +static void createWidget(std::vector>& widgets) { + const auto W = makeAtomicShared(); W->registerSelf(W); widgets.emplace_back(W); } -std::vector>& CRenderer::getOrCreateWidgetsFor(const CSessionLockSurface& surf) { +std::vector>& CRenderer::getOrCreateWidgetsFor(const CSessionLockSurface& surf) { RASSERT(surf.m_outputID != OUTPUT_INVALID, "Invalid output ID!"); if (!widgets.contains(surf.m_outputID)) { diff --git a/src/renderer/Renderer.hpp b/src/renderer/Renderer.hpp index a638736..bc2952e 100644 --- a/src/renderer/Renderer.hpp +++ b/src/renderer/Renderer.hpp @@ -12,7 +12,7 @@ #include "widgets/IWidget.hpp" #include "Framebuffer.hpp" -typedef std::unordered_map>> widgetMap_t; +typedef std::unordered_map>> widgetMap_t; class CRenderer { public: @@ -48,7 +48,7 @@ class CRenderer { void startFadeIn(); void startFadeOut(bool unlock = false); - std::vector>& getOrCreateWidgetsFor(const CSessionLockSurface& surf); + std::vector>& getOrCreateWidgetsFor(const CSessionLockSurface& surf); private: widgetMap_t widgets; diff --git a/src/renderer/widgets/Background.cpp b/src/renderer/widgets/Background.cpp index 2299601..565076a 100644 --- a/src/renderer/widgets/Background.cpp +++ b/src/renderer/widgets/Background.cpp @@ -22,7 +22,7 @@ CBackground::~CBackground() { reset(); } -void CBackground::registerSelf(const SP& self) { +void CBackground::registerSelf(const ASP& self) { m_self = self; } @@ -98,14 +98,14 @@ void CBackground::renderRect(CHyprColor color) { g_pRenderer->renderRect(monbox, color, 0); } -static void onReloadTimer(WP ref) { +static void onReloadTimer(AWP ref) { if (auto PBG = ref.lock(); PBG) { PBG->onReloadTimerUpdate(); PBG->plantReloadTimer(); } } -static void onAssetCallback(WP ref) { +static void onAssetCallback(AWP ref) { if (auto PBG = ref.lock(); PBG) PBG->startCrossFade(); } diff --git a/src/renderer/widgets/Background.hpp b/src/renderer/widgets/Background.hpp index 3884aa6..316fa46 100644 --- a/src/renderer/widgets/Background.hpp +++ b/src/renderer/widgets/Background.hpp @@ -22,7 +22,7 @@ class CBackground : public IWidget { CBackground(); ~CBackground(); - void registerSelf(const SP& self); + void registerSelf(const ASP& self); virtual void configure(const std::unordered_map& props, const SP& pOutput); virtual bool draw(const SRenderData& data); @@ -38,7 +38,7 @@ class CBackground : public IWidget { void startCrossFade(); private: - WP m_self; + AWP m_self; // if needed UP blurredFB; @@ -73,6 +73,6 @@ class CBackground : public IWidget { int reloadTime = -1; std::string reloadCommand; CAsyncResourceGatherer::SPreloadRequest request; - std::shared_ptr reloadTimer; + ASP reloadTimer; std::filesystem::file_time_type modificationTime; }; diff --git a/src/renderer/widgets/Image.cpp b/src/renderer/widgets/Image.cpp index 82a0829..0ff1c6f 100644 --- a/src/renderer/widgets/Image.cpp +++ b/src/renderer/widgets/Image.cpp @@ -12,18 +12,18 @@ CImage::~CImage() { reset(); } -void CImage::registerSelf(const SP& self) { +void CImage::registerSelf(const ASP& self) { m_self = self; } -static void onTimer(WP ref) { +static void onTimer(AWP ref) { if (auto PIMAGE = ref.lock(); PIMAGE) { PIMAGE->onTimerUpdate(); PIMAGE->plantTimer(); } } -static void onAssetCallback(WP ref) { +static void onAssetCallback(AWP ref) { if (auto PIMAGE = ref.lock(); PIMAGE) PIMAGE->renderUpdate(); } @@ -82,7 +82,7 @@ void CImage::configure(const std::unordered_map& props, c viewport = pOutput->getViewport(); stringPort = pOutput->stringPort; - shadow.configure(m_self.lock(), props, viewport); + shadow.configure(m_self, props, viewport); try { size = std::any_cast(props.at("size")); diff --git a/src/renderer/widgets/Image.hpp b/src/renderer/widgets/Image.hpp index 3afa3a7..c638c62 100644 --- a/src/renderer/widgets/Image.hpp +++ b/src/renderer/widgets/Image.hpp @@ -20,7 +20,7 @@ class CImage : public IWidget { CImage() = default; ~CImage(); - void registerSelf(const SP& self); + void registerSelf(const ASP& self); virtual void configure(const std::unordered_map& props, const SP& pOutput); virtual bool draw(const SRenderData& data); @@ -35,7 +35,7 @@ class CImage : public IWidget { void plantTimer(); private: - WP m_self; + AWP m_self; CFramebuffer imageFB; @@ -56,7 +56,7 @@ class CImage : public IWidget { std::string onclickCommand; std::filesystem::file_time_type modificationTime; - std::shared_ptr imageTimer; + ASP imageTimer; CAsyncResourceGatherer::SPreloadRequest request; Vector2D viewport; diff --git a/src/renderer/widgets/Label.cpp b/src/renderer/widgets/Label.cpp index 7befb19..bd7692c 100644 --- a/src/renderer/widgets/Label.cpp +++ b/src/renderer/widgets/Label.cpp @@ -12,11 +12,11 @@ CLabel::~CLabel() { reset(); } -void CLabel::registerSelf(const SP& self) { +void CLabel::registerSelf(const ASP& self) { m_self = self; } -static void onTimer(WP ref) { +static void onTimer(AWP ref) { if (auto PLABEL = ref.lock(); PLABEL) { // update label PLABEL->onTimerUpdate(); @@ -25,7 +25,7 @@ static void onTimer(WP ref) { } } -static void onAssetCallback(WP ref) { +static void onAssetCallback(AWP ref) { if (auto PLABEL = ref.lock(); PLABEL) PLABEL->renderUpdate(); } @@ -71,7 +71,7 @@ void CLabel::configure(const std::unordered_map& props, c outputStringPort = pOutput->stringPort; viewport = pOutput->getViewport(); - shadow.configure(m_self.lock(), props, viewport); + shadow.configure(m_self, props, viewport); try { configPos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport); diff --git a/src/renderer/widgets/Label.hpp b/src/renderer/widgets/Label.hpp index b43a2c4..5a0ee93 100644 --- a/src/renderer/widgets/Label.hpp +++ b/src/renderer/widgets/Label.hpp @@ -17,7 +17,7 @@ class CLabel : public IWidget { CLabel() = default; ~CLabel(); - void registerSelf(const SP& self); + void registerSelf(const ASP& self); virtual void configure(const std::unordered_map& prop, const SP& pOutput); virtual bool draw(const SRenderData& data); @@ -32,7 +32,7 @@ class CLabel : public IWidget { void plantTimer(); private: - WP m_self; + AWP m_self; std::string getUniqueResourceId(); @@ -53,7 +53,7 @@ class CLabel : public IWidget { CAsyncResourceGatherer::SPreloadRequest request; - std::shared_ptr labelTimer = nullptr; + ASP labelTimer = nullptr; CShadowable shadow; bool updateShadow = true; diff --git a/src/renderer/widgets/PasswordInputField.cpp b/src/renderer/widgets/PasswordInputField.cpp index 8023d7a..1339378 100644 --- a/src/renderer/widgets/PasswordInputField.cpp +++ b/src/renderer/widgets/PasswordInputField.cpp @@ -19,7 +19,7 @@ CPasswordInputField::~CPasswordInputField() { reset(); } -void CPasswordInputField::registerSelf(const SP& self) { +void CPasswordInputField::registerSelf(const ASP& self) { m_self = self; } @@ -29,7 +29,7 @@ void CPasswordInputField::configure(const std::unordered_mapstringPort; viewport = pOutput->getViewport(); - shadow.configure(m_self.lock(), props, viewport); + shadow.configure(m_self, props, viewport); try { pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport); @@ -119,7 +119,7 @@ void CPasswordInputField::reset() { placeholder.currentText.clear(); } -static void fadeOutCallback(WP ref) { +static void fadeOutCallback(AWP ref) { if (const auto PP = ref.lock(); PP) PP->onFadeOutTimer(); } diff --git a/src/renderer/widgets/PasswordInputField.hpp b/src/renderer/widgets/PasswordInputField.hpp index 764d83a..1aa403d 100644 --- a/src/renderer/widgets/PasswordInputField.hpp +++ b/src/renderer/widgets/PasswordInputField.hpp @@ -19,7 +19,7 @@ class CPasswordInputField : public IWidget { CPasswordInputField() = default; virtual ~CPasswordInputField(); - void registerSelf(const SP& self); + void registerSelf(const ASP& self); virtual void configure(const std::unordered_map& prop, const SP& pOutput); virtual bool draw(const SRenderData& data); @@ -30,33 +30,33 @@ class CPasswordInputField : public IWidget { void onFadeOutTimer(); private: - WP m_self; + AWP m_self; - void updateDots(); - void updateFade(); - void updatePlaceholder(); - void updateWidth(); - void updateHiddenInputState(); - void updateInputState(); - void updateColors(); + void updateDots(); + void updateFade(); + void updatePlaceholder(); + void updateWidth(); + void updateHiddenInputState(); + void updateInputState(); + void updateColors(); - bool firstRender = true; - bool redrawShadow = false; - bool checkWaiting = false; - bool displayFail = false; + bool firstRender = true; + bool redrawShadow = false; + bool checkWaiting = false; + bool displayFail = false; - size_t passwordLength = 0; + size_t passwordLength = 0; - PHLANIMVAR size; - Vector2D pos; - Vector2D viewport; - Vector2D configPos; - Vector2D configSize; + PHLANIMVAR size; + Vector2D pos; + Vector2D viewport; + Vector2D configPos; + Vector2D configSize; - std::string halign, valign, configFailText, outputStringPort, configPlaceholderText, fontFamily; - uint64_t configFailTimeoutMs = 2000; + std::string halign, valign, configFailText, outputStringPort, configPlaceholderText, fontFamily; + uint64_t configFailTimeoutMs = 2000; - int outThick, rounding; + int outThick, rounding; struct { PHLANIMVAR currentAmount; @@ -70,10 +70,10 @@ class CPasswordInputField : public IWidget { } dots; struct { - PHLANIMVAR a; - bool appearing = true; - std::shared_ptr fadeOutTimer = nullptr; - bool allowFadeOut = false; + PHLANIMVAR a; + bool appearing = true; + ASP fadeOutTimer = nullptr; + bool allowFadeOut = false; } fade; struct { diff --git a/src/renderer/widgets/Shadowable.cpp b/src/renderer/widgets/Shadowable.cpp index dcd2b22..3e02a1e 100644 --- a/src/renderer/widgets/Shadowable.cpp +++ b/src/renderer/widgets/Shadowable.cpp @@ -2,7 +2,7 @@ #include "../Renderer.hpp" #include -void CShadowable::configure(WP widget_, const std::unordered_map& props, const Vector2D& viewport_) { +void CShadowable::configure(AWP widget_, const std::unordered_map& props, const Vector2D& viewport_) { m_widget = widget_; viewport = viewport_; diff --git a/src/renderer/widgets/Shadowable.hpp b/src/renderer/widgets/Shadowable.hpp index 4d809a1..994980e 100644 --- a/src/renderer/widgets/Shadowable.hpp +++ b/src/renderer/widgets/Shadowable.hpp @@ -13,19 +13,19 @@ class CShadowable { public: virtual ~CShadowable() = default; CShadowable() = default; - void configure(WP widget_, const std::unordered_map& props, const Vector2D& viewport_ /* TODO: make this not the entire viewport */); + void configure(AWP widget_, const std::unordered_map& props, const Vector2D& viewport_ /* TODO: make this not the entire viewport */); // instantly re-renders the shadow using the widget's draw() method void markShadowDirty(); virtual bool draw(const IWidget::SRenderData& data); private: - WP m_widget; - int size = 10; - int passes = 4; - float boostA = 1.0; - CHyprColor color{0, 0, 0, 1.0}; - Vector2D viewport; + AWP m_widget; + int size = 10; + int passes = 4; + float boostA = 1.0; + CHyprColor color{0, 0, 0, 1.0}; + Vector2D viewport; // to avoid recursive shadows bool ignoreDraw = false; diff --git a/src/renderer/widgets/Shape.cpp b/src/renderer/widgets/Shape.cpp index cc3e73b..c1c6dc1 100644 --- a/src/renderer/widgets/Shape.cpp +++ b/src/renderer/widgets/Shape.cpp @@ -7,14 +7,14 @@ #include #include -void CShape::registerSelf(const SP& self) { +void CShape::registerSelf(const ASP& self) { m_self = self; } void CShape::configure(const std::unordered_map& props, const SP& pOutput) { viewport = pOutput->getViewport(); - shadow.configure(m_self.lock(), props, viewport); + shadow.configure(m_self, props, viewport); try { size = CLayoutValueData::fromAnyPv(props.at("size"))->getAbsolute(viewport); diff --git a/src/renderer/widgets/Shape.hpp b/src/renderer/widgets/Shape.hpp index 133a9ae..33a4e02 100644 --- a/src/renderer/widgets/Shape.hpp +++ b/src/renderer/widgets/Shape.hpp @@ -14,7 +14,7 @@ class CShape : public IWidget { CShape() = default; virtual ~CShape() = default; - void registerSelf(const SP& self); + void registerSelf(const ASP& self); virtual void configure(const std::unordered_map& prop, const SP& pOutput); virtual bool draw(const SRenderData& data); @@ -23,7 +23,7 @@ class CShape : public IWidget { virtual void onHover(const Vector2D& pos); private: - WP m_self; + AWP m_self; CFramebuffer shapeFB; From fee04f640676868fe343bd3ffd0b81b22bd032ee Mon Sep 17 00:00:00 2001 From: Karun Sandhu <129101708+MrSom3body@users.noreply.github.com> Date: Sat, 28 Jun 2025 20:47:11 +0200 Subject: [PATCH 8/8] flake.lock: update --- flake.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/flake.lock b/flake.lock index 3ca8ec1..523db0c 100644 --- a/flake.lock +++ b/flake.lock @@ -13,11 +13,11 @@ ] }, "locked": { - "lastModified": 1749145600, - "narHash": "sha256-v2kY5RDk9oyo1x9m8u83GdklC96xlJ7ka1rrvZoYL78=", + "lastModified": 1750621377, + "narHash": "sha256-8u6b5oAdX0rCuoR8wFenajBRmI+mzbpNig6hSCuWUzE=", "owner": "hyprwm", "repo": "hyprgraphics", - "rev": "80b754e38e836777ad3a9d5d1ffc3491b0332471", + "rev": "b3d628d01693fb9bb0a6690cd4e7b80abda04310", "type": "github" }, "original": { @@ -39,11 +39,11 @@ ] }, "locked": { - "lastModified": 1749145882, - "narHash": "sha256-qr0KXeczF8Sma3Ae7+dR2NHhvG7YeLBJv19W4oMu6ZE=", + "lastModified": 1750371198, + "narHash": "sha256-/iuJ1paQOBoSLqHflRNNGyroqfF/yvPNurxzcCT0cAE=", "owner": "hyprwm", "repo": "hyprlang", - "rev": "1bfb84f54d50c7ae6558c794d3cfd5f6a7e6e676", + "rev": "cee01452bca58d6cadb3224e21e370de8bc20f0b", "type": "github" }, "original": { @@ -62,11 +62,11 @@ ] }, "locked": { - "lastModified": 1750966151, - "narHash": "sha256-SlIgrGlF/MDl8DcAiz0Xg2dK+N+Sy03gHxMhzbBK8vY=", + "lastModified": 1751061882, + "narHash": "sha256-g9n8Vrbx+2JYM170P9BbvGHN39Wlkr4U+V2WLHQsXL8=", "owner": "hyprwm", "repo": "hyprutils", - "rev": "1eb6759ae7a53cff9a9f80e1e6db88235e0c7648", + "rev": "4737241eaf8a1e51671a2a088518071f9a265cf4", "type": "github" }, "original": { @@ -85,11 +85,11 @@ ] }, "locked": { - "lastModified": 1749145760, - "narHash": "sha256-IHaGWpGrv7seFWdw/1A+wHtTsPlOGIKMrk1TUIYJEFI=", + "lastModified": 1750371869, + "narHash": "sha256-lGk4gLjgZQ/rndUkzmPYcgbHr8gKU5u71vyrjnwfpB4=", "owner": "hyprwm", "repo": "hyprwayland-scanner", - "rev": "817918315ea016cc2d94004bfb3223b5fd9dfcc6", + "rev": "aa38edd6e3e277ae6a97ea83a69261a5c3aab9fd", "type": "github" }, "original": { @@ -100,11 +100,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1748929857, - "narHash": "sha256-lcZQ8RhsmhsK8u7LIFsJhsLh/pzR9yZ8yqpTzyGdj+Q=", + "lastModified": 1751011381, + "narHash": "sha256-krGXKxvkBhnrSC/kGBmg5MyupUUT5R6IBCLEzx9jhMM=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "c2a03962b8e24e669fb37b7df10e7c79531ff1a4", + "rev": "30e2e2857ba47844aa71991daa6ed1fc678bcbb7", "type": "github" }, "original": {