summaryrefslogtreecommitdiffstats
path: root/src/client/qwaylandinputdevice.cpp
diff options
context:
space:
mode:
authorGatis Paeglis <gatis.paeglis@qt.io>2019-01-16 14:42:50 +0100
committerGatis Paeglis <gatis.paeglis@qt.io>2019-04-17 06:28:58 +0000
commit35880c7e1021a379e3cdd4005edd53472b63856c (patch)
tree884a9f8839c712c1be44a080cf3844267bf5176b /src/client/qwaylandinputdevice.cpp
parent458bc86f82f8fa6cfd659950549d1d2b36e5e40d (diff)
rework key handling
- Document the magical 8 keycode offset in QKeyEvent::nativeScanCode() - Check if we are working with the expected keymap format. - Rename sendKey() to handleKey() as that is typical naming convention for events that are passed to QWindowSystemInterface. - WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP is in the bundled xml so use it in send_keymap() - Rename toWaylandXkbV1Key() to toWaylandKey() as previous name was incorrect. - Remove "Generic fallback" in keyboard_key() as it was non-functional, you can't expect any useful output when mapping scan code directly to Qt::Key. It was not working in 5.9 (did not check beyond that) and no one has complained. It is safe to assume that the fallback code path is dead and can be dropped. To use HW keyboard with wayland, you need to build with libxkbcommon. We require this on XCB since Qt 5.1.0, so it is not an unreasonable requirement for Wayland. - Cleanup auto-repeat key handling. - Cleanup "#if QT_CONFIG(xkbcommon)" checks. Change-Id: Ie9fcc628621487fb58bc55dd595bf0d51eedfc92 Reviewed-by: Johan Helsing <johan.helsing@qt.io>
Diffstat (limited to 'src/client/qwaylandinputdevice.cpp')
-rw-r--r--src/client/qwaylandinputdevice.cpp127
1 files changed, 61 insertions, 66 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);