summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/client/qwaylandinputdevice.cpp127
-rw-r--r--src/client/qwaylandinputdevice_p.h26
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard.cpp40
-rw-r--r--src/compositor/compositor_api/qwaylandkeyboard_p.h2
4 files changed, 100 insertions, 95 deletions
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 572ce1e50..166be1934 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -77,7 +77,20 @@ namespace QtWaylandClient {
QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
: mParent(p)
{
- connect(&mRepeatTimer, SIGNAL(timeout()), this, SLOT(repeatKey()));
+ mRepeatTimer.callOnTimeout([&]() {
+ if (!focusWindow()) {
+ // We destroyed the keyboard focus surface, but the server didn't get the message yet...
+ // or the server didn't send an enter event first.
+ return;
+ }
+ mRepeatTimer.setInterval(mRepeatRate);
+ handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, mRepeatKey.modifiers,
+ mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
+ mRepeatKey.text, true);
+ handleKey(mRepeatKey.time, QEvent::KeyPress, mRepeatKey.key, mRepeatKey.modifiers,
+ mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
+ mRepeatKey.text, true);
+ });
}
#if QT_CONFIG(xkbcommon)
@@ -728,8 +741,10 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in
void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd, uint32_t size)
{
+ mKeymapFormat = format;
#if QT_CONFIG(xkbcommon)
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
+ qCWarning(lcQpaWayland) << "unknown keymap format:" << format;
close(fd);
return;
}
@@ -751,7 +766,6 @@ void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd,
else
mXkbState.reset(nullptr);
#else
- Q_UNUSED(format);
Q_UNUSED(fd);
Q_UNUSED(size);
#endif
@@ -798,29 +812,34 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf
handleFocusLost();
}
-void QWaylandInputDevice::Keyboard::sendKey(QWindow *tlw, ulong timestamp, QEvent::Type type, int key,
- Qt::KeyboardModifiers modifiers, quint32 nativeScanCode,
- quint32 nativeVirtualKey, quint32 nativeModifiers,
- const QString& text, bool autorep, ushort count)
+void QWaylandInputDevice::Keyboard::handleKey(ulong timestamp, QEvent::Type type, int key,
+ Qt::KeyboardModifiers modifiers, quint32 nativeScanCode,
+ quint32 nativeVirtualKey, quint32 nativeModifiers,
+ const QString &text, bool autorepeat, ushort count)
{
QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
bool filtered = false;
if (inputContext && !mParent->mQDisplay->usingInputContextFromCompositor()) {
QKeyEvent event(type, key, modifiers, nativeScanCode, nativeVirtualKey,
- nativeModifiers, text, autorep, count);
+ nativeModifiers, text, autorepeat, count);
event.setTimestamp(timestamp);
filtered = inputContext->filterEvent(&event);
}
if (!filtered) {
- QWindowSystemInterface::handleExtendedKeyEvent(tlw, timestamp, type, key, modifiers,
- nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
+ QWindowSystemInterface::handleExtendedKeyEvent(focusWindow()->window(), timestamp, type, key, modifiers,
+ nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorepeat, count);
}
}
void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
{
+ if (mKeymapFormat != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 && mKeymapFormat != WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) {
+ qCWarning(lcQpaWayland) << Q_FUNC_INFO << "unknown keymap format:" << mKeymapFormat;
+ return;
+ }
+
auto *window = focusWindow();
if (!window) {
// We destroyed the keyboard focus surface, but the server didn't get the message yet...
@@ -828,76 +847,53 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
return;
}
- uint32_t code = key + 8;
- bool isDown = state != WL_KEYBOARD_KEY_STATE_RELEASED;
- QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease;
- QString text;
- int qtkey = key + 8; // qt-compositor substracts 8 for some reason
mParent->mSerial = serial;
+ const bool isDown = state != WL_KEYBOARD_KEY_STATE_RELEASED;
if (isDown)
mParent->mQDisplay->setLastInputDevice(mParent, serial, window);
+ if (mKeymapFormat == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
#if QT_CONFIG(xkbcommon)
- if ((!mXkbKeymap || !mXkbState) && !createDefaultKeymap())
- return;
-
- xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState.get(), code);
-
- Qt::KeyboardModifiers modifiers = mParent->modifiers();
+ if ((!mXkbKeymap || !mXkbState) && !createDefaultKeymap())
+ return;
- std::tie(qtkey, text) = QWaylandXkb::keysymToQtKey(sym, modifiers);
+ auto code = key + 8; // map to wl_keyboard::keymap_format::keymap_format_xkb_v1
- sendKey(window->window(), time, type, qtkey, modifiers, code, sym, mNativeModifiers, text);
-#else
- // Generic fallback for single hard keys: Assume 'key' is a Qt key code.
- sendKey(window->window(), time, type, qtkey, Qt::NoModifier, code, 0, 0);
-#endif
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState.get(), code);
- if (state == WL_KEYBOARD_KEY_STATE_PRESSED
-#if QT_CONFIG(xkbcommon)
- && xkb_keymap_key_repeats(mXkbKeymap.get(), code)
-#endif
- ) {
- mRepeatKey = qtkey;
- mRepeatCode = code;
- mRepeatTime = time;
- mRepeatText = text;
-#if QT_CONFIG(xkbcommon)
- mRepeatSym = sym;
-#endif
- mRepeatTimer.setInterval(mRepeatDelay);
- mRepeatTimer.start();
- } else if (mRepeatCode == code) {
- mRepeatTimer.stop();
- }
-}
+ Qt::KeyboardModifiers modifiers = mParent->modifiers();
-void QWaylandInputDevice::Keyboard::repeatKey()
-{
- auto *window = focusWindow();
- if (!window) {
- // We destroyed the keyboard focus surface, but the server didn't get the message yet...
- // or the server didn't send an enter event first.
- return;
- }
+ int qtkey = 0;
+ QString text;
+ std::tie(qtkey, text) = QWaylandXkb::keysymToQtKey(sym, modifiers);
- mRepeatTimer.setInterval(mRepeatRate);
- sendKey(window->window(), mRepeatTime, QEvent::KeyRelease, mRepeatKey, modifiers(), mRepeatCode,
-#if QT_CONFIG(xkbcommon)
- mRepeatSym, mNativeModifiers,
-#else
- 0, 0,
-#endif
- mRepeatText, true);
+ QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease;
+ handleKey(time, type, qtkey, modifiers, code, sym, mNativeModifiers, text);
- sendKey(window->window(), mRepeatTime, QEvent::KeyPress, mRepeatKey, modifiers(), mRepeatCode,
-#if QT_CONFIG(xkbcommon)
- mRepeatSym, mNativeModifiers,
+ if (state == WL_KEYBOARD_KEY_STATE_PRESSED && xkb_keymap_key_repeats(mXkbKeymap.get(), code)) {
+ mRepeatKey.key = qtkey;
+ mRepeatKey.code = code;
+ mRepeatKey.time = time;
+ mRepeatKey.text = text;
+ mRepeatKey.modifiers = modifiers;
+ mRepeatKey.nativeModifiers = mNativeModifiers;
+ mRepeatKey.nativeVirtualKey = sym;
+ mRepeatTimer.setInterval(mRepeatDelay);
+ mRepeatTimer.start();
+ } else if (mRepeatKey.code == code) {
+ mRepeatTimer.stop();
+ }
#else
- 0, 0,
+ Q_UNUSED(time);
+ Q_UNUSED(key);
+ qCWarning(lcQpaWayland, "xkbcommon not available on this build, not performing key mapping");
+ return;
#endif
- mRepeatText, true);
+ } else if (mKeymapFormat == WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) {
+ // raw scan code
+ return;
+ }
}
void QWaylandInputDevice::Keyboard::handleFocusDestroyed()
@@ -935,7 +931,6 @@ void QWaylandInputDevice::Keyboard::keyboard_modifiers(uint32_t serial,
0, 0, group);
mNativeModifiers = mods_depressed | mods_latched | mods_locked;
#else
- Q_UNUSED(serial);
Q_UNUSED(mods_depressed);
Q_UNUSED(mods_latched);
Q_UNUSED(mods_locked);
diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h
index 98e60286e..2dc3ddc27 100644
--- a/src/client/qwaylandinputdevice_p.h
+++ b/src/client/qwaylandinputdevice_p.h
@@ -211,18 +211,25 @@ public:
uint32_t mNativeModifiers = 0;
- int mRepeatKey;
- uint32_t mRepeatCode;
- uint32_t mRepeatTime;
+ struct repeatKey {
+ int key;
+ uint32_t code;
+ uint32_t time;
+ QString text;
+ Qt::KeyboardModifiers modifiers;
+ uint32_t nativeVirtualKey;
+ uint32_t nativeModifiers;
+ } mRepeatKey;
+
+ QTimer mRepeatTimer;
int mRepeatRate = 25;
int mRepeatDelay = 400;
- QString mRepeatText;
- QTimer mRepeatTimer;
+
+ uint32_t mKeymapFormat = WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1;
Qt::KeyboardModifiers modifiers() const;
private slots:
- void repeatKey();
void handleFocusDestroyed();
void handleFocusLost();
@@ -230,12 +237,11 @@ private:
#if QT_CONFIG(xkbcommon)
bool createDefaultKeymap();
#endif
- void sendKey(QWindow *tlw, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
- quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
- const QString& text = QString(), bool autorep = false, ushort count = 1);
+ void handleKey(ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
+ quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
+ const QString &text, bool autorepeat = false, ushort count = 1);
#if QT_CONFIG(xkbcommon)
- xkb_keysym_t mRepeatSym = XKB_KEY_NoSymbol;
QXkbCommon::ScopedXKBKeymap mXkbKeymap;
QXkbCommon::ScopedXKBState mXkbState;
#endif
diff --git a/src/compositor/compositor_api/qwaylandkeyboard.cpp b/src/compositor/compositor_api/qwaylandkeyboard.cpp
index e84eed64a..f66fe3263 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard.cpp
+++ b/src/compositor/compositor_api/qwaylandkeyboard.cpp
@@ -143,7 +143,7 @@ void QWaylandKeyboardPrivate::keyboard_bind_resource(wl_keyboard::Resource *reso
#endif
{
int null_fd = open("/dev/null", O_RDONLY);
- send_keymap(resource->handle, 0 /* WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP */,
+ send_keymap(resource->handle, WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP,
null_fd, 0);
close(null_fd);
}
@@ -163,11 +163,8 @@ void QWaylandKeyboardPrivate::keyboard_release(wl_keyboard::Resource *resource)
void QWaylandKeyboardPrivate::keyEvent(uint code, uint32_t state)
{
-#if QT_CONFIG(xkbcommon)
- uint key = toWaylandXkbV1Key(code);
-#else
- uint key = code;
-#endif
+ uint key = toWaylandKey(code);
+
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
keys << key;
} else {
@@ -179,11 +176,7 @@ void QWaylandKeyboardPrivate::sendKeyEvent(uint code, uint32_t state)
{
uint32_t time = compositor()->currentTimeMsecs();
uint32_t serial = compositor()->nextSerial();
-#if QT_CONFIG(xkbcommon)
- uint key = toWaylandXkbV1Key(code);
-#else
- uint key = code;
-#endif
+ uint key = toWaylandKey(code);
if (focusResource)
send_key(focusResource->handle, serial, time, key, state);
}
@@ -284,6 +277,24 @@ void QWaylandKeyboardPrivate::maybeUpdateKeymap()
#endif
}
+uint QWaylandKeyboardPrivate::toWaylandKey(const uint nativeScanCode)
+{
+#if QT_CONFIG(xkbcommon)
+ // In all current XKB keymaps there's a constant offset of 8 (for historical
+ // reasons) from hardware/evdev scancodes to XKB keycodes. On X11, we pass
+ // XKB keycodes (as sent by X server) via QKeyEvent::nativeScanCode. eglfs+evdev
+ // adds 8 for consistency, see qtbase/05c07c7636012ebb4131ca099ca4ea093af76410.
+ // eglfs+libinput also adds 8, for the same reason. Wayland protocol uses
+ // hardware/evdev scancodes, thus we need to minus 8 before sending the event
+ // out.
+ const uint offset = 8;
+ Q_ASSERT(nativeScanCode >= offset);
+ return nativeScanCode - offset;
+#else
+ return nativeScanCode;
+#endif
+}
+
#if QT_CONFIG(xkbcommon)
static int createAnonymousFile(size_t size)
{
@@ -348,13 +359,6 @@ void QWaylandKeyboardPrivate::createXKBState(xkb_keymap *keymap)
qWarning("Failed to create XKB state");
}
-uint QWaylandKeyboardPrivate::toWaylandXkbV1Key(const uint nativeScanCode)
-{
- const uint offset = 8;
- Q_ASSERT(nativeScanCode >= offset);
- return nativeScanCode - offset;
-}
-
void QWaylandKeyboardPrivate::createXKBKeymap()
{
if (!xkbContext())
diff --git a/src/compositor/compositor_api/qwaylandkeyboard_p.h b/src/compositor/compositor_api/qwaylandkeyboard_p.h
index c4d29c2d6..fb3f5fe34 100644
--- a/src/compositor/compositor_api/qwaylandkeyboard_p.h
+++ b/src/compositor/compositor_api/qwaylandkeyboard_p.h
@@ -115,7 +115,7 @@ private:
void createXKBKeymap();
void createXKBState(xkb_keymap *keymap);
#endif
- static uint toWaylandXkbV1Key(const uint nativeScanCode);
+ static uint toWaylandKey(const uint nativeScanCode);
void sendRepeatInfo();