summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorGiulio Camuffo <giuliocamuffo@gmail.com>2013-08-13 11:25:46 +0200
committerAndy Nichols <andy.nichols@digia.com>2013-08-22 11:44:56 +0200
commit536420a28952b0f58bdb539595e8a4c00a8dbddf (patch)
tree20d5ee8db5ee7aa45fac948ec29a249a6cb5cbcc /src/plugins/platforms
parent7ff722f3c9d29ef501a9cb47bebe6c7e8d3c5a88 (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.cpp84
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.