diff options
author | Giulio Camuffo <giuliocamuffo@gmail.com> | 2013-08-13 11:25:46 +0200 |
---|---|---|
committer | Andy Nichols <andy.nichols@digia.com> | 2013-08-22 11:44:56 +0200 |
commit | 536420a28952b0f58bdb539595e8a4c00a8dbddf (patch) | |
tree | 20d5ee8db5ee7aa45fac948ec29a249a6cb5cbcc /src/plugins/platforms | |
parent | 7ff722f3c9d29ef501a9cb47bebe6c7e8d3c5a88 (diff) |
Fix key handling.
Use the keymap sent by the compositor and improve the way the text
and the Qt::Key of the keysym is calculated, making the keypad work.
Change-Id: Icc4667dab0649ce47792c512fbcaa0193e2ffd45
Reviewed-by: Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
Reviewed-by: Jan Arne Petersen <jan.petersen@kdab.com>
Reviewed-by: Andy Nichols <andy.nichols@digia.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp | 84 |
1 files changed, 64 insertions, 20 deletions
diff --git a/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp index bdf5a055d..aab939f6d 100644 --- a/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp +++ b/src/plugins/platforms/wayland_common/qwaylandinputdevice.cpp @@ -55,6 +55,7 @@ #include <unistd.h> #include <fcntl.h> +#include <sys/mman.h> #include <wayland-cursor.h> @@ -94,7 +95,7 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, uint32_t id) names.variant = strdup(""); names.options = strdup(""); - xkb_context *mXkbContext = xkb_context_new(xkb_context_flags(0)); + mXkbContext = xkb_context_new(xkb_context_flags(0)); if (mXkbContext) { mXkbMap = xkb_map_new_from_names(mXkbContext, &names, xkb_map_compile_flags(0)); if (mXkbMap) { @@ -423,30 +424,73 @@ static const uint32_t KeyTbl[] = { 0, 0 }; -static uint32_t translateKey(uint32_t sym, char *string, size_t size) +static int keysymToQtKey(xkb_keysym_t key) { - Q_UNUSED(size); - string[0] = '\0'; + int code = 0; + int i = 0; + while (KeyTbl[i]) { + if (key == KeyTbl[i]) { + code = (int)KeyTbl[i+1]; + break; + } + i += 2; + } - if (sym >= XK_F1 && sym <= XK_F35) - return Qt::Key_F1 + (int(sym) - XK_F1); + return code; +} - for (int i = 0; KeyTbl[i]; i += 2) - if (sym == KeyTbl[i]) - return KeyTbl[i + 1]; +static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text) +{ + int code = 0; + + if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) { + code = Qt::Key_F1 + (int(keysym) - XKB_KEY_F1); + } else if (keysym >= XKB_KEY_KP_Space && keysym <= XKB_KEY_KP_9) { + if (keysym >= XKB_KEY_KP_0) { + // numeric keypad keys + code = Qt::Key_0 + ((int)keysym - XKB_KEY_KP_0); + } else { + code = keysymToQtKey(keysym); + } + modifiers |= Qt::KeypadModifier; + } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f + && text.unicode()->unicode() != 0x7f + && !(keysym >= XKB_KEY_dead_grave && keysym <= XKB_KEY_dead_currency)) { + code = text.unicode()->toUpper().unicode(); + } else { + // any other keys + code = keysymToQtKey(keysym); + } - string[0] = sym; - string[1] = '\0'; - return toupper(sym); + return code; } #endif // QT_NO_WAYLAND_XKB void QWaylandInputDevice::keyboard_keymap(uint32_t format, int32_t fd, uint32_t size) { +#ifndef QT_NO_WAYLAND_XKB + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + close(fd); + return; + } + + char *map_str = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_str == MAP_FAILED) { + close(fd); + return; + } + + mXkbMap = xkb_map_new_from_string(mXkbContext, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, (xkb_keymap_compile_flags)0); + munmap(map_str, size); + close(fd); + + mXkbState = xkb_state_new(mXkbMap); +#else Q_UNUSED(format); Q_UNUSED(fd); Q_UNUSED(size); +#endif } void QWaylandInputDevice::keyboard_enter(uint32_t time, struct wl_surface *surface, struct wl_array *keys) @@ -527,15 +571,15 @@ void QWaylandInputDevice::keyboard_key(uint32_t serial, uint32_t time, uint32_t Qt::KeyboardModifiers modifiers = translateModifiers(mXkbState); QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease; - char s[2]; - sym = translateKey(sym, s, sizeof s); + uint utf32 = xkb_keysym_to_utf32(sym); + QString text = QString::fromUcs4(&utf32, 1); - if (window) - QWindowSystemInterface::handleExtendedKeyEvent(window->window(), - time, type, sym, - modifiers, - code, 0, 0, - QString::fromLatin1(s)); + int qtkey = keysymToQtKey(sym, modifiers, text); + + QWindowSystemInterface::handleExtendedKeyEvent(window->window(), + time, type, qtkey, + modifiers, + code, 0, 0, text); } #else // Generic fallback for single hard keys: Assume 'key' is a Qt key code. |