mirror of
https://github.com/hyprwm/hyprlock.git
synced 2026-05-19 19:28:08 +02:00
Merge 853235504e into 274154f92a
This commit is contained in:
commit
3d38b9d48f
4 changed files with 90 additions and 1 deletions
|
|
@ -243,6 +243,9 @@ void CConfigManager::init() {
|
|||
m_config.addConfigValue("general:text_trim", Hyprlang::INT{1});
|
||||
m_config.addConfigValue("general:hide_cursor", Hyprlang::INT{0});
|
||||
m_config.addConfigValue("general:ignore_empty_input", Hyprlang::INT{0});
|
||||
// WARNING: auto_submit_after leaks the exact password length to observers.
|
||||
// Do not enable it with a normal PAM/system password; it is intended only for PIN-like configurations.
|
||||
m_config.addConfigValue("general:auto_submit_after", 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});
|
||||
|
|
|
|||
|
|
@ -158,6 +158,8 @@ void CSessionLockSurface::render() {
|
|||
}
|
||||
|
||||
needsFrame = FEEDBACK.needsFrame || g_pAnimationManager->shouldTickForNext();
|
||||
|
||||
g_pHyprlock->onLockSurfaceRendered();
|
||||
}
|
||||
|
||||
void CSessionLockSurface::onCallback() {
|
||||
|
|
|
|||
|
|
@ -539,6 +539,8 @@ bool CHyprlock::isLockAquired() {
|
|||
}
|
||||
|
||||
void CHyprlock::clearPasswordBuffer() {
|
||||
cancelPendingAutoSubmit();
|
||||
|
||||
if (m_sPasswordState.passBuffer.empty())
|
||||
return;
|
||||
|
||||
|
|
@ -663,10 +665,13 @@ void CHyprlock::handleKeySym(xkb_keysym_t sym, bool composed) {
|
|||
if (SYM == XKB_KEY_Escape || (m_bCtrl && (SYM == XKB_KEY_u || SYM == XKB_KEY_BackSpace || SYM == XKB_KEY_a))) {
|
||||
Log::logger->log(Log::INFO, "Clearing password buffer");
|
||||
|
||||
cancelPendingAutoSubmit();
|
||||
m_sPasswordState.passBuffer = "";
|
||||
} else if (SYM == XKB_KEY_Return || SYM == XKB_KEY_KP_Enter) {
|
||||
Log::logger->log(Log::INFO, "Authenticating");
|
||||
|
||||
cancelPendingAutoSubmit();
|
||||
|
||||
static const auto IGNOREEMPTY = g_pConfigManager->getValue<Hyprlang::INT>("general:ignore_empty_input");
|
||||
|
||||
if (m_sPasswordState.passBuffer.empty() && *IGNOREEMPTY) {
|
||||
|
|
@ -676,6 +681,8 @@ void CHyprlock::handleKeySym(xkb_keysym_t sym, bool composed) {
|
|||
|
||||
g_pAuth->submitInput(m_sPasswordState.passBuffer);
|
||||
} else if (SYM == XKB_KEY_BackSpace || SYM == XKB_KEY_Delete) {
|
||||
cancelPendingAutoSubmit();
|
||||
|
||||
if (m_sPasswordState.passBuffer.length() > 0) {
|
||||
// handle utf-8
|
||||
while ((m_sPasswordState.passBuffer.back() & 0xc0) == 0x80)
|
||||
|
|
@ -691,11 +698,75 @@ void CHyprlock::handleKeySym(xkb_keysym_t sym, bool composed) {
|
|||
int len = (composed) ? xkb_compose_state_get_utf8(g_pSeatManager->m_pXKBComposeState, buf, sizeof(buf)) /* nullbyte */ + 1 :
|
||||
xkb_keysym_to_utf8(SYM, buf, sizeof(buf)) /* already includes a nullbyte */;
|
||||
|
||||
if (len > 1)
|
||||
if (len > 1) {
|
||||
m_sPasswordState.passBuffer += std::string{buf, len - 1};
|
||||
|
||||
static const auto AUTOSUBMITAFTER = g_pConfigManager->getValue<Hyprlang::INT>("general:auto_submit_after");
|
||||
if (*AUTOSUBMITAFTER > 0 && getPasswordBufferDisplayLen() == static_cast<size_t>(*AUTOSUBMITAFTER))
|
||||
enqueuePendingAutoSubmit(getPasswordBufferDisplayLen());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CHyprlock::enqueuePendingAutoSubmit(size_t expectedDisplayLen) {
|
||||
if (m_sAutoSubmitState.pending)
|
||||
return;
|
||||
|
||||
const auto READYOUTPUTS = std::ranges::count_if(m_vOutputs, [](const auto& output) { return output && output->m_sessionLockSurface && output->m_sessionLockSurface->readyForFrame; });
|
||||
|
||||
m_sAutoSubmitState.pending = true;
|
||||
m_sAutoSubmitState.expectedBufferLen = m_sPasswordState.passBuffer.length();
|
||||
m_sAutoSubmitState.expectedDisplayLen = expectedDisplayLen;
|
||||
// The first render after a new character only moves the dot animation target.
|
||||
// Wait for follow-up renders so the final dot is actually visible before auth clears the buffer.
|
||||
m_sAutoSubmitState.rendersUntilSubmit = std::max<size_t>(1, READYOUTPUTS) * 3;
|
||||
m_sAutoSubmitState.fallbackTimer = addTimer(std::chrono::milliseconds(500), [this](ASP<CTimer> self, void* data) { submitPendingAutoSubmit(); }, nullptr);
|
||||
}
|
||||
|
||||
void CHyprlock::cancelPendingAutoSubmit() {
|
||||
if (m_sAutoSubmitState.fallbackTimer) {
|
||||
m_sAutoSubmitState.fallbackTimer->cancel();
|
||||
m_sAutoSubmitState.fallbackTimer.reset();
|
||||
}
|
||||
|
||||
m_sAutoSubmitState.pending = false;
|
||||
m_sAutoSubmitState.expectedBufferLen = 0;
|
||||
m_sAutoSubmitState.expectedDisplayLen = 0;
|
||||
m_sAutoSubmitState.rendersUntilSubmit = 0;
|
||||
}
|
||||
|
||||
void CHyprlock::submitPendingAutoSubmit() {
|
||||
if (!m_sAutoSubmitState.pending)
|
||||
return;
|
||||
|
||||
const auto EXPECTEDBUFFERLEN = m_sAutoSubmitState.expectedBufferLen;
|
||||
const auto EXPECTEDDISPLAYLEN = m_sAutoSubmitState.expectedDisplayLen;
|
||||
|
||||
cancelPendingAutoSubmit();
|
||||
|
||||
if (m_sPasswordState.passBuffer.length() != EXPECTEDBUFFERLEN || getPasswordBufferDisplayLen() != EXPECTEDDISPLAYLEN)
|
||||
return;
|
||||
|
||||
Log::logger->log(Log::INFO, "Auto-submitting password");
|
||||
g_pAuth->submitInput(m_sPasswordState.passBuffer);
|
||||
}
|
||||
|
||||
void CHyprlock::onLockSurfaceRendered() {
|
||||
if (!m_sAutoSubmitState.pending)
|
||||
return;
|
||||
|
||||
if (m_sPasswordState.passBuffer.length() != m_sAutoSubmitState.expectedBufferLen || getPasswordBufferDisplayLen() != m_sAutoSubmitState.expectedDisplayLen) {
|
||||
cancelPendingAutoSubmit();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_sAutoSubmitState.rendersUntilSubmit > 0)
|
||||
--m_sAutoSubmitState.rendersUntilSubmit;
|
||||
|
||||
if (m_sAutoSubmitState.rendersUntilSubmit == 0)
|
||||
submitPendingAutoSubmit();
|
||||
}
|
||||
|
||||
void CHyprlock::onClick(uint32_t button, bool down, const Vector2D& pos) {
|
||||
if (!down)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ class CHyprlock {
|
|||
void handleKeySym(xkb_keysym_t sym, bool compose);
|
||||
void onPasswordCheckTimer();
|
||||
void clearPasswordBuffer();
|
||||
void onLockSurfaceRendered();
|
||||
bool passwordCheckWaiting();
|
||||
std::optional<std::string> passwordLastFailReason();
|
||||
|
||||
|
|
@ -124,6 +125,10 @@ class CHyprlock {
|
|||
bool m_fadeOutOrTerminate = false;
|
||||
bool m_bTerminate = false;
|
||||
|
||||
void enqueuePendingAutoSubmit(size_t expectedDisplayLen);
|
||||
void cancelPendingAutoSubmit();
|
||||
void submitPendingAutoSubmit();
|
||||
|
||||
struct {
|
||||
wl_display* display = nullptr;
|
||||
SP<CCWlRegistry> registry = nullptr;
|
||||
|
|
@ -146,6 +151,14 @@ class CHyprlock {
|
|||
bool displayFailText = false;
|
||||
} m_sPasswordState;
|
||||
|
||||
struct {
|
||||
ASP<CTimer> fallbackTimer = nullptr;
|
||||
size_t expectedBufferLen = 0;
|
||||
size_t expectedDisplayLen = 0;
|
||||
size_t rendersUntilSubmit = 0;
|
||||
bool pending = false;
|
||||
} m_sAutoSubmitState;
|
||||
|
||||
struct {
|
||||
std::mutex timersMutex;
|
||||
std::mutex eventRequestMutex;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue