core: add key repeat for backspace and make del clear the input (#277)

* core: add support for repeating backspace when held

* core: move keysym handling to a seperate function in order to reuse it for key repeat

* core: get keyboard repeat info from wayland

* core: defaults for keyboard repeat and delay
This commit is contained in:
Maximilian Seidler 2024-05-14 17:11:45 +02:00 committed by GitHub
parent 386a1e6fc2
commit 316c37746d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 84 additions and 34 deletions

View file

@ -695,7 +695,8 @@ static void handleKeyboardModifiers(void* data, wl_keyboard* wl_keyboard, uint s
} }
static void handleRepeatInfo(void* data, struct wl_keyboard* wl_keyboard, int32_t rate, int32_t delay) { static void handleRepeatInfo(void* data, struct wl_keyboard* wl_keyboard, int32_t rate, int32_t delay) {
; g_pHyprlock->m_iKeebRepeatRate = rate;
g_pHyprlock->m_iKeebRepeatDelay = delay;
} }
inline const wl_keyboard_listener keyboardListener = { inline const wl_keyboard_listener keyboardListener = {
@ -793,6 +794,35 @@ void CHyprlock::renderOutput(const std::string& stringPort) {
PMONITOR->sessionLockSurface->render(); PMONITOR->sessionLockSurface->render();
} }
void CHyprlock::startKeyRepeat(xkb_keysym_t sym) {
if (m_pKeyRepeatTimer) {
m_pKeyRepeatTimer->cancel();
m_pKeyRepeatTimer.reset();
}
if (m_iKeebRepeatDelay <= 0)
return;
m_pKeyRepeatTimer = addTimer(
std::chrono::milliseconds(m_iKeebRepeatDelay), [sym](std::shared_ptr<CTimer> self, void* data) { g_pHyprlock->repeatKey(sym); }, nullptr);
}
void CHyprlock::repeatKey(xkb_keysym_t sym) {
if (m_iKeebRepeatRate <= 0)
return;
handleKeySym(sym);
// This condition is for backspace and delete keys, but should also be ok for other keysyms since our buffer won't be empty anyways
if (bool CONTINUE = m_sPasswordState.passBuffer.length() > 0; CONTINUE)
m_pKeyRepeatTimer = addTimer(
std::chrono::milliseconds(m_iKeebRepeatRate), [sym](std::shared_ptr<CTimer> self, void* data) { g_pHyprlock->repeatKey(sym); }, nullptr);
for (auto& o : m_vOutputs) {
o->sessionLockSurface->render();
}
}
void CHyprlock::onKey(uint32_t key, bool down) { void CHyprlock::onKey(uint32_t key, bool down) {
if (m_bFadeStarted) if (m_bFadeStarted)
return; return;
@ -812,8 +842,13 @@ void CHyprlock::onKey(uint32_t key, bool down) {
if (down) if (down)
m_vPressedKeys.push_back(key); m_vPressedKeys.push_back(key);
else else {
std::erase(m_vPressedKeys, key); std::erase(m_vPressedKeys, key);
if (m_pKeyRepeatTimer) {
m_pKeyRepeatTimer->cancel();
m_pKeyRepeatTimer.reset();
}
}
if (g_pAuth->checkWaiting()) { if (g_pAuth->checkWaiting()) {
for (auto& o : m_vOutputs) { for (auto& o : m_vOutputs) {
@ -829,6 +864,18 @@ void CHyprlock::onKey(uint32_t key, bool down) {
m_bNumLock = xkb_state_mod_name_is_active(g_pHyprlock->m_pXKBState, XKB_MOD_NAME_NUM, XKB_STATE_MODS_LOCKED); m_bNumLock = xkb_state_mod_name_is_active(g_pHyprlock->m_pXKBState, XKB_MOD_NAME_NUM, XKB_STATE_MODS_LOCKED);
m_bCtrl = xkb_state_mod_name_is_active(m_pXKBState, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE); m_bCtrl = xkb_state_mod_name_is_active(m_pXKBState, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE);
handleKeySym(SYM);
if (SYM == XKB_KEY_BackSpace || SYM == XKB_KEY_Delete) // keys allowed to repeat
startKeyRepeat(SYM);
}
for (auto& o : m_vOutputs) {
o->sessionLockSurface->render();
}
}
void CHyprlock::handleKeySym(xkb_keysym_t sym) {
const auto SYM = sym;
if (SYM == XKB_KEY_Escape || (m_bCtrl && (SYM == XKB_KEY_u || SYM == XKB_KEY_BackSpace))) { if (SYM == XKB_KEY_Escape || (m_bCtrl && (SYM == XKB_KEY_u || SYM == XKB_KEY_BackSpace))) {
Debug::log(LOG, "Clearing password buffer"); Debug::log(LOG, "Clearing password buffer");
@ -844,7 +891,7 @@ void CHyprlock::onKey(uint32_t key, bool down) {
} }
g_pAuth->submitInput(m_sPasswordState.passBuffer); g_pAuth->submitInput(m_sPasswordState.passBuffer);
} else if (SYM == XKB_KEY_BackSpace) { } else if (SYM == XKB_KEY_BackSpace || SYM == XKB_KEY_Delete) {
if (m_sPasswordState.passBuffer.length() > 0) { if (m_sPasswordState.passBuffer.length() > 0) {
// handle utf-8 // handle utf-8
while ((m_sPasswordState.passBuffer.back() & 0xc0) == 0x80) while ((m_sPasswordState.passBuffer.back() & 0xc0) == 0x80)
@ -861,11 +908,6 @@ void CHyprlock::onKey(uint32_t key, bool down) {
if (len > 1) if (len > 1)
m_sPasswordState.passBuffer += std::string{buf, len - 1}; m_sPasswordState.passBuffer += std::string{buf, len - 1};
} }
}
for (auto& o : m_vOutputs) {
o->sessionLockSurface->render();
}
} }
void CHyprlock::acquireSessionLock() { void CHyprlock::acquireSessionLock() {

View file

@ -54,6 +54,9 @@ class CHyprlock {
std::string spawnSync(const std::string& cmd); std::string spawnSync(const std::string& cmd);
void onKey(uint32_t key, bool down); void onKey(uint32_t key, bool down);
void handleKeySym(xkb_keysym_t sym);
void startKeyRepeat(xkb_keysym_t sym);
void repeatKey(xkb_keysym_t sym);
void onPasswordCheckTimer(); void onPasswordCheckTimer();
void clearPasswordBuffer(); void clearPasswordBuffer();
bool passwordCheckWaiting(); bool passwordCheckWaiting();
@ -82,6 +85,9 @@ class CHyprlock {
xkb_keymap* m_pXKBKeymap = nullptr; xkb_keymap* m_pXKBKeymap = nullptr;
xkb_state* m_pXKBState = nullptr; xkb_state* m_pXKBState = nullptr;
int32_t m_iKeebRepeatRate = 25;
int32_t m_iKeebRepeatDelay = 600;
xkb_layout_index_t m_uiActiveLayout = 0; xkb_layout_index_t m_uiActiveLayout = 0;
bool m_bTerminate = false; bool m_bTerminate = false;
@ -97,6 +103,8 @@ class CHyprlock {
std::chrono::system_clock::time_point m_tFadeEnds; std::chrono::system_clock::time_point m_tFadeEnds;
Vector2D m_vLastEnterCoords = {}; Vector2D m_vLastEnterCoords = {};
std::shared_ptr<CTimer> m_pKeyRepeatTimer = nullptr;
std::vector<std::unique_ptr<COutput>> m_vOutputs; std::vector<std::unique_ptr<COutput>> m_vOutputs;
std::vector<std::shared_ptr<CTimer>> getTimers(); std::vector<std::shared_ptr<CTimer>> getTimers();