mirror of
https://github.com/hyprwm/hyprlock.git
synced 2025-05-13 05:40:42 +01:00
Compare commits
5 commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f7f0c9c6b0 | ||
![]() |
c12cf8e509 | ||
![]() |
0c5fd97d61 | ||
![]() |
fae1c4f6fe | ||
![]() |
e3bd47e177 |
30 changed files with 338 additions and 106 deletions
|
@ -36,7 +36,7 @@ add_compile_definitions(HYPRLOCK_VERSION="${VERSION}")
|
|||
if (DEFINED HYPRLOCK_COMMIT)
|
||||
add_compile_definitions(HYPRLOCK_COMMIT="${HYPRLOCK_COMMIT}")
|
||||
else()
|
||||
# get git commit
|
||||
# get git commit
|
||||
execute_process(
|
||||
OUTPUT_VARIABLE GIT_SHORT_HASH
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
|
@ -82,9 +82,6 @@ pkg_check_modules(
|
|||
hyprlang>=0.6.0
|
||||
egl
|
||||
xkbcommon
|
||||
libjpeg
|
||||
libwebp
|
||||
libmagic
|
||||
cairo
|
||||
pangocairo
|
||||
libdrm
|
||||
|
|
39
README.md
39
README.md
|
@ -2,10 +2,14 @@
|
|||
Hyprland's simple, yet multi-threaded and GPU-accelerated screen locking utility.
|
||||
|
||||
## Features
|
||||
- uses the secure ext-session-lock protocol
|
||||
- full support for fractional-scale
|
||||
- fully GPU accelerated
|
||||
- multi-threaded resource acquisition for no hitches
|
||||
- Uses the ext-session-lock protocol
|
||||
- Support for fractional-scale
|
||||
- Fully GPU accelerated
|
||||
- Multi-threaded resource acquisition
|
||||
- Blurred screenshot as the background
|
||||
- Native fingerprint support (using libfprint's dbus interface)
|
||||
- Some of Hyprland's eyecandy: gradient borders, blur, animations, shadows, etc.
|
||||
- and more...
|
||||
|
||||
## How it looks
|
||||
|
||||
|
@ -25,26 +29,23 @@ yay -S hyprlock-git # compiles from latest source
|
|||
|
||||
### Deps
|
||||
You need the following dependencies
|
||||
- wayland-client
|
||||
- wayland-protocols
|
||||
- mesa
|
||||
- hyprwayland-scanner
|
||||
|
||||
And the development libraries for the following
|
||||
- cairo
|
||||
- libdrm
|
||||
- pango
|
||||
- xkbcommon
|
||||
- pam
|
||||
- hyprgraphics
|
||||
- hyprland-protocols
|
||||
- hyprlang
|
||||
- hyprutils
|
||||
- hyprgraphics
|
||||
- libmagic (file-devel on Fedora)
|
||||
- hyprwayland-scanner
|
||||
- mesa (required is libgbm, libdrm and the opengl runtime)
|
||||
- pam
|
||||
- pango
|
||||
- sdbus-cpp (>= 2.0.0)
|
||||
- wayland-client
|
||||
- wayland-protocols
|
||||
- xkbcommon
|
||||
|
||||
Development libraries are usually suffixed with `-devel` or `-dev` in most distro repos.
|
||||
|
||||
You also need to install `mesa-libgbm-devel` on some distros like RPM based ones where its not
|
||||
bundled with the mesa package.
|
||||
Sometimes distro packages are missing required development files.
|
||||
Such distros usually offer development versions of library package - commonly suffixed with `-devel` or `-dev`.
|
||||
|
||||
### Building
|
||||
|
||||
|
|
|
@ -5,11 +5,14 @@
|
|||
# ref. https://wiki.hyprland.org/Hypr-Ecosystem/hyprlock/#general-remarks
|
||||
#
|
||||
# shortcuts to clear password buffer: ESC, Ctrl+U, Ctrl+Backspace
|
||||
#
|
||||
# you can get started by copying this config to ~/.config/hypr/hyprlock.conf
|
||||
#
|
||||
|
||||
$font = Monospace
|
||||
|
||||
general {
|
||||
hide_cursor = true
|
||||
hide_cursor = false
|
||||
}
|
||||
|
||||
# uncomment to enable fingerprint authentication
|
||||
|
@ -90,3 +93,14 @@ label {
|
|||
halign = right
|
||||
valign = top
|
||||
}
|
||||
|
||||
label {
|
||||
monitor =
|
||||
text = $LAYOUT[en,ru]
|
||||
font_size = 24
|
||||
onclick = hyprctl switchxkblayout all next
|
||||
|
||||
position = 250, -20
|
||||
halign = center
|
||||
valign = center
|
||||
}
|
||||
|
|
|
@ -4,11 +4,8 @@
|
|||
cmake,
|
||||
pkg-config,
|
||||
cairo,
|
||||
file,
|
||||
libdrm,
|
||||
libGL,
|
||||
libjpeg,
|
||||
libwebp,
|
||||
libxkbcommon,
|
||||
libgbm,
|
||||
hyprgraphics,
|
||||
|
@ -40,11 +37,8 @@ stdenv.mkDerivation {
|
|||
|
||||
buildInputs = [
|
||||
cairo
|
||||
file
|
||||
libdrm
|
||||
libGL
|
||||
libjpeg
|
||||
libwebp
|
||||
libxkbcommon
|
||||
libgbm
|
||||
hyprgraphics
|
||||
|
|
|
@ -209,6 +209,9 @@ void CConfigManager::init() {
|
|||
m_config.addSpecialConfigValue(name, "shadow_passes", Hyprlang::INT{0}); \
|
||||
m_config.addSpecialConfigValue(name, "shadow_color", Hyprlang::INT{0xFF000000}); \
|
||||
m_config.addSpecialConfigValue(name, "shadow_boost", Hyprlang::FLOAT{1.2});
|
||||
|
||||
#define CLICKABLE(name) m_config.addSpecialConfigValue(name, "onclick", Hyprlang::STRING{""});
|
||||
|
||||
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});
|
||||
|
@ -257,6 +260,7 @@ void CConfigManager::init() {
|
|||
m_config.addSpecialConfigValue("shape", "xray", Hyprlang::INT{0});
|
||||
m_config.addSpecialConfigValue("shape", "zindex", Hyprlang::INT{0});
|
||||
SHADOWABLE("shape");
|
||||
CLICKABLE("shape");
|
||||
|
||||
m_config.addSpecialCategory("image", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
|
||||
m_config.addSpecialConfigValue("image", "monitor", Hyprlang::STRING{""});
|
||||
|
@ -273,6 +277,7 @@ void CConfigManager::init() {
|
|||
m_config.addSpecialConfigValue("image", "reload_cmd", Hyprlang::STRING{""});
|
||||
m_config.addSpecialConfigValue("image", "zindex", Hyprlang::INT{0});
|
||||
SHADOWABLE("image");
|
||||
CLICKABLE("image");
|
||||
|
||||
m_config.addSpecialCategory("input-field", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
|
||||
m_config.addSpecialConfigValue("input-field", "monitor", Hyprlang::STRING{""});
|
||||
|
@ -320,6 +325,7 @@ void CConfigManager::init() {
|
|||
m_config.addSpecialConfigValue("label", "text_align", Hyprlang::STRING{""});
|
||||
m_config.addSpecialConfigValue("label", "zindex", Hyprlang::INT{0});
|
||||
SHADOWABLE("label");
|
||||
CLICKABLE("label");
|
||||
|
||||
m_config.registerHandler(&::handleSource, "source", {.allowFlags = false});
|
||||
m_config.registerHandler(&::handleBezier, "bezier", {.allowFlags = false});
|
||||
|
@ -356,6 +362,7 @@ void CConfigManager::init() {
|
|||
Debug::log(ERR, "Config has errors:\n{}\nProceeding ignoring faulty entries", result.getError());
|
||||
|
||||
#undef SHADOWABLE
|
||||
#undef CLICKABLE
|
||||
}
|
||||
|
||||
std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
|
||||
|
@ -367,6 +374,8 @@ std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
|
|||
"shadow_boost", m_config.getSpecialConfigValue(name, "shadow_boost", k.c_str()) \
|
||||
}
|
||||
|
||||
#define CLICKABLE(name) {"onclick", m_config.getSpecialConfigValue(name, "onclick", k.c_str())}
|
||||
|
||||
//
|
||||
auto keys = m_config.listKeysForSpecialCategory("background");
|
||||
result.reserve(keys.size());
|
||||
|
@ -414,6 +423,7 @@ std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
|
|||
{"xray", m_config.getSpecialConfigValue("shape", "xray", k.c_str())},
|
||||
{"zindex", m_config.getSpecialConfigValue("shape", "zindex", k.c_str())},
|
||||
SHADOWABLE("shape"),
|
||||
CLICKABLE("shape"),
|
||||
}
|
||||
});
|
||||
// clang-format on
|
||||
|
@ -440,6 +450,7 @@ std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
|
|||
{"reload_cmd", m_config.getSpecialConfigValue("image", "reload_cmd", k.c_str())},
|
||||
{"zindex", m_config.getSpecialConfigValue("image", "zindex", k.c_str())},
|
||||
SHADOWABLE("image"),
|
||||
CLICKABLE("image"),
|
||||
}
|
||||
});
|
||||
// clang-format on
|
||||
|
@ -505,6 +516,7 @@ std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
|
|||
{"text_align", m_config.getSpecialConfigValue("label", "text_align", k.c_str())},
|
||||
{"zindex", m_config.getSpecialConfigValue("label", "zindex", k.c_str())},
|
||||
SHADOWABLE("label"),
|
||||
CLICKABLE("label"),
|
||||
}
|
||||
});
|
||||
// clang-format on
|
||||
|
|
|
@ -9,9 +9,12 @@ CCursorShape::CCursorShape(SP<CCWpCursorShapeManagerV1> mgr) : mgr(mgr) {
|
|||
}
|
||||
|
||||
void CCursorShape::setShape(const wpCursorShapeDeviceV1Shape shape) {
|
||||
if (!dev)
|
||||
if (!g_pSeatManager->m_pPointer)
|
||||
return;
|
||||
|
||||
if (!dev)
|
||||
dev = makeShared<CCWpCursorShapeDeviceV1>(mgr->sendGetPointer(g_pSeatManager->m_pPointer->resource()));
|
||||
|
||||
dev->sendSetShape(lastCursorSerial, shape);
|
||||
}
|
||||
|
||||
|
|
|
@ -139,3 +139,7 @@ void CSessionLockSurface::onCallback() {
|
|||
render();
|
||||
}
|
||||
}
|
||||
|
||||
SP<CCWlSurface> CSessionLockSurface::getWlSurface() {
|
||||
return surface;
|
||||
}
|
||||
|
|
|
@ -17,15 +17,16 @@ class CSessionLockSurface {
|
|||
CSessionLockSurface(const SP<COutput>& pOutput);
|
||||
~CSessionLockSurface();
|
||||
|
||||
void configure(const Vector2D& size, uint32_t serial);
|
||||
void configure(const Vector2D& size, uint32_t serial);
|
||||
|
||||
bool readyForFrame = false;
|
||||
bool readyForFrame = false;
|
||||
|
||||
float fractionalScale = 1.0;
|
||||
float fractionalScale = 1.0;
|
||||
|
||||
void render();
|
||||
void onCallback();
|
||||
void onScaleUpdate();
|
||||
void render();
|
||||
void onCallback();
|
||||
void onScaleUpdate();
|
||||
SP<CCWlSurface> getWlSurface();
|
||||
|
||||
private:
|
||||
WP<COutput> m_outputRef;
|
||||
|
|
|
@ -26,7 +26,13 @@ void CSeatManager::registerSeat(SP<CCWlSeat> seat) {
|
|||
if (caps & WL_SEAT_CAPABILITY_POINTER) {
|
||||
m_pPointer = makeShared<CCWlPointer>(r->sendGetPointer());
|
||||
|
||||
static const auto HIDECURSOR = g_pConfigManager->getValue<Hyprlang::INT>("general:hide_cursor");
|
||||
m_pPointer->setMotion([](CCWlPointer* r, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) {
|
||||
g_pHyprlock->m_vMouseLocation = {wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)};
|
||||
|
||||
if (!*HIDECURSOR)
|
||||
g_pHyprlock->onHover(g_pHyprlock->m_vMouseLocation);
|
||||
|
||||
if (std::chrono::system_clock::now() > g_pHyprlock->m_tGraceEnds)
|
||||
return;
|
||||
|
||||
|
@ -40,16 +46,34 @@ void CSeatManager::registerSeat(SP<CCWlSeat> seat) {
|
|||
if (!m_pCursorShape)
|
||||
return;
|
||||
|
||||
static const auto HIDE = g_pConfigManager->getValue<Hyprlang::INT>("general:hide_cursor");
|
||||
|
||||
m_pCursorShape->lastCursorSerial = serial;
|
||||
|
||||
if (*HIDE)
|
||||
if (*HIDECURSOR)
|
||||
m_pCursorShape->hideCursor();
|
||||
else
|
||||
m_pCursorShape->setShape(wpCursorShapeDeviceV1Shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
|
||||
|
||||
g_pHyprlock->m_vLastEnterCoords = {wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y)};
|
||||
|
||||
if (*HIDECURSOR)
|
||||
return;
|
||||
|
||||
for (const auto& POUTPUT : g_pHyprlock->m_vOutputs) {
|
||||
if (!POUTPUT->m_sessionLockSurface)
|
||||
continue;
|
||||
|
||||
const auto& PWLSURFACE = POUTPUT->m_sessionLockSurface->getWlSurface();
|
||||
if (PWLSURFACE->resource() == surf)
|
||||
g_pHyprlock->m_focusedOutput = POUTPUT;
|
||||
}
|
||||
});
|
||||
|
||||
m_pPointer->setLeave([](CCWlPointer* r, uint32_t serial, wl_proxy* surf) { g_pHyprlock->m_focusedOutput.reset(); });
|
||||
|
||||
m_pPointer->setButton([](CCWlPointer* r, uint32_t serial, uint32_t time, uint32_t button, wl_pointer_button_state state) {
|
||||
if (*HIDECURSOR)
|
||||
return;
|
||||
g_pHyprlock->onClick(button, state == WL_POINTER_BUTTON_STATE_PRESSED, g_pHyprlock->m_vMouseLocation);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -669,6 +669,61 @@ void CHyprlock::handleKeySym(xkb_keysym_t sym, bool composed) {
|
|||
}
|
||||
}
|
||||
|
||||
void CHyprlock::onClick(uint32_t button, bool down, const Vector2D& pos) {
|
||||
if (!m_focusedOutput.lock())
|
||||
return;
|
||||
|
||||
// TODO: add the UNLIKELY marco from Hyprland
|
||||
if (!m_focusedOutput->m_sessionLockSurface)
|
||||
return;
|
||||
|
||||
const auto SCALEDPOS = pos * m_focusedOutput->m_sessionLockSurface->fractionalScale;
|
||||
const auto widgets = g_pRenderer->getOrCreateWidgetsFor(*m_focusedOutput->m_sessionLockSurface);
|
||||
for (const auto& widget : widgets) {
|
||||
if (widget->containsPoint(SCALEDPOS))
|
||||
widget->onClick(button, down, pos);
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprlock::onHover(const Vector2D& pos) {
|
||||
if (!m_focusedOutput.lock())
|
||||
return;
|
||||
|
||||
if (!m_focusedOutput->m_sessionLockSurface)
|
||||
return;
|
||||
|
||||
bool outputNeedsRedraw = false;
|
||||
bool cursorChanged = false;
|
||||
|
||||
const auto SCALEDPOS = pos * m_focusedOutput->m_sessionLockSurface->fractionalScale;
|
||||
const auto widgets = g_pRenderer->getOrCreateWidgetsFor(*m_focusedOutput->m_sessionLockSurface);
|
||||
for (const auto& widget : widgets) {
|
||||
const bool CONTAINSPOINT = widget->containsPoint(SCALEDPOS);
|
||||
const bool HOVERED = widget->isHovered();
|
||||
|
||||
if (CONTAINSPOINT) {
|
||||
if (!HOVERED) {
|
||||
widget->setHover(true);
|
||||
widget->onHover(pos);
|
||||
outputNeedsRedraw = true;
|
||||
}
|
||||
|
||||
if (!cursorChanged)
|
||||
cursorChanged = true;
|
||||
|
||||
} else if (HOVERED) {
|
||||
widget->setHover(false);
|
||||
outputNeedsRedraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cursorChanged)
|
||||
g_pSeatManager->m_pCursorShape->setShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT);
|
||||
|
||||
if (outputNeedsRedraw)
|
||||
m_focusedOutput->m_sessionLockSurface->render();
|
||||
}
|
||||
|
||||
bool CHyprlock::acquireSessionLock() {
|
||||
Debug::log(LOG, "Locking session");
|
||||
m_sLockState.lock = makeShared<CCExtSessionLockV1>(m_sWaylandState.sessionLock->sendLock());
|
||||
|
@ -817,19 +872,6 @@ void CHyprlock::enqueueForceUpdateTimers() {
|
|||
nullptr, false);
|
||||
}
|
||||
|
||||
std::string CHyprlock::spawnSync(const std::string& cmd) {
|
||||
CProcess proc("/bin/sh", {"-c", cmd});
|
||||
if (!proc.runSync()) {
|
||||
Debug::log(ERR, "Failed to run \"{}\"", cmd);
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!proc.stdErr().empty())
|
||||
Debug::log(ERR, "Shell command \"{}\" STDERR:\n{}", cmd, proc.stdErr());
|
||||
|
||||
return proc.stdOut();
|
||||
}
|
||||
|
||||
SP<CCZwlrScreencopyManagerV1> CHyprlock::getScreencopy() {
|
||||
return m_sWaylandState.screencopy;
|
||||
}
|
||||
|
|
|
@ -48,9 +48,9 @@ class CHyprlock {
|
|||
bool acquireSessionLock();
|
||||
void releaseSessionLock();
|
||||
|
||||
std::string spawnSync(const std::string& cmd);
|
||||
|
||||
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);
|
||||
|
@ -95,6 +95,9 @@ class CHyprlock {
|
|||
//
|
||||
std::chrono::system_clock::time_point m_tGraceEnds;
|
||||
Vector2D m_vLastEnterCoords = {};
|
||||
WP<COutput> m_focusedOutput;
|
||||
|
||||
Vector2D m_vMouseLocation = {};
|
||||
|
||||
std::shared_ptr<CTimer> m_pKeyRepeatTimer = nullptr;
|
||||
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
#include "MiscFunctions.hpp"
|
||||
#include "Log.hpp"
|
||||
#include <hyprutils/string/String.hpp>
|
||||
#include <hyprutils/os/Process.hpp>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace Hyprutils::String;
|
||||
using namespace Hyprutils::OS;
|
||||
|
||||
std::string absolutePath(const std::string& rawpath, const std::string& currentDir) {
|
||||
std::filesystem::path path(rawpath);
|
||||
|
@ -137,3 +139,22 @@ int createPoolFile(size_t size, std::string& name) {
|
|||
|
||||
return FD;
|
||||
}
|
||||
|
||||
std::string spawnSync(const std::string& cmd) {
|
||||
CProcess proc("/bin/sh", {"-c", cmd});
|
||||
if (!proc.runSync()) {
|
||||
Debug::log(ERR, "Failed to run \"{}\"", cmd);
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!proc.stdErr().empty())
|
||||
Debug::log(ERR, "Shell command \"{}\" STDERR:\n{}", cmd, proc.stdErr());
|
||||
|
||||
return proc.stdOut();
|
||||
}
|
||||
|
||||
void spawnAsync(const std::string& cmd) {
|
||||
CProcess proc("/bin/sh", {"-c", cmd});
|
||||
if (!proc.runAsync())
|
||||
Debug::log(ERR, "Failed to start \"{}\"", cmd);
|
||||
}
|
||||
|
|
|
@ -7,3 +7,5 @@
|
|||
std::string absolutePath(const std::string&, const std::string&);
|
||||
int64_t configStringToInt(const std::string& VALUE);
|
||||
int createPoolFile(size_t size, std::string& name);
|
||||
std::string spawnSync(const std::string& cmd);
|
||||
void spawnAsync(const std::string& cmd);
|
||||
|
|
|
@ -107,7 +107,7 @@ int main(int argc, char** argv, char** envp) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (noFadeIn)
|
||||
if (noFadeIn || immediate)
|
||||
g_pConfigManager->m_AnimationTree.setConfigForNode("fadeIn", false, 0.f, "default");
|
||||
|
||||
try {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#include "../config/ConfigManager.hpp"
|
||||
#include "../core/Egl.hpp"
|
||||
#include <cairo/cairo.h>
|
||||
#include <magic.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
|
@ -218,7 +217,7 @@ void CAsyncResourceGatherer::renderText(const SPreloadRequest& rq) {
|
|||
const bool ISCMD = rq.props.contains("cmd") ? std::any_cast<bool>(rq.props.at("cmd")) : false;
|
||||
|
||||
static const auto TRIM = g_pConfigManager->getValue<Hyprlang::INT>("general:text_trim");
|
||||
std::string text = ISCMD ? g_pHyprlock->spawnSync(rq.asset) : rq.asset;
|
||||
std::string text = ISCMD ? spawnSync(rq.asset) : rq.asset;
|
||||
|
||||
if (*TRIM) {
|
||||
text.erase(0, text.find_first_not_of(" \n\r\t"));
|
||||
|
|
|
@ -117,6 +117,6 @@ CFramebuffer::~CFramebuffer() {
|
|||
release();
|
||||
}
|
||||
|
||||
bool CFramebuffer::isAllocated() {
|
||||
bool CFramebuffer::isAllocated() const {
|
||||
return m_iFb != (GLuint)-1;
|
||||
}
|
|
@ -13,7 +13,7 @@ class CFramebuffer {
|
|||
void bind() const;
|
||||
void release();
|
||||
void reset();
|
||||
bool isAllocated();
|
||||
bool isAllocated() const;
|
||||
|
||||
Vector2D m_vSize;
|
||||
|
||||
|
|
|
@ -406,7 +406,7 @@ std::vector<SP<IWidget>>& CRenderer::getOrCreateWidgetsFor(const CSessionLockSur
|
|||
|
||||
const auto POUTPUT = surf.m_outputRef.lock();
|
||||
for (auto& c : CWIDGETS) {
|
||||
if (!c.monitor.empty() && c.monitor != POUTPUT->stringPort && !POUTPUT->stringDesc.starts_with(c.monitor) && !POUTPUT->stringDesc.starts_with("desc:" + c.monitor))
|
||||
if (!c.monitor.empty() && c.monitor != POUTPUT->stringPort && !POUTPUT->stringDesc.starts_with(c.monitor) && !("desc:" + POUTPUT->stringDesc).starts_with(c.monitor))
|
||||
continue;
|
||||
|
||||
// by type
|
||||
|
|
|
@ -48,27 +48,26 @@ class CRenderer {
|
|||
|
||||
void startFadeIn();
|
||||
void startFadeOut(bool unlock = false, bool immediate = true);
|
||||
std::vector<SP<IWidget>>& getOrCreateWidgetsFor(const CSessionLockSurface& surf);
|
||||
|
||||
private:
|
||||
widgetMap_t widgets;
|
||||
widgetMap_t widgets;
|
||||
|
||||
std::vector<SP<IWidget>>& getOrCreateWidgetsFor(const CSessionLockSurface& surf);
|
||||
CShader rectShader;
|
||||
CShader texShader;
|
||||
CShader texMixShader;
|
||||
CShader blurShader1;
|
||||
CShader blurShader2;
|
||||
CShader blurPrepareShader;
|
||||
CShader blurFinishShader;
|
||||
CShader borderShader;
|
||||
|
||||
CShader rectShader;
|
||||
CShader texShader;
|
||||
CShader texMixShader;
|
||||
CShader blurShader1;
|
||||
CShader blurShader2;
|
||||
CShader blurPrepareShader;
|
||||
CShader blurFinishShader;
|
||||
CShader borderShader;
|
||||
Mat3x3 projMatrix = Mat3x3::identity();
|
||||
Mat3x3 projection;
|
||||
|
||||
Mat3x3 projMatrix = Mat3x3::identity();
|
||||
Mat3x3 projection;
|
||||
PHLANIMVAR<float> opacity;
|
||||
|
||||
PHLANIMVAR<float> opacity;
|
||||
|
||||
std::vector<GLint> boundFBs;
|
||||
std::vector<GLint> boundFBs;
|
||||
};
|
||||
|
||||
inline UP<CRenderer> g_pRenderer;
|
||||
|
|
|
@ -240,7 +240,7 @@ void CBackground::onReloadTimerUpdate() {
|
|||
// Path parsing and early returns
|
||||
|
||||
if (!reloadCommand.empty()) {
|
||||
path = g_pHyprlock->spawnSync(reloadCommand);
|
||||
path = spawnSync(reloadCommand);
|
||||
|
||||
if (path.ends_with('\n'))
|
||||
path.pop_back();
|
||||
|
|
|
@ -266,3 +266,15 @@ IWidget::SFormatResult IWidget::formatString(std::string in) {
|
|||
result.formatted = in;
|
||||
return result;
|
||||
}
|
||||
|
||||
void IWidget::setHover(bool hover) {
|
||||
hovered = hover;
|
||||
}
|
||||
|
||||
bool IWidget::isHovered() const {
|
||||
return hovered;
|
||||
}
|
||||
|
||||
bool IWidget::containsPoint(const Vector2D& pos) const {
|
||||
return getBoundingBoxWl().containsPoint(pos);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "../../helpers/Math.hpp"
|
||||
#include "../../defines.hpp"
|
||||
#include "../../helpers/Math.hpp"
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <any>
|
||||
|
@ -24,6 +24,13 @@ class IWidget {
|
|||
static int roundingForBox(const CBox& box, int roundingConfig);
|
||||
static int roundingForBorderBox(const CBox& borderBox, int roundingConfig, int thickness);
|
||||
|
||||
virtual CBox getBoundingBoxWl() const {
|
||||
return CBox();
|
||||
};
|
||||
virtual void onClick(uint32_t button, bool down, const Vector2D& pos) {}
|
||||
virtual void onHover(const Vector2D& pos) {}
|
||||
bool containsPoint(const Vector2D& pos) const;
|
||||
|
||||
struct SFormatResult {
|
||||
std::string formatted;
|
||||
float updateEveryMs = 0; // 0 means don't (static)
|
||||
|
@ -33,4 +40,10 @@ class IWidget {
|
|||
};
|
||||
|
||||
static SFormatResult formatString(std::string in);
|
||||
|
||||
void setHover(bool hover);
|
||||
bool isHovered() const;
|
||||
|
||||
private:
|
||||
bool hovered = false;
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../../config/ConfigDataValues.hpp"
|
||||
#include <cmath>
|
||||
#include <hyprlang.hpp>
|
||||
#include <hyprutils/math/Vector2D.hpp>
|
||||
|
||||
CImage::~CImage() {
|
||||
reset();
|
||||
|
@ -31,7 +32,7 @@ void CImage::onTimerUpdate() {
|
|||
const std::string OLDPATH = path;
|
||||
|
||||
if (!reloadCommand.empty()) {
|
||||
path = g_pHyprlock->spawnSync(reloadCommand);
|
||||
path = spawnSync(reloadCommand);
|
||||
|
||||
if (path.ends_with('\n'))
|
||||
path.pop_back();
|
||||
|
@ -84,18 +85,19 @@ void CImage::configure(const std::unordered_map<std::string, std::any>& props, c
|
|||
shadow.configure(m_self.lock(), props, viewport);
|
||||
|
||||
try {
|
||||
size = std::any_cast<Hyprlang::INT>(props.at("size"));
|
||||
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
|
||||
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
|
||||
color = *CGradientValueData::fromAnyPv(props.at("border_color"));
|
||||
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport);
|
||||
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
||||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
|
||||
size = std::any_cast<Hyprlang::INT>(props.at("size"));
|
||||
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
|
||||
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
|
||||
color = *CGradientValueData::fromAnyPv(props.at("border_color"));
|
||||
configPos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport);
|
||||
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
||||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
|
||||
|
||||
path = std::any_cast<Hyprlang::STRING>(props.at("path"));
|
||||
reloadTime = std::any_cast<Hyprlang::INT>(props.at("reload_time"));
|
||||
reloadCommand = std::any_cast<Hyprlang::STRING>(props.at("reload_cmd"));
|
||||
path = std::any_cast<Hyprlang::STRING>(props.at("path"));
|
||||
reloadTime = std::any_cast<Hyprlang::INT>(props.at("reload_time"));
|
||||
reloadCommand = std::any_cast<Hyprlang::STRING>(props.at("reload_cmd"));
|
||||
onclickCommand = std::any_cast<Hyprlang::STRING>(props.at("onclick"));
|
||||
} catch (const std::bad_any_cast& e) {
|
||||
RASSERT(false, "Failed to construct CImage: {}", e.what()); //
|
||||
} catch (const std::out_of_range& e) {
|
||||
|
@ -196,10 +198,10 @@ bool CImage::draw(const SRenderData& data) {
|
|||
|
||||
shadow.draw(data);
|
||||
|
||||
const auto TEXPOS = posFromHVAlign(viewport, tex->m_vSize, pos, halign, valign, angle);
|
||||
pos = posFromHVAlign(viewport, tex->m_vSize, configPos, halign, valign, angle);
|
||||
|
||||
texbox.x = TEXPOS.x;
|
||||
texbox.y = TEXPOS.y;
|
||||
texbox.x = pos.x;
|
||||
texbox.y = pos.y;
|
||||
|
||||
texbox.round();
|
||||
texbox.rot = angle;
|
||||
|
@ -233,3 +235,23 @@ void CImage::renderUpdate() {
|
|||
|
||||
g_pHyprlock->renderOutput(stringPort);
|
||||
}
|
||||
|
||||
CBox CImage::getBoundingBoxWl() const {
|
||||
if (!imageFB.isAllocated())
|
||||
return CBox{};
|
||||
|
||||
return {
|
||||
Vector2D{pos.x, viewport.y - pos.y - imageFB.m_cTex.m_vSize.y},
|
||||
imageFB.m_cTex.m_vSize,
|
||||
};
|
||||
}
|
||||
|
||||
void CImage::onClick(uint32_t button, bool down, const Vector2D& pos) {
|
||||
if (down && !onclickCommand.empty())
|
||||
spawnAsync(onclickCommand);
|
||||
}
|
||||
|
||||
void CImage::onHover(const Vector2D& pos) {
|
||||
if (!onclickCommand.empty())
|
||||
g_pSeatManager->m_pCursorShape->setShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER);
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@ class CImage : public IWidget {
|
|||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& props, const SP<COutput>& pOutput);
|
||||
virtual bool draw(const SRenderData& data);
|
||||
virtual CBox getBoundingBoxWl() const;
|
||||
virtual void onClick(uint32_t button, bool down, const Vector2D& pos);
|
||||
virtual void onHover(const Vector2D& pos);
|
||||
|
||||
void reset();
|
||||
|
||||
|
@ -42,6 +45,7 @@ class CImage : public IWidget {
|
|||
double angle;
|
||||
CGradientValueData color;
|
||||
Vector2D pos;
|
||||
Vector2D configPos;
|
||||
|
||||
std::string halign, valign, path;
|
||||
|
||||
|
@ -49,6 +53,8 @@ class CImage : public IWidget {
|
|||
|
||||
int reloadTime;
|
||||
std::string reloadCommand;
|
||||
std::string onclickCommand;
|
||||
|
||||
std::filesystem::file_time_type modificationTime;
|
||||
std::shared_ptr<CTimer> imageTimer;
|
||||
CAsyncResourceGatherer::SPreloadRequest request;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../../helpers/Log.hpp"
|
||||
#include "../../core/hyprlock.hpp"
|
||||
#include "../../helpers/Color.hpp"
|
||||
#include "../../helpers/MiscFunctions.hpp"
|
||||
#include "../../config/ConfigDataValues.hpp"
|
||||
#include <hyprlang.hpp>
|
||||
#include <stdexcept>
|
||||
|
@ -79,6 +80,7 @@ void CLabel::configure(const std::unordered_map<std::string, std::any>& props, c
|
|||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
|
||||
angle = angle * M_PI / 180.0;
|
||||
onclickCommand = std::any_cast<Hyprlang::STRING>(props.at("onclick"));
|
||||
|
||||
std::string textAlign = std::any_cast<Hyprlang::STRING>(props.at("text_align"));
|
||||
std::string fontFamily = std::any_cast<Hyprlang::STRING>(props.at("font_family"));
|
||||
|
@ -172,3 +174,23 @@ void CLabel::renderUpdate() {
|
|||
|
||||
g_pHyprlock->renderOutput(outputStringPort);
|
||||
}
|
||||
|
||||
CBox CLabel::getBoundingBoxWl() const {
|
||||
if (!asset)
|
||||
return CBox{};
|
||||
|
||||
return {
|
||||
Vector2D{pos.x, viewport.y - pos.y - asset->texture.m_vSize.y},
|
||||
asset->texture.m_vSize,
|
||||
};
|
||||
}
|
||||
|
||||
void CLabel::onClick(uint32_t button, bool down, const Vector2D& pos) {
|
||||
if (down && !onclickCommand.empty())
|
||||
spawnAsync(onclickCommand);
|
||||
}
|
||||
|
||||
void CLabel::onHover(const Vector2D& pos) {
|
||||
if (!onclickCommand.empty())
|
||||
g_pSeatManager->m_pCursorShape->setShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ class CLabel : public IWidget {
|
|||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
|
||||
virtual bool draw(const SRenderData& data);
|
||||
virtual CBox getBoundingBoxWl() const;
|
||||
virtual void onClick(uint32_t button, bool down, const Vector2D& pos);
|
||||
virtual void onHover(const Vector2D& pos);
|
||||
|
||||
void reset();
|
||||
|
||||
|
@ -43,6 +46,7 @@ class CLabel : public IWidget {
|
|||
std::string resourceID;
|
||||
std::string pendingResourceID; // if dynamic label
|
||||
std::string halign, valign;
|
||||
std::string onclickCommand;
|
||||
SPreloadedAsset* asset = nullptr;
|
||||
|
||||
std::string outputStringPort;
|
||||
|
|
|
@ -473,3 +473,14 @@ void CPasswordInputField::updateColors() {
|
|||
|
||||
colorState.font = fontTarget;
|
||||
}
|
||||
|
||||
CBox CPasswordInputField::getBoundingBoxWl() const {
|
||||
return {
|
||||
Vector2D{pos.x, viewport.y - pos.y - size->value().y},
|
||||
size->value(),
|
||||
};
|
||||
}
|
||||
|
||||
void CPasswordInputField::onHover(const Vector2D& pos) {
|
||||
g_pSeatManager->m_pCursorShape->setShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT);
|
||||
}
|
||||
|
|
|
@ -23,6 +23,8 @@ class CPasswordInputField : public IWidget {
|
|||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
|
||||
virtual bool draw(const SRenderData& data);
|
||||
virtual void onHover(const Vector2D& pos);
|
||||
virtual CBox getBoundingBoxWl() const;
|
||||
|
||||
void reset();
|
||||
void onFadeOutTimer();
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#include "Shape.hpp"
|
||||
#include "../Renderer.hpp"
|
||||
#include "../../config/ConfigDataValues.hpp"
|
||||
#include "../../core/hyprlock.hpp"
|
||||
#include "../../helpers/MiscFunctions.hpp"
|
||||
#include <cmath>
|
||||
#include <hyprlang.hpp>
|
||||
#include <sys/types.h>
|
||||
|
||||
void CShape::registerSelf(const SP<CShape>& self) {
|
||||
m_self = self;
|
||||
|
@ -14,16 +17,17 @@ void CShape::configure(const std::unordered_map<std::string, std::any>& props, c
|
|||
shadow.configure(m_self.lock(), props, viewport);
|
||||
|
||||
try {
|
||||
size = CLayoutValueData::fromAnyPv(props.at("size"))->getAbsolute(viewport);
|
||||
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
|
||||
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
|
||||
color = std::any_cast<Hyprlang::INT>(props.at("color"));
|
||||
borderGrad = *CGradientValueData::fromAnyPv(props.at("border_color"));
|
||||
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport);
|
||||
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
||||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
|
||||
xray = std::any_cast<Hyprlang::INT>(props.at("xray"));
|
||||
size = CLayoutValueData::fromAnyPv(props.at("size"))->getAbsolute(viewport);
|
||||
rounding = std::any_cast<Hyprlang::INT>(props.at("rounding"));
|
||||
border = std::any_cast<Hyprlang::INT>(props.at("border_size"));
|
||||
color = std::any_cast<Hyprlang::INT>(props.at("color"));
|
||||
borderGrad = *CGradientValueData::fromAnyPv(props.at("border_color"));
|
||||
pos = CLayoutValueData::fromAnyPv(props.at("position"))->getAbsolute(viewport);
|
||||
halign = std::any_cast<Hyprlang::STRING>(props.at("halign"));
|
||||
valign = std::any_cast<Hyprlang::STRING>(props.at("valign"));
|
||||
angle = std::any_cast<Hyprlang::FLOAT>(props.at("rotate"));
|
||||
xray = std::any_cast<Hyprlang::INT>(props.at("xray"));
|
||||
onclickCommand = std::any_cast<Hyprlang::STRING>(props.at("onclick"));
|
||||
} catch (const std::bad_any_cast& e) {
|
||||
RASSERT(false, "Failed to construct CShape: {}", e.what()); //
|
||||
} catch (const std::out_of_range& e) {
|
||||
|
@ -100,3 +104,19 @@ bool CShape::draw(const SRenderData& data) {
|
|||
|
||||
return data.opacity < 1.0;
|
||||
}
|
||||
CBox CShape::getBoundingBoxWl() const {
|
||||
return {
|
||||
Vector2D{pos.x, viewport.y - pos.y - size.y},
|
||||
size,
|
||||
};
|
||||
}
|
||||
|
||||
void CShape::onClick(uint32_t button, bool down, const Vector2D& pos) {
|
||||
if (down && !onclickCommand.empty())
|
||||
spawnAsync(onclickCommand);
|
||||
}
|
||||
|
||||
void CShape::onHover(const Vector2D& pos) {
|
||||
if (!onclickCommand.empty())
|
||||
g_pSeatManager->m_pCursorShape->setShape(WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER);
|
||||
}
|
||||
|
|
|
@ -18,6 +18,9 @@ class CShape : public IWidget {
|
|||
|
||||
virtual void configure(const std::unordered_map<std::string, std::any>& prop, const SP<COutput>& pOutput);
|
||||
virtual bool draw(const SRenderData& data);
|
||||
virtual CBox getBoundingBoxWl() const;
|
||||
virtual void onClick(uint32_t button, bool down, const Vector2D& pos);
|
||||
virtual void onHover(const Vector2D& pos);
|
||||
|
||||
private:
|
||||
WP<CShape> m_self;
|
||||
|
@ -38,6 +41,7 @@ class CShape : public IWidget {
|
|||
std::string halign, valign;
|
||||
|
||||
bool firstRender = true;
|
||||
std::string onclickCommand;
|
||||
|
||||
Vector2D viewport;
|
||||
CShadowable shadow;
|
||||
|
|
Loading…
Reference in a new issue