mirror of
https://github.com/hyprwm/hyprlock.git
synced 2025-05-13 05:40:42 +01:00
core: more hyprutils smart pointer usage and safe references to widgets (#686)
* core: move to UP and make widgets use SPs * widgets: make widgets have a self ref to avoid UB * fix shadows and let them have a WP to widgets
This commit is contained in:
parent
712ab62a42
commit
9f37c1c8e9
36 changed files with 546 additions and 385 deletions
|
@ -11,10 +11,10 @@
|
||||||
CAuth::CAuth() {
|
CAuth::CAuth() {
|
||||||
static const auto ENABLEPAM = g_pConfigManager->getValue<Hyprlang::INT>("auth:pam:enabled");
|
static const auto ENABLEPAM = g_pConfigManager->getValue<Hyprlang::INT>("auth:pam:enabled");
|
||||||
if (*ENABLEPAM)
|
if (*ENABLEPAM)
|
||||||
m_vImpls.push_back(std::make_shared<CPam>());
|
m_vImpls.emplace_back(makeShared<CPam>());
|
||||||
static const auto ENABLEFINGERPRINT = g_pConfigManager->getValue<Hyprlang::INT>("auth:fingerprint:enabled");
|
static const auto ENABLEFINGERPRINT = g_pConfigManager->getValue<Hyprlang::INT>("auth:fingerprint:enabled");
|
||||||
if (*ENABLEFINGERPRINT)
|
if (*ENABLEFINGERPRINT)
|
||||||
m_vImpls.push_back(std::make_shared<CFingerprint>());
|
m_vImpls.emplace_back(makeShared<CFingerprint>());
|
||||||
|
|
||||||
RASSERT(!m_vImpls.empty(), "At least one authentication method must be enabled!");
|
RASSERT(!m_vImpls.empty(), "At least one authentication method must be enabled!");
|
||||||
}
|
}
|
||||||
|
@ -32,12 +32,7 @@ void CAuth::submitInput(const std::string& input) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CAuth::checkWaiting() {
|
bool CAuth::checkWaiting() {
|
||||||
for (const auto& i : m_vImpls) {
|
return std::ranges::any_of(m_vImpls, [](const auto& i) { return i->checkWaiting(); });
|
||||||
if (i->checkWaiting())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& CAuth::getCurrentFailText() {
|
const std::string& CAuth::getCurrentFailText() {
|
||||||
|
@ -64,7 +59,7 @@ size_t CAuth::getFailedAttempts() {
|
||||||
return m_sCurrentFail.failedAttempts;
|
return m_sCurrentFail.failedAttempts;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<IAuthImplementation> CAuth::getImpl(eAuthImplementations implType) {
|
SP<IAuthImplementation> CAuth::getImpl(eAuthImplementations implType) {
|
||||||
for (const auto& i : m_vImpls) {
|
for (const auto& i : m_vImpls) {
|
||||||
if (i->getImplType() == implType)
|
if (i->getImplType() == implType)
|
||||||
return i;
|
return i;
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
|
||||||
enum eAuthImplementations {
|
enum eAuthImplementations {
|
||||||
AUTH_IMPL_PAM = 0,
|
AUTH_IMPL_PAM = 0,
|
||||||
AUTH_IMPL_FINGERPRINT = 1,
|
AUTH_IMPL_FINGERPRINT = 1,
|
||||||
|
@ -39,7 +40,7 @@ class CAuth {
|
||||||
std::optional<std::string> getPrompt(eAuthImplementations implType);
|
std::optional<std::string> getPrompt(eAuthImplementations implType);
|
||||||
size_t getFailedAttempts();
|
size_t getFailedAttempts();
|
||||||
|
|
||||||
std::shared_ptr<IAuthImplementation> getImpl(eAuthImplementations implType);
|
SP<IAuthImplementation> getImpl(eAuthImplementations implType);
|
||||||
|
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ class CAuth {
|
||||||
size_t failedAttempts = 0;
|
size_t failedAttempts = 0;
|
||||||
} m_sCurrentFail;
|
} m_sCurrentFail;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<IAuthImplementation>> m_vImpls;
|
std::vector<SP<IAuthImplementation>> m_vImpls;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CAuth> g_pAuth;
|
inline UP<CAuth> g_pAuth;
|
||||||
|
|
|
@ -27,7 +27,7 @@ class ICustomConfigValueData {
|
||||||
|
|
||||||
class CLayoutValueData : public ICustomConfigValueData {
|
class CLayoutValueData : public ICustomConfigValueData {
|
||||||
public:
|
public:
|
||||||
CLayoutValueData() {};
|
CLayoutValueData() = default;
|
||||||
virtual ~CLayoutValueData() {};
|
virtual ~CLayoutValueData() {};
|
||||||
|
|
||||||
virtual eConfigValueDataTypes getDataType() {
|
virtual eConfigValueDataTypes getDataType() {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include <hyprlang.hpp>
|
#include <hyprlang.hpp>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
@ -41,4 +40,4 @@ class CConfigManager {
|
||||||
Hyprlang::CConfig m_config;
|
Hyprlang::CConfig m_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CConfigManager> g_pConfigManager;
|
inline UP<CConfigManager> g_pConfigManager;
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
#include <hyprutils/animation/AnimatedVariable.hpp>
|
#include <hyprutils/animation/AnimatedVariable.hpp>
|
||||||
|
|
||||||
#include "../helpers/AnimatedVariable.hpp"
|
#include "../helpers/AnimatedVariable.hpp"
|
||||||
#include "../helpers/Math.hpp"
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
|
|
||||||
class CHyprlockAnimationManager : public Hyprutils::Animation::CAnimationManager {
|
class CHyprlockAnimationManager : public Hyprutils::Animation::CAnimationManager {
|
||||||
|
@ -31,4 +30,4 @@ class CHyprlockAnimationManager : public Hyprutils::Animation::CAnimationManager
|
||||||
bool m_bTickScheduled = false;
|
bool m_bTickScheduled = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CHyprlockAnimationManager> g_pAnimationManager;
|
inline UP<CHyprlockAnimationManager> g_pAnimationManager;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
|
#include "../defines.hpp"
|
||||||
|
|
||||||
class CEGL {
|
class CEGL {
|
||||||
public:
|
public:
|
||||||
CEGL(wl_display*);
|
CEGL(wl_display*);
|
||||||
|
@ -19,4 +19,4 @@ class CEGL {
|
||||||
void makeCurrent(EGLSurface surf);
|
void makeCurrent(EGLSurface surf);
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CEGL> g_pEGL;
|
inline UP<CEGL> g_pEGL;
|
||||||
|
|
|
@ -11,13 +11,9 @@ CSessionLockSurface::~CSessionLockSurface() {
|
||||||
wl_egl_window_destroy(eglWindow);
|
wl_egl_window_destroy(eglWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSessionLockSurface::CSessionLockSurface(COutput* output) : output(output) {
|
CSessionLockSurface::CSessionLockSurface(const SP<COutput>& pOutput) : m_outputRef(pOutput), m_outputID(pOutput->m_ID) {
|
||||||
surface = makeShared<CCWlSurface>(g_pHyprlock->getCompositor()->sendCreateSurface());
|
surface = makeShared<CCWlSurface>(g_pHyprlock->getCompositor()->sendCreateSurface());
|
||||||
|
RASSERT(surface, "Couldn't create wl_surface");
|
||||||
if (!surface) {
|
|
||||||
Debug::log(CRIT, "Couldn't create wl_surface");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const auto FRACTIONALSCALING = g_pConfigManager->getValue<Hyprlang::INT>("general:fractional_scaling");
|
static const auto FRACTIONALSCALING = g_pConfigManager->getValue<Hyprlang::INT>("general:fractional_scaling");
|
||||||
const auto ENABLE_FSV1 = *FRACTIONALSCALING == 1 || /* auto enable */ (*FRACTIONALSCALING == 2);
|
const auto ENABLE_FSV1 = *FRACTIONALSCALING == 1 || /* auto enable */ (*FRACTIONALSCALING == 2);
|
||||||
|
@ -45,7 +41,7 @@ CSessionLockSurface::CSessionLockSurface(COutput* output) : output(output) {
|
||||||
if (!PVIEWPORTER)
|
if (!PVIEWPORTER)
|
||||||
Debug::log(LOG, "No viewporter support! Oops, won't be able to scale!");
|
Debug::log(LOG, "No viewporter support! Oops, won't be able to scale!");
|
||||||
|
|
||||||
lockSurface = makeShared<CCExtSessionLockSurfaceV1>(g_pHyprlock->getSessionLock()->sendGetLockSurface(surface->resource(), output->output->resource()));
|
lockSurface = makeShared<CCExtSessionLockSurfaceV1>(g_pHyprlock->getSessionLock()->sendGetLockSurface(surface->resource(), pOutput->m_wlOutput->resource()));
|
||||||
|
|
||||||
if (!lockSurface) {
|
if (!lockSurface) {
|
||||||
Debug::log(CRIT, "Couldn't create ext_session_lock_surface_v1");
|
Debug::log(CRIT, "Couldn't create ext_session_lock_surface_v1");
|
||||||
|
@ -62,6 +58,8 @@ void CSessionLockSurface::configure(const Vector2D& size_, uint32_t serial_) {
|
||||||
const bool SAMESIZE = logicalSize == size_;
|
const bool SAMESIZE = logicalSize == size_;
|
||||||
const bool SAMESCALE = appliedScale == fractionalScale;
|
const bool SAMESCALE = appliedScale == fractionalScale;
|
||||||
|
|
||||||
|
const auto POUTPUT = m_outputRef.lock();
|
||||||
|
|
||||||
serial = serial_;
|
serial = serial_;
|
||||||
logicalSize = size_;
|
logicalSize = size_;
|
||||||
appliedScale = fractionalScale;
|
appliedScale = fractionalScale;
|
||||||
|
@ -71,8 +69,8 @@ void CSessionLockSurface::configure(const Vector2D& size_, uint32_t serial_) {
|
||||||
viewport->sendSetDestination(logicalSize.x, logicalSize.y);
|
viewport->sendSetDestination(logicalSize.x, logicalSize.y);
|
||||||
surface->sendSetBufferScale(1);
|
surface->sendSetBufferScale(1);
|
||||||
} else {
|
} else {
|
||||||
size = size_ * output->scale;
|
size = size_ * POUTPUT->scale;
|
||||||
surface->sendSetBufferScale(output->scale);
|
surface->sendSetBufferScale(POUTPUT->scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SAMESERIAL)
|
if (!SAMESERIAL)
|
||||||
|
@ -103,8 +101,8 @@ void CSessionLockSurface::configure(const Vector2D& size_, uint32_t serial_) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (readyForFrame && !(SAMESIZE && SAMESCALE)) {
|
if (readyForFrame && !(SAMESIZE && SAMESCALE)) {
|
||||||
g_pRenderer->removeWidgetsFor(this);
|
Debug::log(LOG, "output {} changed, reloading widgets!", POUTPUT->stringPort);
|
||||||
Debug::log(LOG, "Reloading widgets");
|
g_pRenderer->reconfigureWidgetsFor(POUTPUT->m_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
readyForFrame = true;
|
readyForFrame = true;
|
||||||
|
@ -129,7 +127,10 @@ void CSessionLockSurface::render() {
|
||||||
if (g_pHyprlock->m_bTerminate)
|
if (g_pHyprlock->m_bTerminate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug::log(TRACE, "[{}] frame {}, Current fps: {:.2f}", output->stringPort, m_frames, 1000.f / (frameTime - m_lastFrameTime));
|
if (Debug::verbose) {
|
||||||
|
const auto POUTPUT = m_outputRef.lock();
|
||||||
|
Debug::log(TRACE, "[{}] frame {}, Current fps: {:.2f}", POUTPUT->stringPort, m_frames, 1000.f / (frameTime - m_lastFrameTime));
|
||||||
|
}
|
||||||
|
|
||||||
m_lastFrameTime = frameTime;
|
m_lastFrameTime = frameTime;
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ class CRenderer;
|
||||||
|
|
||||||
class CSessionLockSurface {
|
class CSessionLockSurface {
|
||||||
public:
|
public:
|
||||||
CSessionLockSurface(COutput* output);
|
CSessionLockSurface(const SP<COutput>& pOutput);
|
||||||
~CSessionLockSurface();
|
~CSessionLockSurface();
|
||||||
|
|
||||||
void configure(const Vector2D& size, uint32_t serial);
|
void configure(const Vector2D& size, uint32_t serial);
|
||||||
|
@ -28,7 +28,9 @@ class CSessionLockSurface {
|
||||||
void onScaleUpdate();
|
void onScaleUpdate();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
COutput* output = nullptr;
|
WP<COutput> m_outputRef;
|
||||||
|
OUTPUTID m_outputID = OUTPUT_INVALID;
|
||||||
|
|
||||||
SP<CCWlSurface> surface = nullptr;
|
SP<CCWlSurface> surface = nullptr;
|
||||||
SP<CCExtSessionLockSurfaceV1> lockSurface = nullptr;
|
SP<CCExtSessionLockSurfaceV1> lockSurface = nullptr;
|
||||||
uint32_t serial = 0;
|
uint32_t serial = 0;
|
||||||
|
@ -49,4 +51,5 @@ class CSessionLockSurface {
|
||||||
SP<CCWlCallback> frameCallback = nullptr;
|
SP<CCWlCallback> frameCallback = nullptr;
|
||||||
|
|
||||||
friend class CRenderer;
|
friend class CRenderer;
|
||||||
|
friend class COutput;
|
||||||
};
|
};
|
|
@ -1,32 +1,35 @@
|
||||||
#include "Output.hpp"
|
#include "Output.hpp"
|
||||||
#include "../helpers/Log.hpp"
|
#include "../helpers/Log.hpp"
|
||||||
#include "hyprlock.hpp"
|
#include "hyprlock.hpp"
|
||||||
#include "../renderer/Renderer.hpp"
|
|
||||||
|
|
||||||
COutput::COutput(SP<CCWlOutput> output_, uint32_t name_) : name(name_), output(output_) {
|
void COutput::create(WP<COutput> pSelf, SP<CCWlOutput> pWlOutput, uint32_t _name) {
|
||||||
output->setDescription([this](CCWlOutput* r, const char* description) {
|
m_ID = _name;
|
||||||
|
m_wlOutput = pWlOutput;
|
||||||
|
m_self = pSelf;
|
||||||
|
|
||||||
|
m_wlOutput->setDescription([this](CCWlOutput* r, const char* description) {
|
||||||
stringDesc = description ? std::string{description} : "";
|
stringDesc = description ? std::string{description} : "";
|
||||||
Debug::log(LOG, "output {} description {}", name, stringDesc);
|
Debug::log(LOG, "output {} description {}", m_ID, stringDesc);
|
||||||
});
|
});
|
||||||
|
|
||||||
output->setName([this](CCWlOutput* r, const char* name) {
|
m_wlOutput->setName([this](CCWlOutput* r, const char* name) {
|
||||||
stringName = std::string{name} + stringName;
|
stringName = std::string{name} + stringName;
|
||||||
stringPort = std::string{name};
|
stringPort = std::string{name};
|
||||||
Debug::log(LOG, "output {} name {}", name, name);
|
Debug::log(LOG, "output {} name {}", name, name);
|
||||||
});
|
});
|
||||||
|
|
||||||
output->setScale([this](CCWlOutput* r, int32_t sc) { scale = sc; });
|
m_wlOutput->setScale([this](CCWlOutput* r, int32_t sc) { scale = sc; });
|
||||||
|
|
||||||
output->setDone([this](CCWlOutput* r) {
|
m_wlOutput->setDone([this](CCWlOutput* r) {
|
||||||
done = true;
|
done = true;
|
||||||
Debug::log(LOG, "output {} done", name);
|
Debug::log(LOG, "output {} done", m_ID);
|
||||||
if (g_pHyprlock->m_lockAquired && !sessionLockSurface) {
|
if (g_pHyprlock->m_lockAquired && !m_sessionLockSurface) {
|
||||||
Debug::log(LOG, "output {} creating a new lock surface", name);
|
Debug::log(LOG, "output {} creating a new lock surface", m_ID);
|
||||||
sessionLockSurface = std::make_unique<CSessionLockSurface>(this);
|
createSessionLockSurface();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
output->setMode([this](CCWlOutput* r, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
|
m_wlOutput->setMode([this](CCWlOutput* r, uint32_t flags, int32_t width, int32_t height, int32_t refresh) {
|
||||||
// handle portrait mode and flipped cases
|
// handle portrait mode and flipped cases
|
||||||
if (transform % 2 == 1)
|
if (transform % 2 == 1)
|
||||||
size = {height, width};
|
size = {height, width};
|
||||||
|
@ -34,10 +37,18 @@ COutput::COutput(SP<CCWlOutput> output_, uint32_t name_) : name(name_), output(o
|
||||||
size = {width, height};
|
size = {width, height};
|
||||||
});
|
});
|
||||||
|
|
||||||
output->setGeometry(
|
m_wlOutput->setGeometry(
|
||||||
[this](CCWlOutput* r, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform_) {
|
[this](CCWlOutput* r, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform_) {
|
||||||
transform = (wl_output_transform)transform_;
|
transform = (wl_output_transform)transform_;
|
||||||
|
|
||||||
Debug::log(LOG, "output {} make {} model {}", name, make ? make : "", model ? model : "");
|
Debug::log(LOG, "output {} make {} model {}", m_ID, make ? make : "", model ? model : "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void COutput::createSessionLockSurface() {
|
||||||
|
m_sessionLockSurface = makeUnique<CSessionLockSurface>(m_self.lock());
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector2D COutput::getViewport() const {
|
||||||
|
return (m_sessionLockSurface) ? m_sessionLockSurface->size : size;
|
||||||
|
}
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
|
|
||||||
#include "../defines.hpp"
|
#include "../defines.hpp"
|
||||||
#include "wayland.hpp"
|
#include "wayland.hpp"
|
||||||
#include "../helpers/Math.hpp"
|
|
||||||
#include "LockSurface.hpp"
|
#include "LockSurface.hpp"
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class COutput {
|
class COutput {
|
||||||
public:
|
public:
|
||||||
COutput(SP<CCWlOutput> output, uint32_t name);
|
COutput() = default;
|
||||||
|
~COutput() = default;
|
||||||
|
|
||||||
uint32_t name = 0;
|
void create(WP<COutput> pSelf, SP<CCWlOutput> pWlOutput, uint32_t name);
|
||||||
|
|
||||||
|
OUTPUTID m_ID = 0;
|
||||||
bool focused = false;
|
bool focused = false;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL;
|
||||||
|
@ -20,9 +21,13 @@ class COutput {
|
||||||
std::string stringPort = "";
|
std::string stringPort = "";
|
||||||
std::string stringDesc = "";
|
std::string stringDesc = "";
|
||||||
|
|
||||||
std::unique_ptr<CSessionLockSurface> sessionLockSurface;
|
UP<CSessionLockSurface> m_sessionLockSurface;
|
||||||
|
|
||||||
SP<CCWlOutput> output = nullptr;
|
SP<CCWlOutput> m_wlOutput = nullptr;
|
||||||
|
|
||||||
private:
|
WP<COutput> m_self;
|
||||||
|
|
||||||
|
void createSessionLockSurface();
|
||||||
|
|
||||||
|
Vector2D getViewport() const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -131,7 +131,7 @@ void CSeatManager::registerSeat(SP<CCWlSeat> seat) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSeatManager::registerCursorShape(SP<CCWpCursorShapeManagerV1> shape) {
|
void CSeatManager::registerCursorShape(SP<CCWpCursorShapeManagerV1> shape) {
|
||||||
m_pCursorShape = std::make_unique<CCursorShape>(shape);
|
m_pCursorShape = makeUnique<CCursorShape>(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSeatManager::registered() {
|
bool CSeatManager::registered() {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "wayland.hpp"
|
#include "wayland.hpp"
|
||||||
#include <xkbcommon/xkbcommon.h>
|
#include <xkbcommon/xkbcommon.h>
|
||||||
#include <xkbcommon/xkbcommon-compose.h>
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class CSeatManager {
|
class CSeatManager {
|
||||||
public:
|
public:
|
||||||
|
@ -19,7 +18,7 @@ class CSeatManager {
|
||||||
SP<CCWlKeyboard> m_pKeeb;
|
SP<CCWlKeyboard> m_pKeeb;
|
||||||
SP<CCWlPointer> m_pPointer;
|
SP<CCWlPointer> m_pPointer;
|
||||||
|
|
||||||
std::unique_ptr<CCursorShape> m_pCursorShape;
|
UP<CCursorShape> m_pCursorShape;
|
||||||
|
|
||||||
xkb_context* m_pXKBContext = nullptr;
|
xkb_context* m_pXKBContext = nullptr;
|
||||||
xkb_keymap* m_pXKBKeymap = nullptr;
|
xkb_keymap* m_pXKBKeymap = nullptr;
|
||||||
|
@ -30,4 +29,4 @@ class CSeatManager {
|
||||||
SP<CCWlSeat> m_pSeat;
|
SP<CCWlSeat> m_pSeat;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CSeatManager> g_pSeatManager = std::make_unique<CSeatManager>();
|
inline UP<CSeatManager> g_pSeatManager = makeUnique<CSeatManager>();
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../auth/Auth.hpp"
|
#include "../auth/Auth.hpp"
|
||||||
#include "../auth/Fingerprint.hpp"
|
#include "../auth/Fingerprint.hpp"
|
||||||
#include "Egl.hpp"
|
#include "Egl.hpp"
|
||||||
|
#include <hyprutils/memory/UniquePtr.hpp>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
@ -43,7 +44,7 @@ CHyprlock::CHyprlock(const std::string& wlDisplay, const bool immediate, const b
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pEGL = std::make_unique<CEGL>(m_sWaylandState.display);
|
g_pEGL = makeUnique<CEGL>(m_sWaylandState.display);
|
||||||
|
|
||||||
if (!immediate) {
|
if (!immediate) {
|
||||||
static const auto GRACE = g_pConfigManager->getValue<Hyprlang::INT>("general:grace");
|
static const auto GRACE = g_pConfigManager->getValue<Hyprlang::INT>("general:grace");
|
||||||
|
@ -283,10 +284,10 @@ void CHyprlock::run() {
|
||||||
} else if (IFACE == ext_session_lock_manager_v1_interface.name)
|
} else if (IFACE == ext_session_lock_manager_v1_interface.name)
|
||||||
m_sWaylandState.sessionLock =
|
m_sWaylandState.sessionLock =
|
||||||
makeShared<CCExtSessionLockManagerV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &ext_session_lock_manager_v1_interface, 1));
|
makeShared<CCExtSessionLockManagerV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &ext_session_lock_manager_v1_interface, 1));
|
||||||
else if (IFACE == wl_output_interface.name)
|
else if (IFACE == wl_output_interface.name) {
|
||||||
m_vOutputs.emplace_back(
|
m_vOutputs.emplace_back(makeShared<COutput>());
|
||||||
std::make_unique<COutput>(makeShared<CCWlOutput>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wl_output_interface, 4)), name));
|
m_vOutputs.back()->create(m_vOutputs.back(), makeShared<CCWlOutput>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wl_output_interface, 4)), name);
|
||||||
else if (IFACE == wp_cursor_shape_manager_v1_interface.name)
|
} else if (IFACE == wp_cursor_shape_manager_v1_interface.name)
|
||||||
g_pSeatManager->registerCursorShape(
|
g_pSeatManager->registerCursorShape(
|
||||||
makeShared<CCWpCursorShapeManagerV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wp_cursor_shape_manager_v1_interface, 1)));
|
makeShared<CCWpCursorShapeManagerV1>((wl_proxy*)wl_registry_bind((wl_registry*)r->resource(), name, &wp_cursor_shape_manager_v1_interface, 1)));
|
||||||
else if (IFACE == wl_compositor_interface.name)
|
else if (IFACE == wl_compositor_interface.name)
|
||||||
|
@ -308,9 +309,9 @@ void CHyprlock::run() {
|
||||||
});
|
});
|
||||||
m_sWaylandState.registry->setGlobalRemove([this](CCWlRegistry* r, uint32_t name) {
|
m_sWaylandState.registry->setGlobalRemove([this](CCWlRegistry* r, uint32_t name) {
|
||||||
Debug::log(LOG, " | removed iface {}", name);
|
Debug::log(LOG, " | removed iface {}", name);
|
||||||
auto outputIt = std::ranges::find_if(m_vOutputs, [name](const auto& other) { return other->name == name; });
|
auto outputIt = std::ranges::find_if(m_vOutputs, [id = name](const auto& other) { return other->m_ID == id; });
|
||||||
if (outputIt != m_vOutputs.end()) {
|
if (outputIt != m_vOutputs.end()) {
|
||||||
g_pRenderer->removeWidgetsFor(outputIt->get()->sessionLockSurface.get());
|
g_pRenderer->removeWidgetsFor((*outputIt)->m_ID);
|
||||||
m_vOutputs.erase(outputIt);
|
m_vOutputs.erase(outputIt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -325,8 +326,8 @@ void CHyprlock::run() {
|
||||||
// gather info about monitors
|
// gather info about monitors
|
||||||
wl_display_roundtrip(m_sWaylandState.display);
|
wl_display_roundtrip(m_sWaylandState.display);
|
||||||
|
|
||||||
g_pRenderer = std::make_unique<CRenderer>();
|
g_pRenderer = makeUnique<CRenderer>();
|
||||||
g_pAuth = std::make_unique<CAuth>();
|
g_pAuth = makeUnique<CAuth>();
|
||||||
g_pAuth->start();
|
g_pAuth->start();
|
||||||
|
|
||||||
Debug::log(LOG, "Running on {}", m_sCurrentDesktop);
|
Debug::log(LOG, "Running on {}", m_sCurrentDesktop);
|
||||||
|
@ -554,23 +555,23 @@ void CHyprlock::clearPasswordBuffer() {
|
||||||
void CHyprlock::renderOutput(const std::string& stringPort) {
|
void CHyprlock::renderOutput(const std::string& stringPort) {
|
||||||
const auto MON = std::ranges::find_if(m_vOutputs, [stringPort](const auto& other) { return other->stringPort == stringPort; });
|
const auto MON = std::ranges::find_if(m_vOutputs, [stringPort](const auto& other) { return other->stringPort == stringPort; });
|
||||||
|
|
||||||
if (MON == m_vOutputs.end() || !MON->get())
|
if (MON == m_vOutputs.end() || !*MON)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const auto PMONITOR = MON->get();
|
const auto& PMONITOR = *MON;
|
||||||
|
|
||||||
if (!PMONITOR->sessionLockSurface)
|
if (!PMONITOR->m_sessionLockSurface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PMONITOR->sessionLockSurface->render();
|
PMONITOR->m_sessionLockSurface->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHyprlock::renderAllOutputs() {
|
void CHyprlock::renderAllOutputs() {
|
||||||
for (auto& o : m_vOutputs) {
|
for (auto& o : m_vOutputs) {
|
||||||
if (!o->sessionLockSurface)
|
if (!o->m_sessionLockSurface)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
o->sessionLockSurface->render();
|
o->m_sessionLockSurface->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,7 +724,7 @@ bool CHyprlock::acquireSessionLock() {
|
||||||
if (!o->done)
|
if (!o->done)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
o->sessionLockSurface = std::make_unique<CSessionLockSurface>(o.get());
|
o->createSessionLockSurface();
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -37,9 +37,6 @@ class CHyprlock {
|
||||||
void unlock();
|
void unlock();
|
||||||
bool isUnlocked();
|
bool isUnlocked();
|
||||||
|
|
||||||
void onGlobal(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version);
|
|
||||||
void onGlobalRemoved(void* data, struct wl_registry* registry, uint32_t name);
|
|
||||||
|
|
||||||
std::shared_ptr<CTimer> addTimer(const std::chrono::system_clock::duration& timeout, std::function<void(std::shared_ptr<CTimer> self, void* data)> cb_, void* data,
|
std::shared_ptr<CTimer> addTimer(const std::chrono::system_clock::duration& timeout, std::function<void(std::shared_ptr<CTimer> self, void* data)> cb_, void* data,
|
||||||
bool force = false);
|
bool force = false);
|
||||||
|
|
||||||
|
@ -103,7 +100,7 @@ class CHyprlock {
|
||||||
|
|
||||||
std::shared_ptr<CTimer> m_pKeyRepeatTimer = nullptr;
|
std::shared_ptr<CTimer> m_pKeyRepeatTimer = nullptr;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<COutput>> m_vOutputs;
|
std::vector<SP<COutput>> m_vOutputs;
|
||||||
std::vector<std::shared_ptr<CTimer>> getTimers();
|
std::vector<std::shared_ptr<CTimer>> getTimers();
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -167,4 +164,4 @@ class CHyprlock {
|
||||||
std::vector<uint32_t> m_vPressedKeys;
|
std::vector<uint32_t> m_vPressedKeys;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CHyprlock> g_pHyprlock;
|
inline UP<CHyprlock> g_pHyprlock;
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <hyprutils/memory/WeakPtr.hpp>
|
#include <hyprutils/memory/WeakPtr.hpp>
|
||||||
|
#include <hyprutils/memory/UniquePtr.hpp>
|
||||||
#include <hyprgraphics/color/Color.hpp>
|
#include <hyprgraphics/color/Color.hpp>
|
||||||
|
|
||||||
using namespace Hyprutils::Memory;
|
using namespace Hyprutils::Memory;
|
||||||
using namespace Hyprgraphics;
|
using namespace Hyprgraphics;
|
||||||
#define SP CSharedPointer
|
#define SP CSharedPointer
|
||||||
#define WP CWeakPointer
|
#define WP CWeakPointer
|
||||||
|
#define UP CUniquePointer
|
||||||
|
|
||||||
|
typedef int64_t OUTPUTID;
|
||||||
|
constexpr OUTPUTID OUTPUT_INVALID = -1;
|
||||||
|
|
|
@ -90,10 +90,10 @@ int main(int argc, char** argv, char** envp) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pAnimationManager = std::make_unique<CHyprlockAnimationManager>();
|
g_pAnimationManager = makeUnique<CHyprlockAnimationManager>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
g_pConfigManager = std::make_unique<CConfigManager>(configPath);
|
g_pConfigManager = makeUnique<CConfigManager>(configPath);
|
||||||
g_pConfigManager->init();
|
g_pConfigManager->init();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
Debug::log(CRIT, "ConfigManager threw: {}", ex.what());
|
Debug::log(CRIT, "ConfigManager threw: {}", ex.what());
|
||||||
|
@ -107,7 +107,7 @@ int main(int argc, char** argv, char** envp) {
|
||||||
g_pConfigManager->m_AnimationTree.setConfigForNode("fadeIn", false, 0.f, "default");
|
g_pConfigManager->m_AnimationTree.setConfigForNode("fadeIn", false, 0.f, "default");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
g_pHyprlock = std::make_unique<CHyprlock>(wlDisplay, immediate, immediateRender);
|
g_pHyprlock = makeUnique<CHyprlock>(wlDisplay, immediate, immediateRender);
|
||||||
g_pHyprlock->run();
|
g_pHyprlock->run();
|
||||||
} catch (const std::exception& ex) {
|
} catch (const std::exception& ex) {
|
||||||
Debug::log(CRIT, "Hyprlock threw: {}", ex.what());
|
Debug::log(CRIT, "Hyprlock threw: {}", ex.what());
|
||||||
|
|
|
@ -48,15 +48,12 @@ void CAsyncResourceGatherer::enqueueScreencopyFrames() {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& mon : mons) {
|
for (auto& mon : mons) {
|
||||||
const auto MON = std::find_if(g_pHyprlock->m_vOutputs.begin(), g_pHyprlock->m_vOutputs.end(),
|
const auto MON = std::ranges::find_if(g_pHyprlock->m_vOutputs, [mon](const auto& other) { return other->stringPort == mon || other->stringDesc.starts_with(mon); });
|
||||||
[mon](const auto& other) { return other->stringPort == mon || other->stringDesc.starts_with(mon); });
|
|
||||||
|
|
||||||
if (MON == g_pHyprlock->m_vOutputs.end())
|
if (MON == g_pHyprlock->m_vOutputs.end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const auto PMONITOR = MON->get();
|
scframes.emplace_back(makeUnique<CScreencopyFrame>(*MON));
|
||||||
|
|
||||||
scframes.emplace_back(std::make_unique<CScreencopyFrame>(PMONITOR));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,17 +301,6 @@ void CAsyncResourceGatherer::renderText(const SPreloadRequest& rq) {
|
||||||
preloadTargets.push_back(target);
|
preloadTargets.push_back(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct STimerCallbackData {
|
|
||||||
void (*cb)(void*) = nullptr;
|
|
||||||
void* data = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void timerCallback(std::shared_ptr<CTimer> self, void* data_) {
|
|
||||||
auto data = (STimerCallbackData*)data_;
|
|
||||||
data->cb(data->data);
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAsyncResourceGatherer::asyncAssetSpinLock() {
|
void CAsyncResourceGatherer::asyncAssetSpinLock() {
|
||||||
while (!g_pHyprlock->m_bTerminate) {
|
while (!g_pHyprlock->m_bTerminate) {
|
||||||
|
|
||||||
|
@ -349,7 +335,7 @@ void CAsyncResourceGatherer::asyncAssetSpinLock() {
|
||||||
|
|
||||||
// plant timer for callback
|
// plant timer for callback
|
||||||
if (r.callback)
|
if (r.callback)
|
||||||
g_pHyprlock->addTimer(std::chrono::milliseconds(0), timerCallback, new STimerCallbackData{.cb = r.callback, .data = r.callbackData});
|
g_pHyprlock->addTimer(std::chrono::milliseconds(0), [cb = r.callback](auto, auto) { cb(); }, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,8 +37,7 @@ class CAsyncResourceGatherer {
|
||||||
// optional. Callbacks will be dispatched from the main thread,
|
// optional. Callbacks will be dispatched from the main thread,
|
||||||
// so wayland/gl calls are OK.
|
// so wayland/gl calls are OK.
|
||||||
// will fire once the resource is fully loaded and ready.
|
// will fire once the resource is fully loaded and ready.
|
||||||
void (*callback)(void*) = nullptr;
|
std::function<void()> callback = nullptr;
|
||||||
void* callbackData = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void requestAsyncAssetPreload(const SPreloadRequest& request);
|
void requestAsyncAssetPreload(const SPreloadRequest& request);
|
||||||
|
@ -75,7 +74,7 @@ class CAsyncResourceGatherer {
|
||||||
Vector2D size;
|
Vector2D size;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::unique_ptr<CScreencopyFrame>> scframes;
|
std::vector<UP<CScreencopyFrame>> scframes;
|
||||||
|
|
||||||
std::vector<SPreloadTarget> preloadTargets;
|
std::vector<SPreloadTarget> preloadTargets;
|
||||||
std::mutex preloadTargetsMutex;
|
std::mutex preloadTargetsMutex;
|
||||||
|
|
|
@ -194,7 +194,7 @@ CRenderer::CRenderer() {
|
||||||
borderShader.gradientLerp = glGetUniformLocation(prog, "gradientLerp");
|
borderShader.gradientLerp = glGetUniformLocation(prog, "gradientLerp");
|
||||||
borderShader.alpha = glGetUniformLocation(prog, "alpha");
|
borderShader.alpha = glGetUniformLocation(prog, "alpha");
|
||||||
|
|
||||||
asyncResourceGatherer = std::make_unique<CAsyncResourceGatherer>();
|
asyncResourceGatherer = makeUnique<CAsyncResourceGatherer>();
|
||||||
|
|
||||||
g_pAnimationManager->createAnimation(0.f, opacity, g_pConfigManager->m_AnimationTree.getConfig("fadeIn"));
|
g_pAnimationManager->createAnimation(0.f, opacity, g_pConfigManager->m_AnimationTree.getConfig("fadeIn"));
|
||||||
}
|
}
|
||||||
|
@ -231,8 +231,8 @@ CRenderer::SRenderFeedback CRenderer::renderLock(const CSessionLockSurface& surf
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// render widgets
|
// render widgets
|
||||||
const auto WIDGETS = getOrCreateWidgetsFor(&surf);
|
const auto WIDGETS = getOrCreateWidgetsFor(surf);
|
||||||
for (auto& w : *WIDGETS) {
|
for (auto& w : WIDGETS) {
|
||||||
feedback.needsFrame = w->draw({opacity->value()}) || feedback.needsFrame;
|
feedback.needsFrame = w->draw({opacity->value()}) || feedback.needsFrame;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -397,62 +397,49 @@ void CRenderer::renderTextureMix(const CBox& box, const CTexture& tex, const CTe
|
||||||
glBindTexture(tex.m_iTarget, 0);
|
glBindTexture(tex.m_iTarget, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<IWidget>>* CRenderer::getOrCreateWidgetsFor(const CSessionLockSurface* surf) {
|
template <class Widget>
|
||||||
if (!widgets.contains(surf)) {
|
static void createWidget(std::vector<SP<IWidget>>& widgets) {
|
||||||
|
const auto W = makeShared<Widget>();
|
||||||
|
W->registerSelf(W);
|
||||||
|
widgets.emplace_back(W);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SP<IWidget>>& CRenderer::getOrCreateWidgetsFor(const CSessionLockSurface& surf) {
|
||||||
|
RASSERT(surf.m_outputID != OUTPUT_INVALID, "Invalid output ID!");
|
||||||
|
|
||||||
|
if (!widgets.contains(surf.m_outputID)) {
|
||||||
auto CWIDGETS = g_pConfigManager->getWidgetConfigs();
|
auto CWIDGETS = g_pConfigManager->getWidgetConfigs();
|
||||||
|
|
||||||
std::ranges::sort(CWIDGETS, [](CConfigManager::SWidgetConfig& a, CConfigManager::SWidgetConfig& b) {
|
std::ranges::sort(CWIDGETS, [](CConfigManager::SWidgetConfig& a, CConfigManager::SWidgetConfig& b) {
|
||||||
return std::any_cast<Hyprlang::INT>(a.values.at("zindex")) < std::any_cast<Hyprlang::INT>(b.values.at("zindex"));
|
return std::any_cast<Hyprlang::INT>(a.values.at("zindex")) < std::any_cast<Hyprlang::INT>(b.values.at("zindex"));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const auto POUTPUT = surf.m_outputRef.lock();
|
||||||
for (auto& c : CWIDGETS) {
|
for (auto& c : CWIDGETS) {
|
||||||
if (!c.monitor.empty() && c.monitor != surf->output->stringPort && !surf->output->stringDesc.starts_with(c.monitor) &&
|
if (!c.monitor.empty() && c.monitor != POUTPUT->stringPort && !POUTPUT->stringDesc.starts_with(c.monitor) && !POUTPUT->stringDesc.starts_with("desc:" + c.monitor))
|
||||||
!surf->output->stringDesc.starts_with("desc:" + c.monitor))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// by type
|
// by type
|
||||||
if (c.type == "background") {
|
if (c.type == "background") {
|
||||||
const std::string PATH = std::any_cast<Hyprlang::STRING>(c.values.at("path"));
|
createWidget<CBackground>(widgets[surf.m_outputID]);
|
||||||
|
|
||||||
std::string resourceID = "";
|
|
||||||
if (PATH == "screenshot") {
|
|
||||||
resourceID = CScreencopyFrame::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->gathered) {
|
|
||||||
if (!asyncResourceGatherer->getAssetByID(resourceID))
|
|
||||||
resourceID = ""; // Fallback to solid color (background:color)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!g_pHyprlock->getScreencopy()) {
|
|
||||||
Debug::log(ERR, "No screencopy support! path=screenshot won't work. Falling back to background color.");
|
|
||||||
resourceID = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (!PATH.empty())
|
|
||||||
resourceID = "background:" + PATH;
|
|
||||||
|
|
||||||
widgets[surf].emplace_back(std::make_unique<CBackground>(surf->size, surf->output, resourceID, c.values, PATH == "screenshot"));
|
|
||||||
} else if (c.type == "input-field") {
|
} else if (c.type == "input-field") {
|
||||||
widgets[surf].emplace_back(std::make_unique<CPasswordInputField>(surf->size, c.values, surf->output->stringPort));
|
createWidget<CPasswordInputField>(widgets[surf.m_outputID]);
|
||||||
} else if (c.type == "label") {
|
} else if (c.type == "label") {
|
||||||
widgets[surf].emplace_back(std::make_unique<CLabel>(surf->size, c.values, surf->output->stringPort));
|
createWidget<CLabel>(widgets[surf.m_outputID]);
|
||||||
} else if (c.type == "shape") {
|
} else if (c.type == "shape") {
|
||||||
widgets[surf].emplace_back(std::make_unique<CShape>(surf->size, c.values));
|
createWidget<CShape>(widgets[surf.m_outputID]);
|
||||||
} else if (c.type == "image") {
|
} else if (c.type == "image") {
|
||||||
const std::string PATH = std::any_cast<Hyprlang::STRING>(c.values.at("path"));
|
createWidget<CImage>(widgets[surf.m_outputID]);
|
||||||
|
} else {
|
||||||
std::string resourceID = "";
|
Debug::log(ERR, "Unknown widget type: {}", c.type);
|
||||||
if (!PATH.empty())
|
continue;
|
||||||
resourceID = "image:" + PATH;
|
|
||||||
|
|
||||||
widgets[surf].emplace_back(std::make_unique<CImage>(surf->size, surf->output, resourceID, c.values));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
widgets[surf.m_outputID].back()->configure(c.values, POUTPUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &widgets[surf];
|
return widgets[surf.m_outputID];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderer::blurFB(const CFramebuffer& outfb, SBlurParams params) {
|
void CRenderer::blurFB(const CFramebuffer& outfb, SBlurParams params) {
|
||||||
|
@ -618,8 +605,15 @@ void CRenderer::popFb() {
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundFBs.empty() ? 0 : boundFBs.back());
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, boundFBs.empty() ? 0 : boundFBs.back());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderer::removeWidgetsFor(const CSessionLockSurface* surf) {
|
void CRenderer::removeWidgetsFor(OUTPUTID id) {
|
||||||
widgets.erase(surf);
|
widgets.erase(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRenderer::reconfigureWidgetsFor(OUTPUTID id) {
|
||||||
|
// TODO: reconfigure widgets by just calling their configure method again.
|
||||||
|
// Requires a way to get a widgets config properties.
|
||||||
|
// I think the best way would be to store the anonymos key of the widget config.
|
||||||
|
removeWidgetsFor(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRenderer::startFadeIn() {
|
void CRenderer::startFadeIn() {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include "Shader.hpp"
|
#include "Shader.hpp"
|
||||||
|
#include "../defines.hpp"
|
||||||
#include "../core/LockSurface.hpp"
|
#include "../core/LockSurface.hpp"
|
||||||
#include "../helpers/AnimatedVariable.hpp"
|
#include "../helpers/AnimatedVariable.hpp"
|
||||||
#include "../helpers/Color.hpp"
|
#include "../helpers/Color.hpp"
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
#include "widgets/IWidget.hpp"
|
#include "widgets/IWidget.hpp"
|
||||||
#include "Framebuffer.hpp"
|
#include "Framebuffer.hpp"
|
||||||
|
|
||||||
typedef std::unordered_map<const CSessionLockSurface*, std::vector<std::unique_ptr<IWidget>>> widgetMap_t;
|
typedef std::unordered_map<OUTPUTID, std::vector<SP<IWidget>>> widgetMap_t;
|
||||||
|
|
||||||
class CRenderer {
|
class CRenderer {
|
||||||
public:
|
public:
|
||||||
|
@ -29,7 +29,7 @@ class CRenderer {
|
||||||
float boostA = 1.0;
|
float boostA = 1.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
SRenderFeedback renderLock(const CSessionLockSurface& surface);
|
SRenderFeedback renderLock(const CSessionLockSurface& surf);
|
||||||
|
|
||||||
void renderRect(const CBox& box, const CHyprColor& col, int rounding = 0);
|
void renderRect(const CBox& box, const CHyprColor& col, int rounding = 0);
|
||||||
void renderBorder(const CBox& box, const CGradientValueData& gradient, int thickness, int rounding = 0, float alpha = 1.0);
|
void renderBorder(const CBox& box, const CGradientValueData& gradient, int thickness, int rounding = 0, float alpha = 1.0);
|
||||||
|
@ -37,13 +37,14 @@ class CRenderer {
|
||||||
void renderTextureMix(const CBox& box, const CTexture& tex, const CTexture& tex2, float a = 1.0, float mixFactor = 0.0, int rounding = 0, std::optional<eTransform> tr = {});
|
void renderTextureMix(const CBox& box, const CTexture& tex, const CTexture& tex2, float a = 1.0, float mixFactor = 0.0, int rounding = 0, std::optional<eTransform> tr = {});
|
||||||
void blurFB(const CFramebuffer& outfb, SBlurParams params);
|
void blurFB(const CFramebuffer& outfb, SBlurParams params);
|
||||||
|
|
||||||
std::unique_ptr<CAsyncResourceGatherer> asyncResourceGatherer;
|
UP<CAsyncResourceGatherer> asyncResourceGatherer;
|
||||||
std::chrono::system_clock::time_point firstFullFrameTime;
|
std::chrono::system_clock::time_point firstFullFrameTime;
|
||||||
|
|
||||||
void pushFb(GLint fb);
|
void pushFb(GLint fb);
|
||||||
void popFb();
|
void popFb();
|
||||||
|
|
||||||
void removeWidgetsFor(const CSessionLockSurface* surf);
|
void removeWidgetsFor(OUTPUTID id);
|
||||||
|
void reconfigureWidgetsFor(OUTPUTID id);
|
||||||
|
|
||||||
void startFadeIn();
|
void startFadeIn();
|
||||||
void startFadeOut(bool unlock = false, bool immediate = true);
|
void startFadeOut(bool unlock = false, bool immediate = true);
|
||||||
|
@ -51,7 +52,7 @@ class CRenderer {
|
||||||
private:
|
private:
|
||||||
widgetMap_t widgets;
|
widgetMap_t widgets;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<IWidget>>* getOrCreateWidgetsFor(const CSessionLockSurface* surf);
|
std::vector<SP<IWidget>>& getOrCreateWidgetsFor(const CSessionLockSurface& surf);
|
||||||
|
|
||||||
CShader rectShader;
|
CShader rectShader;
|
||||||
CShader texShader;
|
CShader texShader;
|
||||||
|
@ -70,4 +71,4 @@ class CRenderer {
|
||||||
std::vector<GLint> boundFBs;
|
std::vector<GLint> boundFBs;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::unique_ptr<CRenderer> g_pRenderer;
|
inline UP<CRenderer> g_pRenderer;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
|
#include <hyprutils/memory/UniquePtr.hpp>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <libdrm/drm_fourcc.h>
|
#include <libdrm/drm_fourcc.h>
|
||||||
|
@ -22,24 +23,27 @@ static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = nullpt
|
||||||
static PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
|
static PFNEGLQUERYDMABUFMODIFIERSEXTPROC eglQueryDmaBufModifiersEXT = nullptr;
|
||||||
|
|
||||||
//
|
//
|
||||||
std::string CScreencopyFrame::getResourceId(COutput* output) {
|
std::string CScreencopyFrame::getResourceId(SP<COutput> pOutput) {
|
||||||
return std::format("screencopy:{}-{}x{}", output->stringPort, output->size.x, output->size.y);
|
return std::format("screencopy:{}-{}x{}", pOutput->stringPort, pOutput->size.x, pOutput->size.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
CScreencopyFrame::CScreencopyFrame(COutput* output) : m_output(output) {
|
CScreencopyFrame::CScreencopyFrame(SP<COutput> pOutput) : m_outputRef(pOutput) {
|
||||||
m_resourceID = getResourceId(m_output);
|
|
||||||
|
|
||||||
captureOutput();
|
captureOutput();
|
||||||
|
|
||||||
static const auto SCMODE = g_pConfigManager->getValue<Hyprlang::INT>("general:screencopy_mode");
|
static const auto SCMODE = g_pConfigManager->getValue<Hyprlang::INT>("general:screencopy_mode");
|
||||||
if (*SCMODE == 1)
|
if (*SCMODE == 1)
|
||||||
m_frame = std::make_unique<CSCSHMFrame>(m_sc);
|
m_frame = makeUnique<CSCSHMFrame>(m_sc);
|
||||||
else
|
else
|
||||||
m_frame = std::make_unique<CSCDMAFrame>(m_sc);
|
m_frame = makeUnique<CSCDMAFrame>(m_sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CScreencopyFrame::captureOutput() {
|
void CScreencopyFrame::captureOutput() {
|
||||||
m_sc = makeShared<CCZwlrScreencopyFrameV1>(g_pHyprlock->getScreencopy()->sendCaptureOutput(false, m_output->output->resource()));
|
const auto POUTPUT = m_outputRef.lock();
|
||||||
|
RASSERT(POUTPUT, "Screencopy, but no valid output");
|
||||||
|
|
||||||
|
m_resourceID = getResourceId(POUTPUT);
|
||||||
|
|
||||||
|
m_sc = makeShared<CCZwlrScreencopyFrameV1>(g_pHyprlock->getScreencopy()->sendCaptureOutput(false, POUTPUT->m_wlOutput->resource()));
|
||||||
|
|
||||||
m_sc->setBufferDone([this](CCZwlrScreencopyFrameV1* r) {
|
m_sc->setBufferDone([this](CCZwlrScreencopyFrameV1* r) {
|
||||||
Debug::log(TRACE, "[sc] wlrOnBufferDone for {}", (void*)this);
|
Debug::log(TRACE, "[sc] wlrOnBufferDone for {}", (void*)this);
|
||||||
|
|
|
@ -22,9 +22,9 @@ class ISCFrame {
|
||||||
|
|
||||||
class CScreencopyFrame {
|
class CScreencopyFrame {
|
||||||
public:
|
public:
|
||||||
static std::string getResourceId(COutput* output);
|
static std::string getResourceId(SP<COutput> pOutput);
|
||||||
|
|
||||||
CScreencopyFrame(COutput* mon);
|
CScreencopyFrame(SP<COutput> pOutput);
|
||||||
~CScreencopyFrame() = default;
|
~CScreencopyFrame() = default;
|
||||||
|
|
||||||
void captureOutput();
|
void captureOutput();
|
||||||
|
@ -35,8 +35,8 @@ class CScreencopyFrame {
|
||||||
SPreloadedAsset m_asset;
|
SPreloadedAsset m_asset;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
COutput* m_output = nullptr;
|
WP<COutput> m_outputRef;
|
||||||
std::unique_ptr<ISCFrame> m_frame = nullptr;
|
UP<ISCFrame> m_frame = nullptr;
|
||||||
|
|
||||||
bool m_dmaFailed = false;
|
bool m_dmaFailed = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,23 +10,15 @@
|
||||||
#include <GLES3/gl32.h>
|
#include <GLES3/gl32.h>
|
||||||
|
|
||||||
CBackground::~CBackground() {
|
CBackground::~CBackground() {
|
||||||
|
reset();
|
||||||
if (reloadTimer) {
|
|
||||||
reloadTimer->cancel();
|
|
||||||
reloadTimer.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fade) {
|
|
||||||
if (fade->crossFadeTimer) {
|
|
||||||
fade->crossFadeTimer->cancel();
|
|
||||||
fade->crossFadeTimer.reset();
|
|
||||||
}
|
|
||||||
fade.reset();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CBackground::CBackground(const Vector2D& viewport_, COutput* output_, const std::string& resourceID_, const std::unordered_map<std::string, std::any>& props, bool ss) :
|
void CBackground::registerSelf(const SP<CBackground>& self) {
|
||||||
viewport(viewport_), resourceID(resourceID_), output(output_), isScreenshot(ss) {
|
m_self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBackground::configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput) {
|
||||||
|
reset();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
color = std::any_cast<Hyprlang::INT>(props.at("color"));
|
color = std::any_cast<Hyprlang::INT>(props.at("color"));
|
||||||
|
@ -48,6 +40,29 @@ CBackground::CBackground(const Vector2D& viewport_, COutput* output_, const std:
|
||||||
RASSERT(false, "Missing propperty for CBackground: {}", e.what()); //
|
RASSERT(false, "Missing propperty for CBackground: {}", e.what()); //
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isScreenshot = path == "screenshot";
|
||||||
|
|
||||||
|
viewport = pOutput->getViewport();
|
||||||
|
outputPort = pOutput->stringPort;
|
||||||
|
transform = isScreenshot ? wlTransformToHyprutils(invertTransform(pOutput->transform)) : HYPRUTILS_TRANSFORM_NORMAL;
|
||||||
|
|
||||||
|
if (isScreenshot) {
|
||||||
|
resourceID = CScreencopyFrame::getResourceId(pOutput);
|
||||||
|
// 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) {
|
||||||
|
if (!g_pRenderer->asyncResourceGatherer->getAssetByID(resourceID))
|
||||||
|
resourceID = ""; // Fallback to solid color (background:color)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_pHyprlock->getScreencopy()) {
|
||||||
|
Debug::log(ERR, "No screencopy support! path=screenshot won't work. Falling back to background color.");
|
||||||
|
resourceID = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (!path.empty())
|
||||||
|
resourceID = "background:" + path;
|
||||||
|
|
||||||
if (!isScreenshot && reloadTime > -1) {
|
if (!isScreenshot && reloadTime > -1) {
|
||||||
try {
|
try {
|
||||||
modificationTime = std::filesystem::last_write_time(absolutePath(path, ""));
|
modificationTime = std::filesystem::last_write_time(absolutePath(path, ""));
|
||||||
|
@ -57,32 +72,43 @@ CBackground::CBackground(const Vector2D& viewport_, COutput* output_, const std:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CBackground::reset() {
|
||||||
|
if (reloadTimer) {
|
||||||
|
reloadTimer->cancel();
|
||||||
|
reloadTimer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fade) {
|
||||||
|
if (fade->crossFadeTimer) {
|
||||||
|
fade->crossFadeTimer->cancel();
|
||||||
|
fade->crossFadeTimer.reset();
|
||||||
|
}
|
||||||
|
fade.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CBackground::renderRect(CHyprColor color) {
|
void CBackground::renderRect(CHyprColor color) {
|
||||||
CBox monbox = {0, 0, viewport.x, viewport.y};
|
CBox monbox = {0, 0, viewport.x, viewport.y};
|
||||||
g_pRenderer->renderRect(monbox, color, 0);
|
g_pRenderer->renderRect(monbox, color, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onReloadTimer(std::shared_ptr<CTimer> self, void* data) {
|
static void onReloadTimer(WP<CBackground> ref) {
|
||||||
const auto PBG = (CBackground*)data;
|
if (auto PBG = ref.lock(); PBG) {
|
||||||
|
|
||||||
PBG->onReloadTimerUpdate();
|
PBG->onReloadTimerUpdate();
|
||||||
PBG->plantReloadTimer();
|
PBG->plantReloadTimer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onCrossFadeTimer(std::shared_ptr<CTimer> self, void* data) {
|
static void onCrossFadeTimer(WP<CBackground> ref) {
|
||||||
const auto PBG = (CBackground*)data;
|
if (auto PBG = ref.lock(); PBG)
|
||||||
PBG->onCrossFadeTimerUpdate();
|
PBG->onCrossFadeTimerUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onAssetCallback(void* data) {
|
static void onAssetCallback(WP<CBackground> ref) {
|
||||||
const auto PBG = (CBackground*)data;
|
if (auto PBG = ref.lock(); PBG)
|
||||||
PBG->startCrossFadeOrUpdateRender();
|
PBG->startCrossFadeOrUpdateRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onAssetCallbackTimer(std::shared_ptr<CTimer> self, void* data) {
|
|
||||||
onAssetCallback(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CBackground::draw(const SRenderData& data) {
|
bool CBackground::draw(const SRenderData& data) {
|
||||||
|
|
||||||
if (resourceID.empty()) {
|
if (resourceID.empty()) {
|
||||||
|
@ -115,7 +141,7 @@ bool CBackground::draw(const SRenderData& data) {
|
||||||
|
|
||||||
// make it brah
|
// make it brah
|
||||||
Vector2D size = asset->texture.m_vSize;
|
Vector2D size = asset->texture.m_vSize;
|
||||||
if (output->transform % 2 == 1 && isScreenshot) {
|
if (transform % 2 == 1 && isScreenshot) {
|
||||||
size.x = asset->texture.m_vSize.y;
|
size.x = asset->texture.m_vSize.y;
|
||||||
size.y = asset->texture.m_vSize.x;
|
size.y = asset->texture.m_vSize.x;
|
||||||
}
|
}
|
||||||
|
@ -142,16 +168,19 @@ bool CBackground::draw(const SRenderData& data) {
|
||||||
if (fade)
|
if (fade)
|
||||||
g_pRenderer->renderTextureMix(texbox, asset->texture, pendingAsset->texture, 1.0,
|
g_pRenderer->renderTextureMix(texbox, asset->texture, pendingAsset->texture, 1.0,
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - fade->start).count() / (1000 * crossFadeTime), 0,
|
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - fade->start).count() / (1000 * crossFadeTime), 0,
|
||||||
HYPRUTILS_TRANSFORM_NORMAL);
|
transform);
|
||||||
else
|
else
|
||||||
g_pRenderer->renderTexture(texbox, asset->texture, 1.0, 0,
|
g_pRenderer->renderTexture(texbox, asset->texture, 1.0, 0, transform);
|
||||||
isScreenshot ?
|
|
||||||
wlTransformToHyprutils(invertTransform(output->transform)) :
|
|
||||||
HYPRUTILS_TRANSFORM_NORMAL); // this could be omitted but whatever it's only once and makes code cleaner plus less blurring on large texs
|
|
||||||
|
|
||||||
if (blurPasses > 0)
|
if (blurPasses > 0)
|
||||||
g_pRenderer->blurFB(blurredFB, CRenderer::SBlurParams{
|
g_pRenderer->blurFB(blurredFB,
|
||||||
.size = blurSize, .passes = blurPasses, .noise = noise, .contrast = contrast, .brightness = brightness, .vibrancy = vibrancy, .vibrancy_darkness = vibrancy_darkness});
|
CRenderer::SBlurParams{.size = blurSize,
|
||||||
|
.passes = blurPasses,
|
||||||
|
.noise = noise,
|
||||||
|
.contrast = contrast,
|
||||||
|
.brightness = brightness,
|
||||||
|
.vibrancy = vibrancy,
|
||||||
|
.vibrancy_darkness = vibrancy_darkness});
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,9 +208,9 @@ bool CBackground::draw(const SRenderData& data) {
|
||||||
void CBackground::plantReloadTimer() {
|
void CBackground::plantReloadTimer() {
|
||||||
|
|
||||||
if (reloadTime == 0)
|
if (reloadTime == 0)
|
||||||
reloadTimer = g_pHyprlock->addTimer(std::chrono::hours(1), onReloadTimer, this, true);
|
reloadTimer = g_pHyprlock->addTimer(std::chrono::hours(1), [REF = m_self](auto, auto) { onReloadTimer(REF); }, nullptr, true);
|
||||||
else if (reloadTime > 0)
|
else if (reloadTime > 0)
|
||||||
reloadTimer = g_pHyprlock->addTimer(std::chrono::seconds(reloadTime), onReloadTimer, this, false);
|
reloadTimer = g_pHyprlock->addTimer(std::chrono::seconds(reloadTime), [REF = m_self](auto, auto) { onReloadTimer(REF); }, nullptr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBackground::onCrossFadeTimerUpdate() {
|
void CBackground::onCrossFadeTimerUpdate() {
|
||||||
|
@ -190,7 +219,7 @@ void CBackground::onCrossFadeTimerUpdate() {
|
||||||
|
|
||||||
if (fade) {
|
if (fade) {
|
||||||
fade->crossFadeTimer.reset();
|
fade->crossFadeTimer.reset();
|
||||||
fade.reset(nullptr);
|
fade.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blurPasses <= 0 && !isScreenshot)
|
if (blurPasses <= 0 && !isScreenshot)
|
||||||
|
@ -202,7 +231,7 @@ void CBackground::onCrossFadeTimerUpdate() {
|
||||||
pendingAsset = nullptr;
|
pendingAsset = nullptr;
|
||||||
firstRender = true;
|
firstRender = true;
|
||||||
|
|
||||||
g_pHyprlock->renderOutput(output->stringPort);
|
g_pHyprlock->renderOutput(outputPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBackground::onReloadTimerUpdate() {
|
void CBackground::onReloadTimerUpdate() {
|
||||||
|
@ -245,8 +274,7 @@ void CBackground::onReloadTimerUpdate() {
|
||||||
request.asset = path;
|
request.asset = path;
|
||||||
request.type = CAsyncResourceGatherer::eTargetType::TARGET_IMAGE;
|
request.type = CAsyncResourceGatherer::eTargetType::TARGET_IMAGE;
|
||||||
|
|
||||||
request.callback = onAssetCallback;
|
request.callback = [REF = m_self]() { onAssetCallback(REF); };
|
||||||
request.callbackData = this;
|
|
||||||
|
|
||||||
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
||||||
}
|
}
|
||||||
|
@ -262,7 +290,7 @@ void CBackground::startCrossFadeOrUpdateRender() {
|
||||||
if (crossFadeTime > 0) {
|
if (crossFadeTime > 0) {
|
||||||
// Start a fade
|
// Start a fade
|
||||||
if (!fade)
|
if (!fade)
|
||||||
fade = std::make_unique<SFade>(std::chrono::system_clock::now(), 0, nullptr);
|
fade = makeUnique<SFade>(std::chrono::system_clock::now(), 0, nullptr);
|
||||||
else {
|
else {
|
||||||
// Maybe we where already fading so reset it just in case, but should'nt be happening.
|
// Maybe we where already fading so reset it just in case, but should'nt be happening.
|
||||||
if (fade->crossFadeTimer) {
|
if (fade->crossFadeTimer) {
|
||||||
|
@ -272,15 +300,16 @@ void CBackground::startCrossFadeOrUpdateRender() {
|
||||||
}
|
}
|
||||||
fade->start = std::chrono::system_clock::now();
|
fade->start = std::chrono::system_clock::now();
|
||||||
fade->a = 0;
|
fade->a = 0;
|
||||||
fade->crossFadeTimer = g_pHyprlock->addTimer(std::chrono::milliseconds((int)(1000.0 * crossFadeTime)), onCrossFadeTimer, this);
|
fade->crossFadeTimer =
|
||||||
|
g_pHyprlock->addTimer(std::chrono::milliseconds((int)(1000.0 * crossFadeTime)), [REF = m_self](auto, auto) { onCrossFadeTimer(REF); }, nullptr);
|
||||||
} else {
|
} else {
|
||||||
onCrossFadeTimerUpdate();
|
onCrossFadeTimerUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (!pendingResourceID.empty()) {
|
} else if (!pendingResourceID.empty()) {
|
||||||
Debug::log(WARN, "Asset {} not available after the asyncResourceGatherer's callback!", pendingResourceID);
|
Debug::log(WARN, "Asset {} not available after the asyncResourceGatherer's callback!", pendingResourceID);
|
||||||
g_pHyprlock->addTimer(std::chrono::milliseconds(100), onAssetCallbackTimer, this);
|
g_pHyprlock->addTimer(std::chrono::milliseconds(100), [REF = m_self](auto, auto) { onAssetCallback(REF); }, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pHyprlock->renderOutput(output->stringPort);
|
g_pHyprlock->renderOutput(outputPort);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "../../core/Timer.hpp"
|
#include "../../core/Timer.hpp"
|
||||||
#include "../Framebuffer.hpp"
|
#include "../Framebuffer.hpp"
|
||||||
#include "../AsyncResourceGatherer.hpp"
|
#include "../AsyncResourceGatherer.hpp"
|
||||||
|
#include <hyprutils/math/Misc.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <any>
|
#include <any>
|
||||||
|
@ -23,10 +24,16 @@ struct SFade {
|
||||||
|
|
||||||
class CBackground : public IWidget {
|
class CBackground : public IWidget {
|
||||||
public:
|
public:
|
||||||
CBackground(const Vector2D& viewport, COutput* output_, const std::string& resourceID, const std::unordered_map<std::string, std::any>& props, bool ss_);
|
CBackground() = default;
|
||||||
~CBackground();
|
~CBackground();
|
||||||
|
|
||||||
|
void registerSelf(const SP<CBackground>& self);
|
||||||
|
|
||||||
|
virtual void configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput);
|
||||||
virtual bool draw(const SRenderData& data);
|
virtual bool draw(const SRenderData& data);
|
||||||
|
|
||||||
|
void reset(); // Unload assets, remove timers, etc.
|
||||||
|
|
||||||
void renderRect(CHyprColor color);
|
void renderRect(CHyprColor color);
|
||||||
|
|
||||||
void onReloadTimerUpdate();
|
void onReloadTimerUpdate();
|
||||||
|
@ -35,6 +42,8 @@ class CBackground : public IWidget {
|
||||||
void startCrossFadeOrUpdateRender();
|
void startCrossFadeOrUpdateRender();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WP<CBackground> m_self;
|
||||||
|
|
||||||
// if needed
|
// if needed
|
||||||
CFramebuffer blurredFB;
|
CFramebuffer blurredFB;
|
||||||
|
|
||||||
|
@ -48,6 +57,9 @@ class CBackground : public IWidget {
|
||||||
Vector2D viewport;
|
Vector2D viewport;
|
||||||
std::string path = "";
|
std::string path = "";
|
||||||
|
|
||||||
|
std::string outputPort;
|
||||||
|
Hyprutils::Math::eTransform transform;
|
||||||
|
|
||||||
std::string resourceID;
|
std::string resourceID;
|
||||||
std::string pendingResourceID;
|
std::string pendingResourceID;
|
||||||
|
|
||||||
|
@ -55,12 +67,11 @@ class CBackground : public IWidget {
|
||||||
|
|
||||||
CHyprColor color;
|
CHyprColor color;
|
||||||
SPreloadedAsset* asset = nullptr;
|
SPreloadedAsset* asset = nullptr;
|
||||||
COutput* output = nullptr;
|
|
||||||
bool isScreenshot = false;
|
bool isScreenshot = false;
|
||||||
SPreloadedAsset* pendingAsset = nullptr;
|
SPreloadedAsset* pendingAsset = nullptr;
|
||||||
bool firstRender = true;
|
bool firstRender = true;
|
||||||
|
|
||||||
std::unique_ptr<SFade> fade;
|
UP<SFade> fade;
|
||||||
|
|
||||||
int reloadTime = -1;
|
int reloadTime = -1;
|
||||||
std::string reloadCommand;
|
std::string reloadCommand;
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace std {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Vector2D rotateVector(const Vector2D& vec, const double& ang) {
|
static Vector2D rotateVector(const Vector2D& vec, const double& ang) {
|
||||||
const double COS = std::abs(std::cos(ang));
|
const double COS = std::abs(std::cos(ang));
|
||||||
const double SIN = std::abs(std::sin(ang));
|
const double SIN = std::abs(std::sin(ang));
|
||||||
return Vector2D((vec.x * COS) + (vec.y * SIN), (vec.x * SIN) + (vec.y * COS));
|
return Vector2D((vec.x * COS) + (vec.y * SIN), (vec.x * SIN) + (vec.y * COS));
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../helpers/Math.hpp"
|
#include "../../helpers/Math.hpp"
|
||||||
|
#include "../../defines.hpp"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <any>
|
||||||
|
|
||||||
|
class COutput;
|
||||||
|
|
||||||
class IWidget {
|
class IWidget {
|
||||||
public:
|
public:
|
||||||
struct SRenderData {
|
struct SRenderData {
|
||||||
float opacity = 1;
|
float opacity = 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual ~IWidget() = default;
|
virtual ~IWidget() = default;
|
||||||
|
|
||||||
|
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput) = 0;
|
||||||
virtual bool draw(const SRenderData& data) = 0;
|
virtual bool draw(const SRenderData& data) = 0;
|
||||||
|
|
||||||
static Vector2D posFromHVAlign(const Vector2D& viewport, const Vector2D& size, const Vector2D& offset, const std::string& halign, const std::string& valign,
|
static Vector2D posFromHVAlign(const Vector2D& viewport, const Vector2D& size, const Vector2D& offset, const std::string& halign, const std::string& valign,
|
||||||
|
|
|
@ -8,28 +8,25 @@
|
||||||
#include <hyprlang.hpp>
|
#include <hyprlang.hpp>
|
||||||
|
|
||||||
CImage::~CImage() {
|
CImage::~CImage() {
|
||||||
if (imageTimer) {
|
reset();
|
||||||
imageTimer->cancel();
|
}
|
||||||
imageTimer.reset();
|
|
||||||
|
void CImage::registerSelf(const SP<CImage>& self) {
|
||||||
|
m_self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onTimer(WP<CImage> ref) {
|
||||||
|
if (auto PIMAGE = ref.lock(); PIMAGE) {
|
||||||
|
PIMAGE->onTimerUpdate();
|
||||||
|
PIMAGE->plantTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onTimer(std::shared_ptr<CTimer> self, void* data) {
|
static void onAssetCallback(WP<CImage> ref) {
|
||||||
const auto PIMAGE = (CImage*)data;
|
if (auto PIMAGE = ref.lock(); PIMAGE)
|
||||||
|
|
||||||
PIMAGE->onTimerUpdate();
|
|
||||||
PIMAGE->plantTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onAssetCallback(void* data) {
|
|
||||||
const auto PIMAGE = (CImage*)data;
|
|
||||||
PIMAGE->renderUpdate();
|
PIMAGE->renderUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onAssetCallbackTimer(std::shared_ptr<CTimer> self, void* data) {
|
|
||||||
onAssetCallback(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CImage::onTimerUpdate() {
|
void CImage::onTimerUpdate() {
|
||||||
const std::string OLDPATH = path;
|
const std::string OLDPATH = path;
|
||||||
|
|
||||||
|
@ -65,9 +62,7 @@ void CImage::onTimerUpdate() {
|
||||||
pendingResourceID = request.id;
|
pendingResourceID = request.id;
|
||||||
request.asset = path;
|
request.asset = path;
|
||||||
request.type = CAsyncResourceGatherer::eTargetType::TARGET_IMAGE;
|
request.type = CAsyncResourceGatherer::eTargetType::TARGET_IMAGE;
|
||||||
|
request.callback = [REF = m_self]() { onAssetCallback(REF); };
|
||||||
request.callback = onAssetCallback;
|
|
||||||
request.callbackData = this;
|
|
||||||
|
|
||||||
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
||||||
}
|
}
|
||||||
|
@ -75,20 +70,24 @@ void CImage::onTimerUpdate() {
|
||||||
void CImage::plantTimer() {
|
void CImage::plantTimer() {
|
||||||
|
|
||||||
if (reloadTime == 0) {
|
if (reloadTime == 0) {
|
||||||
imageTimer = g_pHyprlock->addTimer(std::chrono::hours(1), onTimer, this, true);
|
imageTimer = g_pHyprlock->addTimer(std::chrono::hours(1), [REF = m_self](auto, auto) { onTimer(REF); }, nullptr, true);
|
||||||
} else if (reloadTime > 0)
|
} else if (reloadTime > 0)
|
||||||
imageTimer = g_pHyprlock->addTimer(std::chrono::seconds(reloadTime), onTimer, this, false);
|
imageTimer = g_pHyprlock->addTimer(std::chrono::seconds(reloadTime), [REF = m_self](auto, auto) { onTimer(REF); }, nullptr, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
CImage::CImage(const Vector2D& viewport_, COutput* output_, const std::string& resourceID_, const std::unordered_map<std::string, std::any>& props) :
|
void CImage::configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput) {
|
||||||
viewport(viewport_), resourceID(resourceID_), output(output_), shadow(this, props, viewport_) {
|
reset();
|
||||||
|
|
||||||
|
viewport = pOutput->getViewport();
|
||||||
|
|
||||||
|
shadow.configure(m_self.lock(), props, viewport);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
size = std::any_cast<Hyprlang::INT>(props.at("size"));
|
size = std::any_cast<Hyprlang::INT>(props.at("size"));
|
||||||
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
|
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
|
||||||
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
|
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
|
||||||
color = *CGradientValueData::fromAnyPv(props.at("border_color"));
|
color = *CGradientValueData::fromAnyPv(props.at("border_color"));
|
||||||
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport_);
|
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport);
|
||||||
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
||||||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||||
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
|
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
|
||||||
|
@ -113,6 +112,25 @@ CImage::CImage(const Vector2D& viewport_, COutput* output_, const std::string& r
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CImage::reset() {
|
||||||
|
if (imageTimer) {
|
||||||
|
imageTimer->cancel();
|
||||||
|
imageTimer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_pHyprlock->m_bTerminate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
imageFB.release();
|
||||||
|
|
||||||
|
if (asset)
|
||||||
|
g_pRenderer->asyncResourceGatherer->unloadAsset(asset);
|
||||||
|
|
||||||
|
asset = nullptr;
|
||||||
|
pendingResourceID = "";
|
||||||
|
resourceID = "";
|
||||||
|
}
|
||||||
|
|
||||||
bool CImage::draw(const SRenderData& data) {
|
bool CImage::draw(const SRenderData& data) {
|
||||||
|
|
||||||
if (resourceID.empty())
|
if (resourceID.empty())
|
||||||
|
@ -204,8 +222,11 @@ void CImage::renderUpdate() {
|
||||||
pendingResourceID = "";
|
pendingResourceID = "";
|
||||||
} else if (!pendingResourceID.empty()) {
|
} else if (!pendingResourceID.empty()) {
|
||||||
Debug::log(WARN, "Asset {} not available after the asyncResourceGatherer's callback!", pendingResourceID);
|
Debug::log(WARN, "Asset {} not available after the asyncResourceGatherer's callback!", pendingResourceID);
|
||||||
|
pendingResourceID = "";
|
||||||
|
} else if (!pendingResourceID.empty()) {
|
||||||
|
Debug::log(WARN, "Asset {} not available after the asyncResourceGatherer's callback!", pendingResourceID);
|
||||||
|
|
||||||
g_pHyprlock->addTimer(std::chrono::milliseconds(100), onAssetCallbackTimer, this);
|
g_pHyprlock->addTimer(std::chrono::milliseconds(100), [REF = m_self](auto, auto) { onAssetCallback(REF); }, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pHyprlock->renderOutput(output->stringPort);
|
g_pHyprlock->renderOutput(output->stringPort);
|
||||||
|
|
|
@ -17,16 +17,23 @@ class COutput;
|
||||||
|
|
||||||
class CImage : public IWidget {
|
class CImage : public IWidget {
|
||||||
public:
|
public:
|
||||||
CImage(const Vector2D& viewport, COutput* output_, const std::string& resourceID, const std::unordered_map<std::string, std::any>& props);
|
CImage() = default;
|
||||||
~CImage();
|
~CImage();
|
||||||
|
|
||||||
|
void registerSelf(const SP<CImage>& self);
|
||||||
|
|
||||||
|
virtual void configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput);
|
||||||
virtual bool draw(const SRenderData& data);
|
virtual bool draw(const SRenderData& data);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
void renderUpdate();
|
void renderUpdate();
|
||||||
void onTimerUpdate();
|
void onTimerUpdate();
|
||||||
void plantTimer();
|
void plantTimer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WP<CImage> m_self;
|
||||||
|
|
||||||
CFramebuffer imageFB;
|
CFramebuffer imageFB;
|
||||||
|
|
||||||
int size;
|
int size;
|
||||||
|
|
|
@ -8,33 +8,27 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
CLabel::~CLabel() {
|
CLabel::~CLabel() {
|
||||||
if (labelTimer) {
|
reset();
|
||||||
labelTimer->cancel();
|
}
|
||||||
labelTimer.reset();
|
|
||||||
|
void CLabel::registerSelf(const SP<CLabel>& self) {
|
||||||
|
m_self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void onTimer(WP<CLabel> ref) {
|
||||||
|
if (auto PLABEL = ref.lock(); PLABEL) {
|
||||||
|
// update label
|
||||||
|
PLABEL->onTimerUpdate();
|
||||||
|
// plant new timer
|
||||||
|
PLABEL->plantTimer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onTimer(std::shared_ptr<CTimer> self, void* data) {
|
static void onAssetCallback(WP<CLabel> ref) {
|
||||||
if (data == nullptr)
|
if (auto PLABEL = ref.lock(); PLABEL)
|
||||||
return;
|
|
||||||
const auto PLABEL = (CLabel*)data;
|
|
||||||
|
|
||||||
// update label
|
|
||||||
PLABEL->onTimerUpdate();
|
|
||||||
|
|
||||||
// plant new timer
|
|
||||||
PLABEL->plantTimer();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onAssetCallback(void* data) {
|
|
||||||
const auto PLABEL = (CLabel*)data;
|
|
||||||
PLABEL->renderUpdate();
|
PLABEL->renderUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void onAssetCallbackTimer(std::shared_ptr<CTimer> self, void* data) {
|
|
||||||
onAssetCallback(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CLabel::getUniqueResourceId() {
|
std::string CLabel::getUniqueResourceId() {
|
||||||
return std::string{"label:"} + std::to_string((uintptr_t)this) + ",time:" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count());
|
return std::string{"label:"} + std::to_string((uintptr_t)this) + ",time:" + std::to_string(std::chrono::system_clock::now().time_since_epoch().count());
|
||||||
}
|
}
|
||||||
|
@ -57,23 +51,29 @@ void CLabel::onTimerUpdate() {
|
||||||
pendingResourceID = request.id;
|
pendingResourceID = request.id;
|
||||||
request.asset = label.formatted;
|
request.asset = label.formatted;
|
||||||
|
|
||||||
request.callback = onAssetCallback;
|
request.callback = [REF = m_self]() { onAssetCallback(REF); };
|
||||||
request.callbackData = this;
|
|
||||||
|
|
||||||
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CLabel::plantTimer() {
|
void CLabel::plantTimer() {
|
||||||
|
|
||||||
if (label.updateEveryMs != 0)
|
if (label.updateEveryMs != 0)
|
||||||
labelTimer = g_pHyprlock->addTimer(std::chrono::milliseconds((int)label.updateEveryMs), onTimer, this, label.allowForceUpdate);
|
labelTimer = g_pHyprlock->addTimer(std::chrono::milliseconds((int)label.updateEveryMs), [REF = m_self](auto, auto) { onTimer(REF); }, this, label.allowForceUpdate);
|
||||||
else if (label.updateEveryMs == 0 && label.allowForceUpdate)
|
else if (label.updateEveryMs == 0 && label.allowForceUpdate)
|
||||||
labelTimer = g_pHyprlock->addTimer(std::chrono::hours(1), onTimer, this, true);
|
labelTimer = g_pHyprlock->addTimer(std::chrono::hours(1), [REF = m_self](auto, auto) { onTimer(REF); }, this, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
CLabel::CLabel(const Vector2D& viewport_, const std::unordered_map<std::string, std::any>& props, const std::string& output) :
|
void CLabel::configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput) {
|
||||||
outputStringPort(output), shadow(this, props, viewport_) {
|
reset();
|
||||||
|
|
||||||
|
outputStringPort = pOutput->stringPort;
|
||||||
|
viewport = pOutput->getViewport();
|
||||||
|
|
||||||
|
shadow.configure(m_self.lock(), props, viewport);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport_);
|
configPos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport);
|
||||||
labelPreFormat = std::any_cast<Hyprlang::STRING>(props.at("text"));
|
labelPreFormat = std::any_cast<Hyprlang::STRING>(props.at("text"));
|
||||||
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
||||||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||||
|
@ -105,14 +105,30 @@ CLabel::CLabel(const Vector2D& viewport_, const std::unordered_map<std::string,
|
||||||
RASSERT(false, "Missing property for CLabel: {}", e.what()); //
|
RASSERT(false, "Missing property for CLabel: {}", e.what()); //
|
||||||
}
|
}
|
||||||
|
|
||||||
configPos = pos;
|
pos = configPos; // Label size not known yet
|
||||||
viewport = viewport_;
|
|
||||||
|
|
||||||
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
||||||
|
|
||||||
plantTimer();
|
plantTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CLabel::reset() {
|
||||||
|
if (labelTimer) {
|
||||||
|
labelTimer->cancel();
|
||||||
|
labelTimer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_pHyprlock->m_bTerminate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (asset)
|
||||||
|
g_pRenderer->asyncResourceGatherer->unloadAsset(asset);
|
||||||
|
|
||||||
|
asset = nullptr;
|
||||||
|
pendingResourceID.clear();
|
||||||
|
resourceID.clear();
|
||||||
|
}
|
||||||
|
|
||||||
bool CLabel::draw(const SRenderData& data) {
|
bool CLabel::draw(const SRenderData& data) {
|
||||||
if (!asset) {
|
if (!asset) {
|
||||||
asset = g_pRenderer->asyncResourceGatherer->getAssetByID(resourceID);
|
asset = g_pRenderer->asyncResourceGatherer->getAssetByID(resourceID);
|
||||||
|
@ -150,7 +166,7 @@ void CLabel::renderUpdate() {
|
||||||
} else {
|
} else {
|
||||||
Debug::log(WARN, "Asset {} not available after the asyncResourceGatherer's callback!", pendingResourceID);
|
Debug::log(WARN, "Asset {} not available after the asyncResourceGatherer's callback!", pendingResourceID);
|
||||||
|
|
||||||
g_pHyprlock->addTimer(std::chrono::milliseconds(100), onAssetCallbackTimer, this);
|
g_pHyprlock->addTimer(std::chrono::milliseconds(100), [REF = m_self](auto, auto) { onAssetCallback(REF); }, nullptr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,16 +14,23 @@ class CSessionLockSurface;
|
||||||
|
|
||||||
class CLabel : public IWidget {
|
class CLabel : public IWidget {
|
||||||
public:
|
public:
|
||||||
CLabel(const Vector2D& viewport, const std::unordered_map<std::string, std::any>& props, const std::string& output);
|
CLabel() = default;
|
||||||
~CLabel();
|
~CLabel();
|
||||||
|
|
||||||
|
void registerSelf(const SP<CLabel>& self);
|
||||||
|
|
||||||
|
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
|
||||||
virtual bool draw(const SRenderData& data);
|
virtual bool draw(const SRenderData& data);
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
void renderUpdate();
|
void renderUpdate();
|
||||||
void onTimerUpdate();
|
void onTimerUpdate();
|
||||||
void plantTimer();
|
void plantTimer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WP<CLabel> m_self;
|
||||||
|
|
||||||
std::string getUniqueResourceId();
|
std::string getUniqueResourceId();
|
||||||
|
|
||||||
std::string labelPreFormat;
|
std::string labelPreFormat;
|
||||||
|
|
|
@ -15,11 +15,25 @@
|
||||||
|
|
||||||
using namespace Hyprutils::String;
|
using namespace Hyprutils::String;
|
||||||
|
|
||||||
CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::unordered_map<std::string, std::any>& props, const std::string& output) :
|
CPasswordInputField::~CPasswordInputField() {
|
||||||
viewport(viewport_), outputStringPort(output), shadow(this, props, viewport_) {
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPasswordInputField::registerSelf(const SP<CPasswordInputField>& self) {
|
||||||
|
m_self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPasswordInputField::configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput) {
|
||||||
|
reset();
|
||||||
|
|
||||||
|
outputStringPort = pOutput->stringPort;
|
||||||
|
viewport = pOutput->getViewport();
|
||||||
|
|
||||||
|
shadow.configure(m_self.lock(), props, viewport);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport_);
|
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport);
|
||||||
configSize = CLayoutValueData::fromAnyPv(props.at("size"))->getAbsolute(viewport_);
|
configSize = CLayoutValueData::fromAnyPv(props.at("size"))->getAbsolute(viewport);
|
||||||
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
||||||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||||
outThick = std::any_cast<Hyprlang::INT>(props.at("outline_thickness"));
|
outThick = std::any_cast<Hyprlang::INT>(props.at("outline_thickness"));
|
||||||
|
@ -61,6 +75,16 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u
|
||||||
|
|
||||||
colorConfig.caps = colorConfig.caps->m_bIsFallback ? colorConfig.fail : colorConfig.caps;
|
colorConfig.caps = colorConfig.caps->m_bIsFallback ? colorConfig.fail : colorConfig.caps;
|
||||||
|
|
||||||
|
g_pAnimationManager->createAnimation(0.f, fade.a, g_pConfigManager->m_AnimationTree.getConfig("inputFieldFade"));
|
||||||
|
g_pAnimationManager->createAnimation(0.f, dots.currentAmount, g_pConfigManager->m_AnimationTree.getConfig("inputFieldDots"));
|
||||||
|
g_pAnimationManager->createAnimation(configSize, size, g_pConfigManager->m_AnimationTree.getConfig("inputFieldWidth"));
|
||||||
|
g_pAnimationManager->createAnimation(colorConfig.inner, colorState.inner, g_pConfigManager->m_AnimationTree.getConfig("inputFieldColors"));
|
||||||
|
g_pAnimationManager->createAnimation(*colorConfig.outer, colorState.outer, g_pConfigManager->m_AnimationTree.getConfig("inputFieldColors"));
|
||||||
|
|
||||||
|
srand(std::chrono::system_clock::now().time_since_epoch().count());
|
||||||
|
|
||||||
|
pos = posFromHVAlign(viewport, size->goal(), configPos, halign, valign);
|
||||||
|
|
||||||
if (!dots.textFormat.empty()) {
|
if (!dots.textFormat.empty()) {
|
||||||
dots.textResourceID = std::format("input:{}-{}", (uintptr_t)this, dots.textFormat);
|
dots.textResourceID = std::format("input:{}-{}", (uintptr_t)this, dots.textFormat);
|
||||||
CAsyncResourceGatherer::SPreloadRequest request;
|
CAsyncResourceGatherer::SPreloadRequest request;
|
||||||
|
@ -74,23 +98,30 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u
|
||||||
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
g_pRenderer->asyncResourceGatherer->requestAsyncAssetPreload(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pAnimationManager->createAnimation(0.f, fade.a, g_pConfigManager->m_AnimationTree.getConfig("inputFieldFade"));
|
|
||||||
g_pAnimationManager->createAnimation(0.f, dots.currentAmount, g_pConfigManager->m_AnimationTree.getConfig("inputFieldDots"));
|
|
||||||
g_pAnimationManager->createAnimation(configSize, size, g_pConfigManager->m_AnimationTree.getConfig("inputFieldWidth"));
|
|
||||||
|
|
||||||
g_pAnimationManager->createAnimation(colorConfig.inner, colorState.inner, g_pConfigManager->m_AnimationTree.getConfig("inputFieldColors"));
|
|
||||||
g_pAnimationManager->createAnimation(*colorConfig.outer, colorState.outer, g_pConfigManager->m_AnimationTree.getConfig("inputFieldColors"));
|
|
||||||
|
|
||||||
srand(std::chrono::system_clock::now().time_since_epoch().count());
|
|
||||||
|
|
||||||
// request the inital placeholder asset
|
// request the inital placeholder asset
|
||||||
updatePlaceholder();
|
updatePlaceholder();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fadeOutCallback(std::shared_ptr<CTimer> self, void* data) {
|
void CPasswordInputField::reset() {
|
||||||
CPasswordInputField* p = (CPasswordInputField*)data;
|
if (fade.fadeOutTimer.get()) {
|
||||||
|
fade.fadeOutTimer->cancel();
|
||||||
|
fade.fadeOutTimer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
p->onFadeOutTimer();
|
if (g_pHyprlock->m_bTerminate)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (placeholder.asset)
|
||||||
|
g_pRenderer->asyncResourceGatherer->unloadAsset(placeholder.asset);
|
||||||
|
|
||||||
|
placeholder.asset = nullptr;
|
||||||
|
placeholder.resourceID.clear();
|
||||||
|
placeholder.currentText.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fadeOutCallback(WP<CPasswordInputField> ref) {
|
||||||
|
if (const auto PP = ref.lock(); PP)
|
||||||
|
PP->onFadeOutTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPasswordInputField::onFadeOutTimer() {
|
void CPasswordInputField::onFadeOutTimer() {
|
||||||
|
@ -121,7 +152,8 @@ void CPasswordInputField::updateFade() {
|
||||||
*fade.a = 0.0;
|
*fade.a = 0.0;
|
||||||
fade.allowFadeOut = false;
|
fade.allowFadeOut = false;
|
||||||
} else if (!fade.fadeOutTimer.get())
|
} else if (!fade.fadeOutTimer.get())
|
||||||
fade.fadeOutTimer = g_pHyprlock->addTimer(std::chrono::milliseconds(fadeTimeoutMs), fadeOutCallback, this);
|
fade.fadeOutTimer = g_pHyprlock->addTimer(std::chrono::milliseconds(fadeTimeoutMs), [REF = m_self](auto, auto) { fadeOutCallback(REF); }, nullptr);
|
||||||
|
|
||||||
} else if (INPUTUSED && fade.a->goal() != 1.0)
|
} else if (INPUTUSED && fade.a->goal() != 1.0)
|
||||||
*fade.a = 1.0;
|
*fade.a = 1.0;
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "../../config/ConfigDataValues.hpp"
|
#include "../../config/ConfigDataValues.hpp"
|
||||||
#include "../../helpers/AnimatedVariable.hpp"
|
#include "../../helpers/AnimatedVariable.hpp"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <hyprutils/math/Vector2D.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <any>
|
#include <any>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -16,12 +17,20 @@ struct SPreloadedAsset;
|
||||||
|
|
||||||
class CPasswordInputField : public IWidget {
|
class CPasswordInputField : public IWidget {
|
||||||
public:
|
public:
|
||||||
CPasswordInputField(const Vector2D& viewport, const std::unordered_map<std::string, std::any>& props, const std::string& output);
|
CPasswordInputField() = default;
|
||||||
|
virtual ~CPasswordInputField();
|
||||||
|
|
||||||
|
void registerSelf(const SP<CPasswordInputField>& self);
|
||||||
|
|
||||||
|
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
|
||||||
virtual bool draw(const SRenderData& data);
|
virtual bool draw(const SRenderData& data);
|
||||||
|
|
||||||
|
void reset();
|
||||||
void onFadeOutTimer();
|
void onFadeOutTimer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WP<CPasswordInputField> m_self;
|
||||||
|
|
||||||
void updateDots();
|
void updateDots();
|
||||||
void updateFade();
|
void updateFade();
|
||||||
void updatePlaceholder();
|
void updatePlaceholder();
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
#include "../Renderer.hpp"
|
#include "../Renderer.hpp"
|
||||||
#include <hyprlang.hpp>
|
#include <hyprlang.hpp>
|
||||||
|
|
||||||
CShadowable::CShadowable(IWidget* widget_, const std::unordered_map<std::string, std::any>& props, const Vector2D& viewport_) : widget(widget_), viewport(viewport_) {
|
void CShadowable::configure(WP<IWidget> widget_, const std::unordered_map<std::string, std::any>& props, const Vector2D& viewport_) {
|
||||||
|
m_widget = widget_;
|
||||||
|
viewport = viewport_;
|
||||||
|
|
||||||
size = std::any_cast<Hyprlang::INT>(props.at("shadow_size"));
|
size = std::any_cast<Hyprlang::INT>(props.at("shadow_size"));
|
||||||
passes = std::any_cast<Hyprlang::INT>(props.at("shadow_passes"));
|
passes = std::any_cast<Hyprlang::INT>(props.at("shadow_passes"));
|
||||||
color = std::any_cast<Hyprlang::INT>(props.at("shadow_color"));
|
color = std::any_cast<Hyprlang::INT>(props.at("shadow_color"));
|
||||||
|
@ -10,6 +13,10 @@ CShadowable::CShadowable(IWidget* widget_, const std::unordered_map<std::string,
|
||||||
}
|
}
|
||||||
|
|
||||||
void CShadowable::markShadowDirty() {
|
void CShadowable::markShadowDirty() {
|
||||||
|
const auto WIDGET = m_widget.lock();
|
||||||
|
|
||||||
|
if (!m_widget)
|
||||||
|
return;
|
||||||
|
|
||||||
if (passes == 0)
|
if (passes == 0)
|
||||||
return;
|
return;
|
||||||
|
@ -22,7 +29,7 @@ void CShadowable::markShadowDirty() {
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
ignoreDraw = true;
|
ignoreDraw = true;
|
||||||
widget->draw(IWidget::SRenderData{.opacity = 1.0});
|
WIDGET->draw(IWidget::SRenderData{.opacity = 1.0});
|
||||||
ignoreDraw = false;
|
ignoreDraw = false;
|
||||||
|
|
||||||
g_pRenderer->blurFB(shadowFB, CRenderer::SBlurParams{.size = size, .passes = passes, .colorize = color, .boostA = boostA});
|
g_pRenderer->blurFB(shadowFB, CRenderer::SBlurParams{.size = size, .passes = passes, .colorize = color, .boostA = boostA});
|
||||||
|
@ -31,7 +38,7 @@ void CShadowable::markShadowDirty() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CShadowable::draw(const IWidget::SRenderData& data) {
|
bool CShadowable::draw(const IWidget::SRenderData& data) {
|
||||||
if (passes == 0)
|
if (!m_widget || passes == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!shadowFB.isAllocated() || ignoreDraw)
|
if (!shadowFB.isAllocated() || ignoreDraw)
|
||||||
|
|
|
@ -11,14 +11,16 @@
|
||||||
|
|
||||||
class CShadowable {
|
class CShadowable {
|
||||||
public:
|
public:
|
||||||
CShadowable(IWidget* widget_, const std::unordered_map<std::string, std::any>& props, const Vector2D& viewport_ /* TODO: make this not the entire viewport */);
|
virtual ~CShadowable() = default;
|
||||||
|
CShadowable() = default;
|
||||||
|
void configure(WP<IWidget> widget_, const std::unordered_map<std::string, std::any>& props, const Vector2D& viewport_ /* TODO: make this not the entire viewport */);
|
||||||
|
|
||||||
// instantly re-renders the shadow using the widget's draw() method
|
// instantly re-renders the shadow using the widget's draw() method
|
||||||
void markShadowDirty();
|
void markShadowDirty();
|
||||||
virtual bool draw(const IWidget::SRenderData& data);
|
virtual bool draw(const IWidget::SRenderData& data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
IWidget* widget = nullptr;
|
WP<IWidget> m_widget;
|
||||||
int size = 10;
|
int size = 10;
|
||||||
int passes = 4;
|
int passes = 4;
|
||||||
float boostA = 1.0;
|
float boostA = 1.0;
|
||||||
|
|
|
@ -4,15 +4,22 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <hyprlang.hpp>
|
#include <hyprlang.hpp>
|
||||||
|
|
||||||
CShape::CShape(const Vector2D& viewport_, const std::unordered_map<std::string, std::any>& props) : shadow(this, props, viewport_) {
|
void CShape::registerSelf(const SP<CShape>& self) {
|
||||||
|
m_self = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShape::configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput) {
|
||||||
|
viewport = pOutput->getViewport();
|
||||||
|
|
||||||
|
shadow.configure(m_self.lock(), props, viewport);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
size = CLayoutValueData::fromAnyPv(props.at("size"))->getAbsolute(viewport_);
|
size = CLayoutValueData::fromAnyPv(props.at("size"))->getAbsolute(viewport);
|
||||||
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
|
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
|
||||||
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
|
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
|
||||||
color = std::any_cast<Hyprlang::INT>(props.at("color"));
|
color = std::any_cast<Hyprlang::INT>(props.at("color"));
|
||||||
borderGrad = *CGradientValueData::fromAnyPv(props.at("border_color"));
|
borderGrad = *CGradientValueData::fromAnyPv(props.at("border_color"));
|
||||||
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport_);
|
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport);
|
||||||
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
||||||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||||
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
|
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
|
||||||
|
@ -23,7 +30,6 @@ CShape::CShape(const Vector2D& viewport_, const std::unordered_map<std::string,
|
||||||
RASSERT(false, "Missing property for CShape: {}", e.what()); //
|
RASSERT(false, "Missing property for CShape: {}", e.what()); //
|
||||||
}
|
}
|
||||||
|
|
||||||
viewport = viewport_;
|
|
||||||
angle = angle * M_PI / 180.0;
|
angle = angle * M_PI / 180.0;
|
||||||
|
|
||||||
const Vector2D VBORDER = {border, border};
|
const Vector2D VBORDER = {border, border};
|
||||||
|
|
|
@ -11,11 +11,17 @@
|
||||||
|
|
||||||
class CShape : public IWidget {
|
class CShape : public IWidget {
|
||||||
public:
|
public:
|
||||||
CShape(const Vector2D& viewport, const std::unordered_map<std::string, std::any>& props);
|
CShape() = default;
|
||||||
|
virtual ~CShape() = default;
|
||||||
|
|
||||||
|
void registerSelf(const SP<CShape>& self);
|
||||||
|
|
||||||
|
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
|
||||||
virtual bool draw(const SRenderData& data);
|
virtual bool draw(const SRenderData& data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
WP<CShape> m_self;
|
||||||
|
|
||||||
CFramebuffer shapeFB;
|
CFramebuffer shapeFB;
|
||||||
|
|
||||||
int rounding;
|
int rounding;
|
||||||
|
|
Loading…
Reference in a new issue