From f065979b3fc894fd2f252a2dd4e7f6bc28fb27a9 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 26 Jan 2026 18:28:02 +0100 Subject: [PATCH] Fix: detect key repeat in libei input For libei, there's no indication that a key is repeated. However, sending repeated key down events (DKDN instead of DKRP for the synergy protocol) can be confusing to clients, which then causes issues like in #7971. Detect repeated key down events in EiScreen server and send them to the client with the repeat flag set, so in e.g. synergy that causes the DKRP messages, to be less confusing. For me this fixes an issue where the synergy client is creating a USB device, which requires repeated events to be entirely dropped since the host OS where the USB device is connected will do its own repeat when a key is held down. --- src/lib/platform/EiScreen.cpp | 12 ++++++++++-- src/lib/platform/EiScreen.h | 2 ++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/lib/platform/EiScreen.cpp b/src/lib/platform/EiScreen.cpp index ce42a2f5e..57b3e1ece 100644 --- a/src/lib/platform/EiScreen.cpp +++ b/src/lib/platform/EiScreen.cpp @@ -621,18 +621,26 @@ void EiScreen::onKeyEvent(ei_event *event) bool pressed = ei_event_keyboard_get_key_is_press(event); KeyID keyid = m_keyState->mapKeyFromKeyval(keyval); auto keybutton = static_cast(keyval); + bool repeat; m_keyState->updateXkbState(keyval, pressed); KeyModifierMask mask = m_keyState->pollActiveModifiers(); - LOG_DEBUG1("event: key %s keycode=%d keyid=%d mask=0x%x", pressed ? "press" : "release", keycode, keyid, mask); + repeat = pressed && m_lastPressed == keyid && keyid != kKeyNone; + + m_lastPressed = pressed ? keyid : kKeyNone; + + LOG_DEBUG1( + "event: key %s%s keycode=%d keyid=%d mask=0x%x", pressed ? "press" : "release", repeat ? " (repeat)" : "", + keycode, keyid, mask + ); if (m_isPrimary && onHotkey(keyid, pressed, mask)) { return; } if (keyid != kKeyNone) { - m_keyState->sendKeyEvent(getEventTarget(), pressed, false, keyid, mask, 1, keybutton); + m_keyState->sendKeyEvent(getEventTarget(), pressed, repeat, keyid, mask, 1, keybutton); } } diff --git a/src/lib/platform/EiScreen.h b/src/lib/platform/EiScreen.h index e75108db0..3d84aff32 100644 --- a/src/lib/platform/EiScreen.h +++ b/src/lib/platform/EiScreen.h @@ -122,6 +122,8 @@ private: // keyboard stuff EiKeyState *m_keyState = nullptr; + KeyID m_lastPressed = kKeyNone; + // clipboard stuff WlClipboardCollection *m_clipboard = nullptr;