Fake input: check the bound protocol version

Qt binds the lower of the asked and advertised versions; sending
keyboard_keysym (v6) or destroy (v5) to an older KWin makes libwayland
abort. Those requests are skipped there, with a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 10:13:49 +02:00
co-authored by Claude Opus 5.5
parent 5f7873995b
commit 9f3940514b
2 changed files with 30 additions and 6 deletions
+24 -6
View File
@@ -1,9 +1,13 @@
#include "KWinFakeInput.h" #include "KWinFakeInput.h"
#include <QtLogging>
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
namespace { namespace {
constexpr uint32_t KeysymVersion = 6; // keyboard_keysym; keyboard_key is 4
constexpr uint32_t DestroyVersion = 5;
constexpr uint32_t Released = 0; constexpr uint32_t Released = 0;
constexpr uint32_t Pressed = 1; constexpr uint32_t Pressed = 1;
@@ -22,24 +26,38 @@ constexpr ModifierKey ModifierKeys[] = {
} // namespace } // namespace
KWinFakeInput::KWinFakeInput() KWinFakeInput::KWinFakeInput()
: QWaylandClientExtensionTemplate(6) // 6: keyboard_keysym : QWaylandClientExtensionTemplate(KeysymVersion)
{ {
connect(this, &QWaylandClientExtension::activeChanged, this, [this] { connect(this, &QWaylandClientExtension::activeChanged, this, [this] {
if (isActive()) if (!isActive())
authenticate(QStringLiteral("sloposk"), QStringLiteral("On-screen keyboard: type into any window")); return;
if (!canSendKeysyms())
qWarning("KWin's fake input is too old (version %u, need %u): typing outside text fields is off",
boundVersion(), KeysymVersion);
authenticate(QStringLiteral("sloposk"), QStringLiteral("On-screen keyboard: type into any window"));
}); });
initialize(); initialize();
} }
KWinFakeInput::~KWinFakeInput() KWinFakeInput::~KWinFakeInput()
{ {
if (isActive()) if (isActive() && boundVersion() >= DestroyVersion)
destroy(); destroy();
} }
uint32_t KWinFakeInput::boundVersion() const
{
return QtWayland::org_kde_kwin_fake_input::version(); // the proxy's, not the one asked for
}
bool KWinFakeInput::canSendKeysyms() const
{
return isActive() && boundVersion() >= KeysymVersion;
}
void KWinFakeInput::sendKeysym(quint32 keysym, Qt::KeyboardModifiers modifiers) void KWinFakeInput::sendKeysym(quint32 keysym, Qt::KeyboardModifiers modifiers)
{ {
if (!isActive()) if (!canSendKeysyms())
return; return;
for (const ModifierKey &key : ModifierKeys) { for (const ModifierKey &key : ModifierKeys) {
if (modifiers & key.flag) if (modifiers & key.flag)
@@ -55,7 +73,7 @@ void KWinFakeInput::sendKeysym(quint32 keysym, Qt::KeyboardModifiers modifiers)
void KWinFakeInput::setKeyPressed(quint32 keysym, bool pressed) void KWinFakeInput::setKeyPressed(quint32 keysym, bool pressed)
{ {
if (isActive()) if (canSendKeysyms())
keyboard_keysym(keysym, pressed ? Pressed : Released); keyboard_keysym(keysym, pressed ? Pressed : Released);
} }
+6
View File
@@ -24,4 +24,10 @@ public:
void setKeyPressed(quint32 keysym, bool pressed); void setKeyPressed(quint32 keysym, bool pressed);
// Types each character as its keysym. // Types each character as its keysym.
void typeText(const QString &text); void typeText(const QString &text);
private:
// The version KWin bound, which may be older than the one asked for:
// sending a request it lacks makes libwayland abort.
uint32_t boundVersion() const;
bool canSendKeysyms() const;
}; };