input-field: Add fade out timeout #3 (#142)

* input-field: add fade out timeout

* input-field: let dots reset themselfs

Now the dots kind of fade into the placeholder text on a failure.

* Nix/HM module: add input-field:fade_timeout option
This commit is contained in:
Maximilian Seidler 2024-03-06 22:12:49 +01:00 committed by GitHub
parent 624f497272
commit 3d6162e06e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 53 additions and 14 deletions

View file

@ -211,6 +211,12 @@ in {
default = true; 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 { placeholder_text = mkOption {
description = "The placeholder text of the input field"; description = "The placeholder text of the input field";
type = str; type = str;
@ -367,6 +373,7 @@ in {
inner_color = ${input-field.inner_color} inner_color = ${input-field.inner_color}
font_color = ${input-field.font_color} font_color = ${input-field.font_color}
fade_on_empty = ${boolToString input-field.fade_on_empty} fade_on_empty = ${boolToString input-field.fade_on_empty}
fade_timeout = ${toString input-field.fade_timeout}
placeholder_text = ${input-field.placeholder_text} placeholder_text = ${input-field.placeholder_text}
hide_input = ${boolToString input-field.hide_input} hide_input = ${boolToString input-field.hide_input}
rounding = ${toString input-field.rounding} rounding = ${toString input-field.rounding}

View file

@ -70,6 +70,7 @@ void CConfigManager::init() {
m_config.addSpecialConfigValue("input-field", "dots_spacing", Hyprlang::FLOAT{0.2}); 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_rounding", Hyprlang::INT{-1});
m_config.addSpecialConfigValue("input-field", "fade_on_empty", 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", "font_color", Hyprlang::INT{0xFF000000});
m_config.addSpecialConfigValue("input-field", "halign", Hyprlang::STRING{"center"}); m_config.addSpecialConfigValue("input-field", "halign", Hyprlang::STRING{"center"});
m_config.addSpecialConfigValue("input-field", "valign", Hyprlang::STRING{"center"}); m_config.addSpecialConfigValue("input-field", "valign", Hyprlang::STRING{"center"});
@ -156,6 +157,7 @@ std::vector<CConfigManager::SWidgetConfig> CConfigManager::getWidgetConfigs() {
{"dots_center", m_config.getSpecialConfigValue("input-field", "dots_center", k.c_str())}, {"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_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_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_color", m_config.getSpecialConfigValue("input-field", "font_color", k.c_str())},
{"halign", m_config.getSpecialConfigValue("input-field", "halign", k.c_str())}, {"halign", m_config.getSpecialConfigValue("input-field", "halign", k.c_str())},
{"valign", m_config.getSpecialConfigValue("input-field", "valign", k.c_str())}, {"valign", m_config.getSpecialConfigValue("input-field", "valign", k.c_str())},

View file

@ -13,6 +13,7 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u
dots.center = std::any_cast<Hyprlang::INT>(props.at("dots_center")); dots.center = std::any_cast<Hyprlang::INT>(props.at("dots_center"));
dots.rounding = std::any_cast<Hyprlang::INT>(props.at("dots_rounding")); dots.rounding = std::any_cast<Hyprlang::INT>(props.at("dots_rounding"));
fadeOnEmpty = std::any_cast<Hyprlang::INT>(props.at("fade_on_empty")); fadeOnEmpty = std::any_cast<Hyprlang::INT>(props.at("fade_on_empty"));
fadeTimeoutMs = std::any_cast<Hyprlang::INT>(props.at("fade_timeout"));
font = std::any_cast<Hyprlang::INT>(props.at("font_color")); font = std::any_cast<Hyprlang::INT>(props.at("font_color"));
pos = std::any_cast<Hyprlang::VEC2>(props.at("position")); pos = std::any_cast<Hyprlang::VEC2>(props.at("position"));
hiddenInputState.enabled = std::any_cast<Hyprlang::INT>(props.at("hide_input")); hiddenInputState.enabled = std::any_cast<Hyprlang::INT>(props.at("hide_input"));
@ -37,6 +38,21 @@ CPasswordInputField::CPasswordInputField(const Vector2D& viewport_, const std::u
} }
} }
static void fadeOutCallback(std::shared_ptr<CTimer> 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() { void CPasswordInputField::updateFade() {
const auto PASSLEN = g_pHyprlock->getPasswordBufferLen(); const auto PASSLEN = g_pHyprlock->getPasswordBufferLen();
@ -45,12 +61,26 @@ void CPasswordInputField::updateFade() {
return; 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)) { if (PASSLEN == 0 && fade.a != 0.0 && (!fade.animated || fade.appearing)) {
fade.a = 1.0; if (fade.allowFadeOut || fadeTimeoutMs == 0) {
fade.animated = true; fade.a = 1.0;
fade.appearing = false; fade.animated = true;
fade.start = std::chrono::system_clock::now(); fade.appearing = false;
} else if (PASSLEN > 0 && fade.a != 1.0 && (!fade.animated || !fade.appearing)) { 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.a = 0.0;
fade.animated = true; fade.animated = true;
fade.appearing = true; fade.appearing = true;
@ -79,11 +109,6 @@ void CPasswordInputField::updateDots() {
dots.lastFrame = std::chrono::system_clock::now(); 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::microseconds>(std::chrono::system_clock::now() - dots.lastFrame).count(), 0, 20000); const auto DELTA = std::clamp((int)std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now() - dots.lastFrame).count(), 0, 20000);
const float TOADD = DELTA / 1000000.0 * dots.speedPerSecond; const float TOADD = DELTA / 1000000.0 * dots.speedPerSecond;
@ -216,7 +241,7 @@ bool CPasswordInputField::draw(const SRenderData& data) {
forceReload = true; 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() { void CPasswordInputField::updateFailTex() {

View file

@ -3,6 +3,7 @@
#include "IWidget.hpp" #include "IWidget.hpp"
#include "../../helpers/Vector2D.hpp" #include "../../helpers/Vector2D.hpp"
#include "../../helpers/Color.hpp" #include "../../helpers/Color.hpp"
#include "../../core/Timer.hpp"
#include "Shadowable.hpp" #include "Shadowable.hpp"
#include <chrono> #include <chrono>
#include <vector> #include <vector>
@ -16,6 +17,7 @@ class CPasswordInputField : public IWidget {
CPasswordInputField(const Vector2D& viewport, const std::unordered_map<std::string, std::any>& props); CPasswordInputField(const Vector2D& viewport, const std::unordered_map<std::string, std::any>& props);
virtual bool draw(const SRenderData& data); virtual bool draw(const SRenderData& data);
void onFadeOutTimer();
private: private:
void updateDots(); void updateDots();
@ -45,9 +47,11 @@ class CPasswordInputField : public IWidget {
struct { struct {
std::chrono::system_clock::time_point start; std::chrono::system_clock::time_point start;
float a = 0; float a = 0;
bool appearing = true; bool appearing = true;
bool animated = false; bool animated = false;
std::shared_ptr<CTimer> fadeOutTimer = nullptr;
bool allowFadeOut = false;
} fade; } fade;
struct { struct {
@ -67,6 +71,7 @@ class CPasswordInputField : public IWidget {
} hiddenInputState; } hiddenInputState;
bool fadeOnEmpty; bool fadeOnEmpty;
uint64_t fadeTimeoutMs;
CShadowable shadow; CShadowable shadow;
}; };