hyprlock/src/config/ConfigManager.cpp

685 lines
33 KiB
C++
Raw Normal View History

2024-02-18 23:08:03 +00:00
#include "ConfigManager.hpp"
#include "ConfigDataValues.hpp"
#include "../helpers/MiscFunctions.hpp"
#include "../helpers/Log.hpp"
#include "../core/AnimationManager.hpp"
#include <hyprlang.hpp>
#include <hyprutils/string/String.hpp>
#include <hyprutils/path/Path.hpp>
2024-02-18 23:08:03 +00:00
#include <filesystem>
#include <glob.h>
#include <cstring>
#include <format>
using namespace Hyprutils::String;
using namespace Hyprutils::Animation;
ICustomConfigValueData::~ICustomConfigValueData() {
; // empty
}
static Hyprlang::CParseResult handleSource(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
const auto RESULT = g_pConfigManager->handleSource(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
result.setError(RESULT.value().c_str());
return result;
}
2024-02-18 23:08:03 +00:00
static Hyprlang::CParseResult handleBezier(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
const auto RESULT = g_pConfigManager->handleBezier(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
result.setError(RESULT.value().c_str());
return result;
}
static Hyprlang::CParseResult handleAnimation(const char* c, const char* v) {
const std::string VALUE = v;
const std::string COMMAND = c;
const auto RESULT = g_pConfigManager->handleAnimation(COMMAND, VALUE);
Hyprlang::CParseResult result;
if (RESULT.has_value())
result.setError(RESULT.value().c_str());
return result;
}
static Hyprlang::CParseResult configHandleLayoutOption(const char* v, void** data) {
const std::string VALUE = v;
Hyprlang::CParseResult result;
if (!*data)
*data = new CLayoutValueData();
const auto DATA = (CLayoutValueData*)(*data);
const auto SPLIT = VALUE.find(',');
if (SPLIT == std::string::npos) {
result.setError(std::format("expected two comma seperated values, got {}", VALUE).c_str());
return result;
}
auto lhs = VALUE.substr(0, SPLIT);
auto rhs = VALUE.substr(SPLIT + 1);
if (rhs.starts_with(" "))
rhs = rhs.substr(1);
if (lhs.contains(",") || rhs.contains(",")) {
result.setError(std::format("too many arguments in {}", VALUE).c_str());
return result;
}
if (lhs.ends_with("%")) {
DATA->m_sIsRelative.x = true;
lhs.pop_back();
}
if (rhs.ends_with("%")) {
DATA->m_sIsRelative.y = true;
rhs.pop_back();
}
try {
DATA->m_vValues = Hyprutils::Math::Vector2D{std::stof(lhs), std::stof(rhs)};
} catch (const std::exception&) {
result.setError(std::format("invalid layout values: {}", VALUE).c_str());
return result;
}
return result;
}
static void configHandleLayoutOptionDestroy(void** data) {
if (*data)
delete reinterpret_cast<CLayoutValueData*>(*data);
}
static Hyprlang::CParseResult configHandleGradientSet(const char* VALUE, void** data) {
const std::string V = VALUE;
if (!*data)
*data = new CGradientValueData();
const auto DATA = reinterpret_cast<CGradientValueData*>(*data);
DATA->m_vColors.clear();
DATA->m_bIsFallback = false;
std::string parseError = "";
std::string rolling = V;
while (!rolling.empty()) {
const auto SPACEPOS = rolling.find(' ');
const bool LAST = SPACEPOS == std::string::npos;
std::string var = rolling.substr(0, SPACEPOS);
if (var.find("rgb") != std::string::npos) { // rgb(a)
const auto CLOSEPARENPOS = rolling.find(')');
if (CLOSEPARENPOS == std::string::npos || CLOSEPARENPOS + 1 >= rolling.length()) {
var = trim(rolling);
rolling.clear();
} else {
var = rolling.substr(0, CLOSEPARENPOS + 1);
rolling = trim(rolling.substr(CLOSEPARENPOS + 2));
}
} else if (var.find("deg") != std::string::npos) { // last arg
try {
DATA->m_fAngle = std::stoi(var.substr(0, var.find("deg"))) * (M_PI / 180.0); // radians
} catch (...) {
Log::logger->log(Log::WARN, "Error parsing gradient {}", V);
parseError = "Error parsing gradient " + V;
}
break;
} else // hex
rolling = trim(rolling.substr(LAST ? rolling.length() : SPACEPOS + 1));
if (DATA->m_vColors.size() >= 10) {
Log::logger->log(Log::WARN, "Error parsing gradient {}: max colors is 10.", V);
parseError = "Error parsing gradient " + V + ": max colors is 10.";
break;
}
if (var.empty())
continue;
try {
DATA->m_vColors.emplace_back(configStringToInt(var));
} catch (std::exception& e) {
Log::logger->log(Log::WARN, "Error parsing gradient {}", V);
parseError = "Error parsing gradient " + V + ": " + e.what();
}
}
if (V.empty()) {
DATA->m_bIsFallback = true;
DATA->m_vColors.emplace_back(0); // transparent
}
if (DATA->m_vColors.size() == 0) {
Log::logger->log(Log::WARN, "Error parsing gradient {}", V);
parseError = "Error parsing gradient " + V + ": No colors?";
DATA->m_vColors.emplace_back(0); // transparent
}
DATA->updateColorsOk();
Hyprlang::CParseResult result;
if (!parseError.empty())
result.setError(parseError.c_str());
return result;
}
static void configHandleGradientDestroy(void** data) {
if (*data)
delete reinterpret_cast<CGradientValueData*>(*data);
}
static std::expected<std::string, std::string> getMainConfigPath() {
static const auto PATHS = Hyprutils::Path::findConfig("hyprlock");
if (PATHS.first.has_value())
return PATHS.first.value();
else
return std::unexpected{"Could not find config. Searched in order: XDG_CONFIG_HOME, HOME, XDG_CONFIG_DIRS, /etc/xdg"};
2024-02-18 23:08:03 +00:00
}
std::expected<std::string, std::string> CConfigManager::resolveConfigPath(std::optional<std::string_view> explicitPath) {
std::string configPath = "";
if (explicitPath.has_value()) {
configPath = explicitPath.value();
configPath = absolutePath(configPath, "");
} else {
auto mainConfigPath = getMainConfigPath();
if (!mainConfigPath.has_value())
return std::unexpected{mainConfigPath.error()};
configPath = mainConfigPath.value();
}
if (!std::filesystem::exists(configPath))
return std::unexpected{std::vformat("No config file at \"{}\"", std::make_format_args(configPath))};
return configPath;
}
CConfigManager::CConfigManager(const char* configPath) :
m_configCurrentPath(configPath), m_config(configPath,
Hyprlang::SConfigOptions{
.throwAllErrors = true,
.allowMissingConfig = false,
}) {
;
2024-02-18 23:08:03 +00:00
}
inline static constexpr auto GRADIENTCONFIG = [](const char* default_value) -> Hyprlang::CUSTOMTYPE {
return Hyprlang::CUSTOMTYPE{&configHandleGradientSet, configHandleGradientDestroy, default_value};
};
inline static constexpr auto LAYOUTCONFIG = [](const char* default_value) -> Hyprlang::CUSTOMTYPE {
return Hyprlang::CUSTOMTYPE{&configHandleLayoutOption, configHandleLayoutOptionDestroy, default_value};
};
2024-02-18 23:08:03 +00:00
void CConfigManager::init() {
2024-03-05 20:24:11 +00:00
#define SHADOWABLE(name) \
m_config.addSpecialConfigValue(name, "shadow_size", Hyprlang::INT{3}); \
2024-03-05 20:28:29 +00:00
m_config.addSpecialConfigValue(name, "shadow_passes", Hyprlang::INT{0}); \
2024-03-05 20:24:11 +00:00
m_config.addSpecialConfigValue(name, "shadow_color", Hyprlang::INT{0xFF000000}); \
m_config.addSpecialConfigValue(name, "shadow_boost", Hyprlang::FLOAT{1.2});
widgets: add onclick feature (#736) * widget: add click handling and point containment methods to IWidget interface * core: add onClick method to handle mouse click events - renderer: move getOrCreateWidgetsFor method declaration to public section * core: update mouse event handling to track mouse location and button clicks * widget: add onclick command handling and point containment to CLabel - config: add onclick special config value to label * assets: add label configuration for keyboard layout switching * config: add onclick configuration for label widgets - add CLICKABLE macro for onclick configuration - replace direct onclick assignment with CLICKABLE macro * core: fix cursor shape initialization and pointer handling - ensure pointer is available before setting cursor shape - initialize cursor shape device if not already done * core: add hover handling and cursor shape updates - implement onHover method to manage widget hover states - update cursor shape based on hover status - ensure all outputs are redrawn after state changes * widgets: add hover state management and bounding box calculations - add setHover and isHovered methods to manage hover state - implement containsPoint method for hit testing - override getBoundingBox in CLabel for accurate positioning - add onHover method in CLabel to change cursor shape * core: add hover handling in pointer motion - invoke onHover method with current mouse location * widgets: add hover handling and bounding box for password input field - add getBoundingBox method to calculate the widget's bounding box - implement onHover method to update cursor shape on hover * widgets: update hover behavior for label widget - modify cursor shape setting to only apply when onclickCommand is not empty * core: optimize hover handling and rendering for lock surfaces - Improve hover state tracking for widgets - reduce unnecessary redraw calls by tracking hover changes - remove redundant renderAllOutputs() call * widgets: add onclick and hover to shape and image * core: trigger hover and onclick only for the currently focused surface * core: handle fractionalScale in onclick and hover * core: don't trigger onclick or hover when hide_cursor is set * misc: remove braces * core: run onclick commands asnychronously --------- Co-authored-by: Memoraike <memoraike@gmail.com>
2025-05-05 17:11:24 +02:00
#define CLICKABLE(name) m_config.addSpecialConfigValue(name, "onclick", Hyprlang::STRING{""});
m_config.addConfigValue("general:text_trim", Hyprlang::INT{1});
2024-02-20 02:54:19 +00:00
m_config.addConfigValue("general:hide_cursor", Hyprlang::INT{0});
m_config.addConfigValue("general:ignore_empty_input", Hyprlang::INT{0});
m_config.addConfigValue("general:immediate_render", Hyprlang::INT{0});
m_config.addConfigValue("general:fractional_scaling", Hyprlang::INT{2});
m_config.addConfigValue("general:screencopy_mode", Hyprlang::INT{0});
m_config.addConfigValue("general:fail_timeout", Hyprlang::INT{2000});
m_config.addConfigValue("auth:pam:enabled", Hyprlang::INT{1});
m_config.addConfigValue("auth:pam:module", Hyprlang::STRING{"hyprlock"});
m_config.addConfigValue("auth:fingerprint:enabled", Hyprlang::INT{0});
m_config.addConfigValue("auth:fingerprint:ready_message", Hyprlang::STRING{"(Scan fingerprint to unlock)"});
m_config.addConfigValue("auth:fingerprint:present_message", Hyprlang::STRING{"Scanning fingerprint"});
m_config.addConfigValue("auth:fingerprint:retry_delay", Hyprlang::INT{250});
2024-02-18 23:08:03 +00:00
m_config.addConfigValue("animations:enabled", Hyprlang::INT{1});
2024-02-18 23:08:03 +00:00
m_config.addSpecialCategory("background", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
m_config.addSpecialConfigValue("background", "monitor", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("background", "path", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("background", "color", Hyprlang::INT{0xFF111111});
2024-02-21 22:19:01 +00:00
m_config.addSpecialConfigValue("background", "blur_size", Hyprlang::INT{8});
m_config.addSpecialConfigValue("background", "blur_passes", Hyprlang::INT{0});
m_config.addSpecialConfigValue("background", "noise", Hyprlang::FLOAT{0.0117});
m_config.addSpecialConfigValue("background", "contrast", Hyprlang::FLOAT{0.8917});
m_config.addSpecialConfigValue("background", "brightness", Hyprlang::FLOAT{0.8172});
m_config.addSpecialConfigValue("background", "vibrancy", Hyprlang::FLOAT{0.1686});
m_config.addSpecialConfigValue("background", "vibrancy_darkness", Hyprlang::FLOAT{0.05});
m_config.addSpecialConfigValue("background", "zindex", Hyprlang::INT{-1});
m_config.addSpecialConfigValue("background", "reload_time", Hyprlang::INT{-1});
m_config.addSpecialConfigValue("background", "reload_cmd", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("background", "crossfade_time", Hyprlang::FLOAT{-1.0});
2024-02-18 23:08:03 +00:00
m_config.addSpecialCategory("shape", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
m_config.addSpecialConfigValue("shape", "monitor", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("shape", "size", LAYOUTCONFIG("100,100"));
m_config.addSpecialConfigValue("shape", "rounding", Hyprlang::INT{0});
m_config.addSpecialConfigValue("shape", "border_size", Hyprlang::INT{0});
m_config.addSpecialConfigValue("shape", "border_color", GRADIENTCONFIG("0xFF00CFE6"));
m_config.addSpecialConfigValue("shape", "color", Hyprlang::INT{0xFF111111});
m_config.addSpecialConfigValue("shape", "position", LAYOUTCONFIG("0,0"));
m_config.addSpecialConfigValue("shape", "halign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("shape", "valign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("shape", "rotate", Hyprlang::FLOAT{0});
m_config.addSpecialConfigValue("shape", "xray", Hyprlang::INT{0});
m_config.addSpecialConfigValue("shape", "zindex", Hyprlang::INT{0});
SHADOWABLE("shape");
widgets: add onclick feature (#736) * widget: add click handling and point containment methods to IWidget interface * core: add onClick method to handle mouse click events - renderer: move getOrCreateWidgetsFor method declaration to public section * core: update mouse event handling to track mouse location and button clicks * widget: add onclick command handling and point containment to CLabel - config: add onclick special config value to label * assets: add label configuration for keyboard layout switching * config: add onclick configuration for label widgets - add CLICKABLE macro for onclick configuration - replace direct onclick assignment with CLICKABLE macro * core: fix cursor shape initialization and pointer handling - ensure pointer is available before setting cursor shape - initialize cursor shape device if not already done * core: add hover handling and cursor shape updates - implement onHover method to manage widget hover states - update cursor shape based on hover status - ensure all outputs are redrawn after state changes * widgets: add hover state management and bounding box calculations - add setHover and isHovered methods to manage hover state - implement containsPoint method for hit testing - override getBoundingBox in CLabel for accurate positioning - add onHover method in CLabel to change cursor shape * core: add hover handling in pointer motion - invoke onHover method with current mouse location * widgets: add hover handling and bounding box for password input field - add getBoundingBox method to calculate the widget's bounding box - implement onHover method to update cursor shape on hover * widgets: update hover behavior for label widget - modify cursor shape setting to only apply when onclickCommand is not empty * core: optimize hover handling and rendering for lock surfaces - Improve hover state tracking for widgets - reduce unnecessary redraw calls by tracking hover changes - remove redundant renderAllOutputs() call * widgets: add onclick and hover to shape and image * core: trigger hover and onclick only for the currently focused surface * core: handle fractionalScale in onclick and hover * core: don't trigger onclick or hover when hide_cursor is set * misc: remove braces * core: run onclick commands asnychronously --------- Co-authored-by: Memoraike <memoraike@gmail.com>
2025-05-05 17:11:24 +02:00
CLICKABLE("shape");
2024-03-16 17:44:44 +03:00
m_config.addSpecialCategory("image", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
m_config.addSpecialConfigValue("image", "monitor", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("image", "path", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("image", "size", Hyprlang::INT{150});
m_config.addSpecialConfigValue("image", "rounding", Hyprlang::INT{-1});
m_config.addSpecialConfigValue("image", "border_size", Hyprlang::INT{4});
m_config.addSpecialConfigValue("image", "border_color", GRADIENTCONFIG("0xFFDDDDDD"));
m_config.addSpecialConfigValue("image", "position", LAYOUTCONFIG("0,0"));
2024-03-16 17:44:44 +03:00
m_config.addSpecialConfigValue("image", "halign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("image", "valign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("image", "rotate", Hyprlang::FLOAT{0});
m_config.addSpecialConfigValue("image", "reload_time", Hyprlang::INT{-1});
m_config.addSpecialConfigValue("image", "reload_cmd", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("image", "zindex", Hyprlang::INT{0});
2024-03-16 17:44:44 +03:00
SHADOWABLE("image");
widgets: add onclick feature (#736) * widget: add click handling and point containment methods to IWidget interface * core: add onClick method to handle mouse click events - renderer: move getOrCreateWidgetsFor method declaration to public section * core: update mouse event handling to track mouse location and button clicks * widget: add onclick command handling and point containment to CLabel - config: add onclick special config value to label * assets: add label configuration for keyboard layout switching * config: add onclick configuration for label widgets - add CLICKABLE macro for onclick configuration - replace direct onclick assignment with CLICKABLE macro * core: fix cursor shape initialization and pointer handling - ensure pointer is available before setting cursor shape - initialize cursor shape device if not already done * core: add hover handling and cursor shape updates - implement onHover method to manage widget hover states - update cursor shape based on hover status - ensure all outputs are redrawn after state changes * widgets: add hover state management and bounding box calculations - add setHover and isHovered methods to manage hover state - implement containsPoint method for hit testing - override getBoundingBox in CLabel for accurate positioning - add onHover method in CLabel to change cursor shape * core: add hover handling in pointer motion - invoke onHover method with current mouse location * widgets: add hover handling and bounding box for password input field - add getBoundingBox method to calculate the widget's bounding box - implement onHover method to update cursor shape on hover * widgets: update hover behavior for label widget - modify cursor shape setting to only apply when onclickCommand is not empty * core: optimize hover handling and rendering for lock surfaces - Improve hover state tracking for widgets - reduce unnecessary redraw calls by tracking hover changes - remove redundant renderAllOutputs() call * widgets: add onclick and hover to shape and image * core: trigger hover and onclick only for the currently focused surface * core: handle fractionalScale in onclick and hover * core: don't trigger onclick or hover when hide_cursor is set * misc: remove braces * core: run onclick commands asnychronously --------- Co-authored-by: Memoraike <memoraike@gmail.com>
2025-05-05 17:11:24 +02:00
CLICKABLE("image");
2024-03-16 17:44:44 +03:00
2024-02-18 23:08:03 +00:00
m_config.addSpecialCategory("input-field", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
m_config.addSpecialConfigValue("input-field", "monitor", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("input-field", "size", LAYOUTCONFIG("400,90"));
2024-02-18 23:08:03 +00:00
m_config.addSpecialConfigValue("input-field", "inner_color", Hyprlang::INT{0xFFDDDDDD});
m_config.addSpecialConfigValue("input-field", "outer_color", GRADIENTCONFIG("0xFF111111"));
2024-02-18 23:08:03 +00:00
m_config.addSpecialConfigValue("input-field", "outline_thickness", Hyprlang::INT{4});
m_config.addSpecialConfigValue("input-field", "dots_size", Hyprlang::FLOAT{0.25});
2024-02-21 11:42:18 +00:00
m_config.addSpecialConfigValue("input-field", "dots_center", Hyprlang::INT{1});
m_config.addSpecialConfigValue("input-field", "dots_spacing", Hyprlang::FLOAT{0.2});
m_config.addSpecialConfigValue("input-field", "dots_rounding", Hyprlang::INT{-1});
m_config.addSpecialConfigValue("input-field", "dots_text_format", Hyprlang::STRING{""});
2024-02-19 01:22:22 +00:00
m_config.addSpecialConfigValue("input-field", "fade_on_empty", Hyprlang::INT{1});
m_config.addSpecialConfigValue("input-field", "fade_timeout", Hyprlang::INT{2000});
m_config.addSpecialConfigValue("input-field", "font_color", Hyprlang::INT{0xFF000000});
m_config.addSpecialConfigValue("input-field", "font_family", Hyprlang::STRING{"Sans"});
2024-02-19 22:45:59 +00:00
m_config.addSpecialConfigValue("input-field", "halign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("input-field", "valign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("input-field", "position", LAYOUTCONFIG("0,0"));
2024-02-19 22:58:59 +00:00
m_config.addSpecialConfigValue("input-field", "placeholder_text", Hyprlang::STRING{"<i>Input Password</i>"});
2024-02-20 14:42:04 +00:00
m_config.addSpecialConfigValue("input-field", "hide_input", Hyprlang::INT{0});
m_config.addSpecialConfigValue("input-field", "hide_input_base_color", Hyprlang::INT{0xEE00FF99});
m_config.addSpecialConfigValue("input-field", "rounding", Hyprlang::INT{-1});
m_config.addSpecialConfigValue("input-field", "check_color", GRADIENTCONFIG("0xFF22CC88"));
m_config.addSpecialConfigValue("input-field", "fail_color", GRADIENTCONFIG("0xFFCC2222"));
m_config.addSpecialConfigValue("input-field", "fail_text", Hyprlang::STRING{"<i>$FAIL</i>"});
m_config.addSpecialConfigValue("input-field", "check_text", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("input-field", "capslock_color", GRADIENTCONFIG(""));
m_config.addSpecialConfigValue("input-field", "numlock_color", GRADIENTCONFIG(""));
m_config.addSpecialConfigValue("input-field", "bothlock_color", GRADIENTCONFIG(""));
m_config.addSpecialConfigValue("input-field", "invert_numlock", Hyprlang::INT{0});
m_config.addSpecialConfigValue("input-field", "swap_font_color", Hyprlang::INT{0});
m_config.addSpecialConfigValue("input-field", "zindex", Hyprlang::INT{0});
2024-03-05 20:24:11 +00:00
SHADOWABLE("input-field");
2024-02-18 23:08:03 +00:00
2024-02-19 16:26:08 +00:00
m_config.addSpecialCategory("label", Hyprlang::SSpecialCategoryOptions{.key = nullptr, .anonymousKeyBased = true});
m_config.addSpecialConfigValue("label", "monitor", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("label", "position", LAYOUTCONFIG("0,0"));
2024-02-19 16:26:08 +00:00
m_config.addSpecialConfigValue("label", "color", Hyprlang::INT{0xFFFFFFFF});
m_config.addSpecialConfigValue("label", "font_size", Hyprlang::INT{16});
m_config.addSpecialConfigValue("label", "text", Hyprlang::STRING{"Sample Text"});
m_config.addSpecialConfigValue("label", "font_family", Hyprlang::STRING{"Sans"});
m_config.addSpecialConfigValue("label", "halign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("label", "valign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("label", "rotate", Hyprlang::FLOAT{0});
m_config.addSpecialConfigValue("label", "text_align", Hyprlang::STRING{""});
m_config.addSpecialConfigValue("label", "zindex", Hyprlang::INT{0});
2024-03-05 20:24:11 +00:00
SHADOWABLE("label");
widgets: add onclick feature (#736) * widget: add click handling and point containment methods to IWidget interface * core: add onClick method to handle mouse click events - renderer: move getOrCreateWidgetsFor method declaration to public section * core: update mouse event handling to track mouse location and button clicks * widget: add onclick command handling and point containment to CLabel - config: add onclick special config value to label * assets: add label configuration for keyboard layout switching * config: add onclick configuration for label widgets - add CLICKABLE macro for onclick configuration - replace direct onclick assignment with CLICKABLE macro * core: fix cursor shape initialization and pointer handling - ensure pointer is available before setting cursor shape - initialize cursor shape device if not already done * core: add hover handling and cursor shape updates - implement onHover method to manage widget hover states - update cursor shape based on hover status - ensure all outputs are redrawn after state changes * widgets: add hover state management and bounding box calculations - add setHover and isHovered methods to manage hover state - implement containsPoint method for hit testing - override getBoundingBox in CLabel for accurate positioning - add onHover method in CLabel to change cursor shape * core: add hover handling in pointer motion - invoke onHover method with current mouse location * widgets: add hover handling and bounding box for password input field - add getBoundingBox method to calculate the widget's bounding box - implement onHover method to update cursor shape on hover * widgets: update hover behavior for label widget - modify cursor shape setting to only apply when onclickCommand is not empty * core: optimize hover handling and rendering for lock surfaces - Improve hover state tracking for widgets - reduce unnecessary redraw calls by tracking hover changes - remove redundant renderAllOutputs() call * widgets: add onclick and hover to shape and image * core: trigger hover and onclick only for the currently focused surface * core: handle fractionalScale in onclick and hover * core: don't trigger onclick or hover when hide_cursor is set * misc: remove braces * core: run onclick commands asnychronously --------- Co-authored-by: Memoraike <memoraike@gmail.com>
2025-05-05 17:11:24 +02:00
CLICKABLE("label");
2024-02-19 16:26:08 +00:00
m_config.registerHandler(&::handleSource, "source", {.allowFlags = false});
m_config.registerHandler(&::handleBezier, "bezier", {.allowFlags = false});
m_config.registerHandler(&::handleAnimation, "animation", {.allowFlags = false});
//
// Init Animations
//
m_AnimationTree.createNode("global");
// toplevel
m_AnimationTree.createNode("fade", "global");
m_AnimationTree.createNode("inputField", "global");
// inputField
m_AnimationTree.createNode("inputFieldColors", "inputField");
m_AnimationTree.createNode("inputFieldFade", "inputField");
m_AnimationTree.createNode("inputFieldWidth", "inputField");
m_AnimationTree.createNode("inputFieldDots", "inputField");
// fade
m_AnimationTree.createNode("fadeIn", "fade");
m_AnimationTree.createNode("fadeOut", "fade");
// set config for root node
m_AnimationTree.setConfigForNode("global", 1, 8.f, "default");
m_AnimationTree.setConfigForNode("inputFieldColors", 1, 8.f, "linear");
2024-02-18 23:08:03 +00:00
m_config.commence();
auto result = m_config.parse();
if (result.error)
Log::logger->log(Log::ERR, "Config has errors:\n{}\nProceeding ignoring faulty entries", result.getError());
2024-03-05 20:24:11 +00:00
#undef SHADOWABLE
widgets: add onclick feature (#736) * widget: add click handling and point containment methods to IWidget interface * core: add onClick method to handle mouse click events - renderer: move getOrCreateWidgetsFor method declaration to public section * core: update mouse event handling to track mouse location and button clicks * widget: add onclick command handling and point containment to CLabel - config: add onclick special config value to label * assets: add label configuration for keyboard layout switching * config: add onclick configuration for label widgets - add CLICKABLE macro for onclick configuration - replace direct onclick assignment with CLICKABLE macro * core: fix cursor shape initialization and pointer handling - ensure pointer is available before setting cursor shape - initialize cursor shape device if not already done * core: add hover handling and cursor shape updates - implement onHover method to manage widget hover states - update cursor shape based on hover status - ensure all outputs are redrawn after state changes * widgets: add hover state management and bounding box calculations - add setHover and isHovered methods to manage hover state - implement containsPoint method for hit testing - override getBoundingBox in CLabel for accurate positioning - add onHover method in CLabel to change cursor shape * core: add hover handling in pointer motion - invoke onHover method with current mouse location * widgets: add hover handling and bounding box for password input field - add getBoundingBox method to calculate the widget's bounding box - implement onHover method to update cursor shape on hover * widgets: update hover behavior for label widget - modify cursor shape setting to only apply when onclickCommand is not empty * core: optimize hover handling and rendering for lock surfaces - Improve hover state tracking for widgets - reduce unnecessary redraw calls by tracking hover changes - remove redundant renderAllOutputs() call * widgets: add onclick and hover to shape and image * core: trigger hover and onclick only for the currently focused surface * core: handle fractionalScale in onclick and hover * core: don't trigger onclick or hover when hide_cursor is set * misc: remove braces * core: run onclick commands asnychronously --------- Co-authored-by: Memoraike <memoraike@gmail.com>
2025-05-05 17:11:24 +02:00
#undef CLICKABLE
2024-02-18 23:08:03 +00:00
}
std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
std::vector<CConfigManager::SWidgetConfig> result;
2024-03-05 20:24:11 +00:00
#define SHADOWABLE(name) \
{"shadow_size", m_config.getSpecialConfigValue(name, "shadow_size", k.c_str())}, {"shadow_passes", m_config.getSpecialConfigValue(name, "shadow_passes", k.c_str())}, \
{"shadow_color", m_config.getSpecialConfigValue(name, "shadow_color", k.c_str())}, {"shadow_boost", m_config.getSpecialConfigValue(name, "shadow_boost", k.c_str())}
2024-03-05 20:24:11 +00:00
#define CLICKABLE(name) \
{ "onclick", m_config.getSpecialConfigValue(name, "onclick", k.c_str()) }
widgets: add onclick feature (#736) * widget: add click handling and point containment methods to IWidget interface * core: add onClick method to handle mouse click events - renderer: move getOrCreateWidgetsFor method declaration to public section * core: update mouse event handling to track mouse location and button clicks * widget: add onclick command handling and point containment to CLabel - config: add onclick special config value to label * assets: add label configuration for keyboard layout switching * config: add onclick configuration for label widgets - add CLICKABLE macro for onclick configuration - replace direct onclick assignment with CLICKABLE macro * core: fix cursor shape initialization and pointer handling - ensure pointer is available before setting cursor shape - initialize cursor shape device if not already done * core: add hover handling and cursor shape updates - implement onHover method to manage widget hover states - update cursor shape based on hover status - ensure all outputs are redrawn after state changes * widgets: add hover state management and bounding box calculations - add setHover and isHovered methods to manage hover state - implement containsPoint method for hit testing - override getBoundingBox in CLabel for accurate positioning - add onHover method in CLabel to change cursor shape * core: add hover handling in pointer motion - invoke onHover method with current mouse location * widgets: add hover handling and bounding box for password input field - add getBoundingBox method to calculate the widget's bounding box - implement onHover method to update cursor shape on hover * widgets: update hover behavior for label widget - modify cursor shape setting to only apply when onclickCommand is not empty * core: optimize hover handling and rendering for lock surfaces - Improve hover state tracking for widgets - reduce unnecessary redraw calls by tracking hover changes - remove redundant renderAllOutputs() call * widgets: add onclick and hover to shape and image * core: trigger hover and onclick only for the currently focused surface * core: handle fractionalScale in onclick and hover * core: don't trigger onclick or hover when hide_cursor is set * misc: remove braces * core: run onclick commands asnychronously --------- Co-authored-by: Memoraike <memoraike@gmail.com>
2025-05-05 17:11:24 +02:00
2024-02-18 23:08:03 +00:00
//
auto keys = m_config.listKeysForSpecialCategory("background");
result.reserve(keys.size());
2024-02-18 23:08:03 +00:00
for (auto& k : keys) {
// clang-format off
result.push_back(CConfigManager::SWidgetConfig{
.type = "background",
.monitor = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("background", "monitor", k.c_str())),
.values = {
2024-02-18 23:08:03 +00:00
{"path", m_config.getSpecialConfigValue("background", "path", k.c_str())},
{"color", m_config.getSpecialConfigValue("background", "color", k.c_str())},
2024-02-21 22:19:01 +00:00
{"blur_size", m_config.getSpecialConfigValue("background", "blur_size", k.c_str())},
{"blur_passes", m_config.getSpecialConfigValue("background", "blur_passes", k.c_str())},
{"noise", m_config.getSpecialConfigValue("background", "noise", k.c_str())},
{"contrast", m_config.getSpecialConfigValue("background", "contrast", k.c_str())},
{"vibrancy", m_config.getSpecialConfigValue("background", "vibrancy", k.c_str())},
{"brightness", m_config.getSpecialConfigValue("background", "brightness", k.c_str())},
{"vibrancy_darkness", m_config.getSpecialConfigValue("background", "vibrancy_darkness", k.c_str())},
{"zindex", m_config.getSpecialConfigValue("background", "zindex", k.c_str())},
{"reload_time", m_config.getSpecialConfigValue("background", "reload_time", k.c_str())},
{"reload_cmd", m_config.getSpecialConfigValue("background", "reload_cmd", k.c_str())},
{"crossfade_time", m_config.getSpecialConfigValue("background", "crossfade_time", k.c_str())},
2024-02-18 23:08:03 +00:00
}
});
// clang-format on
}
//
keys = m_config.listKeysForSpecialCategory("shape");
for (auto& k : keys) {
// clang-format off
result.push_back(CConfigManager::SWidgetConfig{
.type = "shape",
.monitor = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("shape", "monitor", k.c_str())),
.values = {
{"size", m_config.getSpecialConfigValue("shape", "size", k.c_str())},
{"rounding", m_config.getSpecialConfigValue("shape", "rounding", k.c_str())},
{"border_size", m_config.getSpecialConfigValue("shape", "border_size", k.c_str())},
{"border_color", m_config.getSpecialConfigValue("shape", "border_color", k.c_str())},
{"color", m_config.getSpecialConfigValue("shape", "color", k.c_str())},
{"position", m_config.getSpecialConfigValue("shape", "position", k.c_str())},
{"halign", m_config.getSpecialConfigValue("shape", "halign", k.c_str())},
{"valign", m_config.getSpecialConfigValue("shape", "valign", k.c_str())},
{"rotate", m_config.getSpecialConfigValue("shape", "rotate", k.c_str())},
{"xray", m_config.getSpecialConfigValue("shape", "xray", k.c_str())},
{"zindex", m_config.getSpecialConfigValue("shape", "zindex", k.c_str())},
SHADOWABLE("shape"),
widgets: add onclick feature (#736) * widget: add click handling and point containment methods to IWidget interface * core: add onClick method to handle mouse click events - renderer: move getOrCreateWidgetsFor method declaration to public section * core: update mouse event handling to track mouse location and button clicks * widget: add onclick command handling and point containment to CLabel - config: add onclick special config value to label * assets: add label configuration for keyboard layout switching * config: add onclick configuration for label widgets - add CLICKABLE macro for onclick configuration - replace direct onclick assignment with CLICKABLE macro * core: fix cursor shape initialization and pointer handling - ensure pointer is available before setting cursor shape - initialize cursor shape device if not already done * core: add hover handling and cursor shape updates - implement onHover method to manage widget hover states - update cursor shape based on hover status - ensure all outputs are redrawn after state changes * widgets: add hover state management and bounding box calculations - add setHover and isHovered methods to manage hover state - implement containsPoint method for hit testing - override getBoundingBox in CLabel for accurate positioning - add onHover method in CLabel to change cursor shape * core: add hover handling in pointer motion - invoke onHover method with current mouse location * widgets: add hover handling and bounding box for password input field - add getBoundingBox method to calculate the widget's bounding box - implement onHover method to update cursor shape on hover * widgets: update hover behavior for label widget - modify cursor shape setting to only apply when onclickCommand is not empty * core: optimize hover handling and rendering for lock surfaces - Improve hover state tracking for widgets - reduce unnecessary redraw calls by tracking hover changes - remove redundant renderAllOutputs() call * widgets: add onclick and hover to shape and image * core: trigger hover and onclick only for the currently focused surface * core: handle fractionalScale in onclick and hover * core: don't trigger onclick or hover when hide_cursor is set * misc: remove braces * core: run onclick commands asnychronously --------- Co-authored-by: Memoraike <memoraike@gmail.com>
2025-05-05 17:11:24 +02:00
CLICKABLE("shape"),
}
});
// clang-format on
}
2024-03-16 17:44:44 +03:00
//
keys = m_config.listKeysForSpecialCategory("image");
for (auto& k : keys) {
// clang-format off
result.push_back(CConfigManager::SWidgetConfig{
.type = "image",
.monitor = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("image", "monitor", k.c_str())),
.values = {
2024-03-16 17:44:44 +03:00
{"path", m_config.getSpecialConfigValue("image", "path", k.c_str())},
{"size", m_config.getSpecialConfigValue("image", "size", k.c_str())},
{"rounding", m_config.getSpecialConfigValue("image", "rounding", k.c_str())},
{"border_size", m_config.getSpecialConfigValue("image", "border_size", k.c_str())},
{"border_color", m_config.getSpecialConfigValue("image", "border_color", k.c_str())},
{"position", m_config.getSpecialConfigValue("image", "position", k.c_str())},
{"halign", m_config.getSpecialConfigValue("image", "halign", k.c_str())},
{"valign", m_config.getSpecialConfigValue("image", "valign", k.c_str())},
{"rotate", m_config.getSpecialConfigValue("image", "rotate", k.c_str())},
{"reload_time", m_config.getSpecialConfigValue("image", "reload_time", k.c_str())},
{"reload_cmd", m_config.getSpecialConfigValue("image", "reload_cmd", k.c_str())},
{"zindex", m_config.getSpecialConfigValue("image", "zindex", k.c_str())},
2024-03-16 17:44:44 +03:00
SHADOWABLE("image"),
widgets: add onclick feature (#736) * widget: add click handling and point containment methods to IWidget interface * core: add onClick method to handle mouse click events - renderer: move getOrCreateWidgetsFor method declaration to public section * core: update mouse event handling to track mouse location and button clicks * widget: add onclick command handling and point containment to CLabel - config: add onclick special config value to label * assets: add label configuration for keyboard layout switching * config: add onclick configuration for label widgets - add CLICKABLE macro for onclick configuration - replace direct onclick assignment with CLICKABLE macro * core: fix cursor shape initialization and pointer handling - ensure pointer is available before setting cursor shape - initialize cursor shape device if not already done * core: add hover handling and cursor shape updates - implement onHover method to manage widget hover states - update cursor shape based on hover status - ensure all outputs are redrawn after state changes * widgets: add hover state management and bounding box calculations - add setHover and isHovered methods to manage hover state - implement containsPoint method for hit testing - override getBoundingBox in CLabel for accurate positioning - add onHover method in CLabel to change cursor shape * core: add hover handling in pointer motion - invoke onHover method with current mouse location * widgets: add hover handling and bounding box for password input field - add getBoundingBox method to calculate the widget's bounding box - implement onHover method to update cursor shape on hover * widgets: update hover behavior for label widget - modify cursor shape setting to only apply when onclickCommand is not empty * core: optimize hover handling and rendering for lock surfaces - Improve hover state tracking for widgets - reduce unnecessary redraw calls by tracking hover changes - remove redundant renderAllOutputs() call * widgets: add onclick and hover to shape and image * core: trigger hover and onclick only for the currently focused surface * core: handle fractionalScale in onclick and hover * core: don't trigger onclick or hover when hide_cursor is set * misc: remove braces * core: run onclick commands asnychronously --------- Co-authored-by: Memoraike <memoraike@gmail.com>
2025-05-05 17:11:24 +02:00
CLICKABLE("image"),
2024-03-16 17:44:44 +03:00
}
});
// clang-format on
}
2024-02-18 23:08:03 +00:00
keys = m_config.listKeysForSpecialCategory("input-field");
for (auto& k : keys) {
// clang-format off
result.push_back(CConfigManager::SWidgetConfig{
.type = "input-field",
.monitor = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("input-field", "monitor", k.c_str())),
.values = {
2024-02-18 23:08:03 +00:00
{"size", m_config.getSpecialConfigValue("input-field", "size", k.c_str())},
{"inner_color", m_config.getSpecialConfigValue("input-field", "inner_color", k.c_str())},
{"outer_color", m_config.getSpecialConfigValue("input-field", "outer_color", k.c_str())},
{"outline_thickness", m_config.getSpecialConfigValue("input-field", "outline_thickness", k.c_str())},
{"dots_size", m_config.getSpecialConfigValue("input-field", "dots_size", k.c_str())},
{"dots_spacing", m_config.getSpecialConfigValue("input-field", "dots_spacing", k.c_str())},
2024-02-21 11:42:18 +00:00
{"dots_center", m_config.getSpecialConfigValue("input-field", "dots_center", k.c_str())},
{"dots_rounding", m_config.getSpecialConfigValue("input-field", "dots_rounding", k.c_str())},
{"dots_text_format", m_config.getSpecialConfigValue("input-field", "dots_text_format", k.c_str())},
2024-02-19 01:22:22 +00:00
{"fade_on_empty", m_config.getSpecialConfigValue("input-field", "fade_on_empty", k.c_str())},
{"fade_timeout", m_config.getSpecialConfigValue("input-field", "fade_timeout", k.c_str())},
{"font_color", m_config.getSpecialConfigValue("input-field", "font_color", k.c_str())},
{"font_family", m_config.getSpecialConfigValue("input-field", "font_family", k.c_str())},
2024-02-19 22:45:59 +00:00
{"halign", m_config.getSpecialConfigValue("input-field", "halign", k.c_str())},
{"valign", m_config.getSpecialConfigValue("input-field", "valign", k.c_str())},
{"position", m_config.getSpecialConfigValue("input-field", "position", k.c_str())},
2024-02-19 22:58:59 +00:00
{"placeholder_text", m_config.getSpecialConfigValue("input-field", "placeholder_text", k.c_str())},
2024-02-20 14:42:04 +00:00
{"hide_input", m_config.getSpecialConfigValue("input-field", "hide_input", k.c_str())},
{"hide_input_base_color", m_config.getSpecialConfigValue("input-field", "hide_input_base_color", k.c_str())},
{"rounding", m_config.getSpecialConfigValue("input-field", "rounding", k.c_str())},
{"check_color", m_config.getSpecialConfigValue("input-field", "check_color", k.c_str())},
{"fail_color", m_config.getSpecialConfigValue("input-field", "fail_color", k.c_str())},
{"fail_text", m_config.getSpecialConfigValue("input-field", "fail_text", k.c_str())},
{"check_text", m_config.getSpecialConfigValue("input-field", "check_text", k.c_str())},
{"capslock_color", m_config.getSpecialConfigValue("input-field", "capslock_color", k.c_str())},
{"numlock_color", m_config.getSpecialConfigValue("input-field", "numlock_color", k.c_str())},
{"bothlock_color", m_config.getSpecialConfigValue("input-field", "bothlock_color", k.c_str())},
{"invert_numlock", m_config.getSpecialConfigValue("input-field", "invert_numlock", k.c_str())},
{"swap_font_color", m_config.getSpecialConfigValue("input-field", "swap_font_color", k.c_str())},
{"zindex", m_config.getSpecialConfigValue("input-field", "zindex", k.c_str())},
2024-03-05 20:24:11 +00:00
SHADOWABLE("input-field"),
2024-02-18 23:08:03 +00:00
}
});
// clang-format on
}
2024-02-19 16:26:08 +00:00
keys = m_config.listKeysForSpecialCategory("label");
for (auto& k : keys) {
// clang-format off
result.push_back(CConfigManager::SWidgetConfig{
.type = "label",
.monitor = std::any_cast<Hyprlang::STRING>(m_config.getSpecialConfigValue("label", "monitor", k.c_str())),
.values = {
2024-02-19 16:26:08 +00:00
{"position", m_config.getSpecialConfigValue("label", "position", k.c_str())},
{"color", m_config.getSpecialConfigValue("label", "color", k.c_str())},
{"font_size", m_config.getSpecialConfigValue("label", "font_size", k.c_str())},
{"font_family", m_config.getSpecialConfigValue("label", "font_family", k.c_str())},
{"text", m_config.getSpecialConfigValue("label", "text", k.c_str())},
{"halign", m_config.getSpecialConfigValue("label", "halign", k.c_str())},
{"valign", m_config.getSpecialConfigValue("label", "valign", k.c_str())},
{"rotate", m_config.getSpecialConfigValue("label", "rotate", k.c_str())},
{"text_align", m_config.getSpecialConfigValue("label", "text_align", k.c_str())},
{"zindex", m_config.getSpecialConfigValue("label", "zindex", k.c_str())},
2024-03-05 20:24:11 +00:00
SHADOWABLE("label"),
widgets: add onclick feature (#736) * widget: add click handling and point containment methods to IWidget interface * core: add onClick method to handle mouse click events - renderer: move getOrCreateWidgetsFor method declaration to public section * core: update mouse event handling to track mouse location and button clicks * widget: add onclick command handling and point containment to CLabel - config: add onclick special config value to label * assets: add label configuration for keyboard layout switching * config: add onclick configuration for label widgets - add CLICKABLE macro for onclick configuration - replace direct onclick assignment with CLICKABLE macro * core: fix cursor shape initialization and pointer handling - ensure pointer is available before setting cursor shape - initialize cursor shape device if not already done * core: add hover handling and cursor shape updates - implement onHover method to manage widget hover states - update cursor shape based on hover status - ensure all outputs are redrawn after state changes * widgets: add hover state management and bounding box calculations - add setHover and isHovered methods to manage hover state - implement containsPoint method for hit testing - override getBoundingBox in CLabel for accurate positioning - add onHover method in CLabel to change cursor shape * core: add hover handling in pointer motion - invoke onHover method with current mouse location * widgets: add hover handling and bounding box for password input field - add getBoundingBox method to calculate the widget's bounding box - implement onHover method to update cursor shape on hover * widgets: update hover behavior for label widget - modify cursor shape setting to only apply when onclickCommand is not empty * core: optimize hover handling and rendering for lock surfaces - Improve hover state tracking for widgets - reduce unnecessary redraw calls by tracking hover changes - remove redundant renderAllOutputs() call * widgets: add onclick and hover to shape and image * core: trigger hover and onclick only for the currently focused surface * core: handle fractionalScale in onclick and hover * core: don't trigger onclick or hover when hide_cursor is set * misc: remove braces * core: run onclick commands asnychronously --------- Co-authored-by: Memoraike <memoraike@gmail.com>
2025-05-05 17:11:24 +02:00
CLICKABLE("label"),
2024-02-19 16:26:08 +00:00
}
});
// clang-format on
}
2024-02-18 23:08:03 +00:00
return result;
}
std::optional<std::string> CConfigManager::handleSource(const std::string& command, const std::string& rawpath) {
if (rawpath.length() < 2) {
Log::logger->log(Log::ERR, "source= path garbage");
return "source path " + rawpath + " bogus!";
}
std::unique_ptr<glob_t, void (*)(glob_t*)> glob_buf{new glob_t, [](glob_t* g) { globfree(g); }};
memset(glob_buf.get(), 0, sizeof(glob_t));
const auto CURRENTDIR = std::filesystem::path(m_configCurrentPath).parent_path().string();
if (auto r = glob(absolutePath(rawpath, CURRENTDIR).c_str(), GLOB_TILDE, nullptr, glob_buf.get()); r != 0) {
std::string err = std::format("source= globbing error: {}", r == GLOB_NOMATCH ? "found no match" : GLOB_ABORTED ? "read error" : "out of memory");
Log::logger->log(Log::ERR, "{}", err);
return err;
}
for (size_t i = 0; i < glob_buf->gl_pathc; i++) {
const auto PATH = absolutePath(glob_buf->gl_pathv[i], CURRENTDIR);
if (PATH.empty() || PATH == m_configCurrentPath) {
Log::logger->log(Log::WARN, "source= skipping invalid path");
continue;
}
if (!std::filesystem::is_regular_file(PATH)) {
if (std::filesystem::exists(PATH)) {
Log::logger->log(Log::WARN, "source= skipping non-file {}", PATH);
continue;
}
Log::logger->log(Log::ERR, "source= file doesnt exist");
return "source file " + PATH + " doesn't exist!";
}
// allow for nested config parsing
auto backupConfigPath = m_configCurrentPath;
m_configCurrentPath = PATH;
m_config.parseFile(PATH.c_str());
m_configCurrentPath = backupConfigPath;
}
return {};
}
std::optional<std::string> CConfigManager::handleBezier(const std::string& command, const std::string& args) {
const auto ARGS = CVarList(args);
std::string bezierName = ARGS[0];
if (ARGS[1] == "")
return "too few arguments";
if (ARGS[2] == "")
return "too few arguments";
if (ARGS[3] == "")
return "too few arguments";
if (ARGS[4] == "")
return "too few arguments";
float p1x, p1y, p2x, p2y;
try {
p1x = std::stof(ARGS[1]);
p1y = std::stof(ARGS[2]);
p2x = std::stof(ARGS[3]);
p2y = std::stof(ARGS[4]);
} catch (const std::exception&) {
return "invalid bezier arguments";
}
if (ARGS[5] != "")
return "too many arguments";
g_pAnimationManager->addBezierWithName(
bezierName,
Vector2D(p1x, p1y),
Vector2D(p2x, p2y)
);
return {};
}
std::optional<std::string> CConfigManager::handleAnimation(const std::string& command, const std::string& args) {
const auto ARGS = CVarList(args);
const auto ANIMNAME = ARGS[0];
if (!m_AnimationTree.nodeExists(ANIMNAME))
return "no such animation";
// This helper casts strings like "1", "true", "off", "yes"... to int.
int64_t enabledInt = configStringToInt(ARGS[1]);
// Checking that the int is 1 or 0 because the helper can return integers out of range.
if (enabledInt > 1 || enabledInt < 0)
return "invalid animation on/off state";
if (!enabledInt) {
m_AnimationTree.setConfigForNode(ANIMNAME, 0, 1, "default");
return {};
}
int64_t speed = -1;
// speed
if (isNumber(ARGS[2], true)) {
speed = std::stof(ARGS[2]);
if (speed <= 0) {
speed = 1.f;
return "invalid speed";
}
} else {
speed = 10.f;
return "invalid speed";
}
std::string bezierName = ARGS[3];
// ARGS[4] (style) currently usused by hyprlock
m_AnimationTree.setConfigForNode(ANIMNAME, enabledInt, speed, bezierName, "");
if (!g_pAnimationManager->bezierExists(bezierName)) {
const auto PANIMNODE = m_AnimationTree.getConfig(ANIMNAME);
PANIMNODE->internalBezier = "default";
return "no such bezier";
}
return {};
}