diff --git a/nix/hm-module.nix b/nix/hm-module.nix index 80dbae1..db93572 100644 --- a/nix/hm-module.nix +++ b/nix/hm-module.nix @@ -211,6 +211,12 @@ in { default = true; }; + fade_timeout = mkOption { + description = "Milliseconds before the input field should be faded (0 to fade immediately)"; + type = int; + default = 1000; + }; + placeholder_text = mkOption { description = "The placeholder text of the input field"; type = str; @@ -367,6 +373,7 @@ in { inner_color = ${input-field.inner_color} font_color = ${input-field.font_color} fade_on_empty = ${boolToString input-field.fade_on_empty} + fade_timeout = ${toString input-field.fade_timeout} placeholder_text = ${input-field.placeholder_text} hide_input = ${boolToString input-field.hide_input} rounding = ${toString input-field.rounding} diff --git a/src/config/ConfigManager.cpp b/src/config/ConfigManager.cpp index 97db9ea..97e8dba 100644 --- a/src/config/ConfigManager.cpp +++ b/src/config/ConfigManager.cpp @@ -70,6 +70,7 @@ void CConfigManager::init() { 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", "fade_on_empty", Hyprlang::INT{1}); + m_config.addSpecialConfigValue("input-field", "fade_timeout", Hyprlang::INT{1000}); m_config.addSpecialConfigValue("input-field", "font_color", Hyprlang::INT{0xFF000000}); m_config.addSpecialConfigValue("input-field", "halign", Hyprlang::STRING{"center"}); m_config.addSpecialConfigValue("input-field", "valign", Hyprlang::STRING{"center"}); @@ -156,6 +157,7 @@ std::vector CConfigManager::getWidgetConfigs() { {"dots_center", m_config.getSpecialConfigValue("input-field", "dots_center", k.c_str())}, {"dots_rounding", m_config.getSpecialConfigValue("input-field", "dots_rounding", k.c_str())}, {"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())}, {"halign", m_config.getSpecialConfigValue("input-field", "halign", k.c_str())}, {"valign", m_config.getSpecialConfigValue("input-field", "valign", k.c_str())}, diff --git a/src/renderer/widgets/PasswordInputField.cpp b/src/renderer/widgets/PasswordInputField.cpp index fd09a7e..48a9bde 100644 --- a/src/renderer/widgets/PasswordInputField.cpp +++ b/src/renderer/widgets/PasswordInputField.cpp @@ -13,6 +13,7 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u dots.center = std::any_cast(props.at("dots_center")); dots.rounding = std::any_cast(props.at("dots_rounding")); fadeOnEmpty = std::any_cast(props.at("fade_on_empty")); + fadeTimeoutMs = std::any_cast(props.at("fade_timeout")); font = std::any_cast(props.at("font_color")); pos = std::any_cast(props.at("position")); hiddenInputState.enabled = std::any_cast(props.at("hide_input")); @@ -37,6 +38,21 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u } } +static void fadeOutCallback(std::shared_ptr self, void* data) { + CPasswordInputField* p = (CPasswordInputField*)data; + + p->onFadeOutTimer(); + + for (auto& o : g_pHyprlock->m_vOutputs) { + o->sessionLockSurface->render(); + } +} + +void CPasswordInputField::onFadeOutTimer() { + fade.allowFadeOut = true; + fade.fadeOutTimer.reset(); +} + void CPasswordInputField::updateFade() { const auto PASSLEN = g_pHyprlock->getPasswordBufferLen(); @@ -45,12 +61,26 @@ void CPasswordInputField::updateFade() { return; } + if (PASSLEN > 0 && fade.allowFadeOut) + fade.allowFadeOut = false; + + if (PASSLEN > 0 && fade.fadeOutTimer.get()) { + fade.fadeOutTimer->cancel(); + fade.fadeOutTimer.reset(); + } + if (PASSLEN == 0 && fade.a != 0.0 && (!fade.animated || fade.appearing)) { - fade.a = 1.0; - fade.animated = true; - fade.appearing = false; - fade.start = std::chrono::system_clock::now(); - } else if (PASSLEN > 0 && fade.a != 1.0 && (!fade.animated || !fade.appearing)) { + if (fade.allowFadeOut || fadeTimeoutMs == 0) { + fade.a = 1.0; + fade.animated = true; + fade.appearing = false; + fade.start = std::chrono::system_clock::now(); + fade.allowFadeOut = false; + } else if (!fade.fadeOutTimer.get()) + fade.fadeOutTimer = g_pHyprlock->addTimer(std::chrono::milliseconds(fadeTimeoutMs), fadeOutCallback, this); + } + + if (PASSLEN > 0 && fade.a != 1.0 && (!fade.animated || !fade.appearing)) { fade.a = 0.0; fade.animated = true; fade.appearing = true; @@ -79,11 +109,6 @@ void CPasswordInputField::updateDots() { dots.lastFrame = std::chrono::system_clock::now(); } - if (PASSLEN == 0 && !placeholder.failID.empty()) { - dots.currentAmount = PASSLEN; - return; - } - const auto DELTA = std::clamp((int)std::chrono::duration_cast(std::chrono::system_clock::now() - dots.lastFrame).count(), 0, 20000); const float TOADD = DELTA / 1000000.0 * dots.speedPerSecond; @@ -216,7 +241,7 @@ bool CPasswordInputField::draw(const SRenderData& data) { forceReload = true; } - return dots.currentAmount != PASSLEN || data.opacity < 1.0 || forceReload; + return dots.currentAmount != PASSLEN || fade.animated || data.opacity < 1.0 || forceReload; } void CPasswordInputField::updateFailTex() { diff --git a/src/renderer/widgets/PasswordInputField.hpp b/src/renderer/widgets/PasswordInputField.hpp index 433e114..f81ed63 100644 --- a/src/renderer/widgets/PasswordInputField.hpp +++ b/src/renderer/widgets/PasswordInputField.hpp @@ -3,6 +3,7 @@ #include "IWidget.hpp" #include "../../helpers/Vector2D.hpp" #include "../../helpers/Color.hpp" +#include "../../core/Timer.hpp" #include "Shadowable.hpp" #include #include @@ -16,6 +17,7 @@ class CPasswordInputField : public IWidget { CPasswordInputField(const Vector2D& viewport, const std::unordered_map& props); virtual bool draw(const SRenderData& data); + void onFadeOutTimer(); private: void updateDots(); @@ -45,9 +47,11 @@ class CPasswordInputField : public IWidget { struct { std::chrono::system_clock::time_point start; - float a = 0; - bool appearing = true; - bool animated = false; + float a = 0; + bool appearing = true; + bool animated = false; + std::shared_ptr fadeOutTimer = nullptr; + bool allowFadeOut = false; } fade; struct { @@ -67,6 +71,7 @@ class CPasswordInputField : public IWidget { } hiddenInputState; bool fadeOnEmpty; + uint64_t fadeTimeoutMs; CShadowable shadow; };