summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiulio Camuffo <giulio.camuffo@jollamobile.com>2015-04-22 13:45:28 +0300
committerGiulio Camuffo <giulio.camuffo@jollamobile.com>2015-07-23 07:29:02 +0000
commite57908347009dd1199bd167eeb518f7a5d2ff6d6 (patch)
treeff51d36f8ec2bf6eb09df5cd3c7c3b4d253610d0
parent9f19981d2a237cdc4d2c9c3a1b2418a472c7b841 (diff)
Use xkbcommon for internal key events too
To manage the keyboard state and send key events to clients we use the xkbcommon library (unless disabled). That means that we currently have a separation between key events outgoing to clients and key events being used internally in the compositor, resulting in different keysyms being produced in the two cases for the same hardware key. Filter the key events coming from the underlying platform and modify them according to the xkb state instead. Change-Id: I4c6678be68e5b214b2b9cd0222dc9f425c580085 Reviewed-by: Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> Reviewed-by: Robin Burchell <robin.burchell@viroteck.net>
-rw-r--r--src/client/client.pro2
-rw-r--r--src/client/qwaylandinputdevice.cpp158
-rw-r--r--src/compositor/wayland_wrapper/qwlcompositor.cpp53
-rw-r--r--src/compositor/wayland_wrapper/qwlcompositor_p.h2
-rw-r--r--src/compositor/wayland_wrapper/qwlkeyboard.cpp21
-rw-r--r--src/compositor/wayland_wrapper/qwlkeyboard_p.h10
-rw-r--r--src/compositor/wayland_wrapper/wayland_wrapper.pri2
-rw-r--r--src/shared/qwaylandxkb.cpp202
-rw-r--r--src/shared/qwaylandxkb.h56
9 files changed, 341 insertions, 165 deletions
diff --git a/src/client/client.pro b/src/client/client.pro
index 29016c9c8..ba17b21c5 100644
--- a/src/client/client.pro
+++ b/src/client/client.pro
@@ -75,6 +75,7 @@ SOURCES += qwaylandintegration.cpp \
qwaylandtouch.cpp \
qwaylandqtkey.cpp \
../shared/qwaylandmimehelper.cpp \
+ ../shared/qwaylandxkb.cpp \
qwaylandabstractdecoration.cpp \
qwaylanddecorationfactory.cpp \
qwaylanddecorationplugin.cpp \
@@ -107,6 +108,7 @@ HEADERS += qwaylandintegration_p.h \
qwaylandtouch_p.h \
qwaylandqtkey_p.h \
../shared/qwaylandmimehelper.h \
+ ../shared/qwaylandxkb.h \
qwaylandabstractdecoration_p.h \
qwaylanddecorationfactory_p.h \
qwaylanddecorationplugin_p.h \
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp
index 009ef670e..9ac678c93 100644
--- a/src/client/qwaylandinputdevice.cpp
+++ b/src/client/qwaylandinputdevice.cpp
@@ -42,6 +42,7 @@
#include "qwaylandscreen_p.h"
#include "qwaylandcursor_p.h"
#include "qwaylanddisplay_p.h"
+#include "../shared/qwaylandxkb.h"
#include <QtGui/private/qpixmap_raster_p.h>
#include <qpa/qplatformwindow.h>
@@ -302,16 +303,7 @@ Qt::KeyboardModifiers QWaylandInputDevice::Keyboard::modifiers() const
if (!mXkbState)
return ret;
- xkb_state_component cstate = static_cast<xkb_state_component>(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED);
-
- if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_SHIFT, cstate))
- ret |= Qt::ShiftModifier;
- if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_CTRL, cstate))
- ret |= Qt::ControlModifier;
- if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_ALT, cstate))
- ret |= Qt::AltModifier;
- if (xkb_state_mod_name_is_active(mXkbState, XKB_MOD_NAME_LOGO, cstate))
- ret |= Qt::MetaModifier;
+ ret = QWaylandXkb::modifiers(mXkbState);
#endif
return ret;
@@ -530,150 +522,6 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in
window->handleMouse(mParent, e);
}
-#ifndef QT_NO_WAYLAND_XKB
-
-static const uint32_t KeyTbl[] = {
- XKB_KEY_Escape, Qt::Key_Escape,
- XKB_KEY_Tab, Qt::Key_Tab,
- XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab,
- XKB_KEY_BackSpace, Qt::Key_Backspace,
- XKB_KEY_Return, Qt::Key_Return,
- XKB_KEY_Insert, Qt::Key_Insert,
- XKB_KEY_Delete, Qt::Key_Delete,
- XKB_KEY_Clear, Qt::Key_Delete,
- XKB_KEY_Pause, Qt::Key_Pause,
- XKB_KEY_Print, Qt::Key_Print,
-
- XKB_KEY_Home, Qt::Key_Home,
- XKB_KEY_End, Qt::Key_End,
- XKB_KEY_Left, Qt::Key_Left,
- XKB_KEY_Up, Qt::Key_Up,
- XKB_KEY_Right, Qt::Key_Right,
- XKB_KEY_Down, Qt::Key_Down,
- XKB_KEY_Prior, Qt::Key_PageUp,
- XKB_KEY_Next, Qt::Key_PageDown,
-
- XKB_KEY_Shift_L, Qt::Key_Shift,
- XKB_KEY_Shift_R, Qt::Key_Shift,
- XKB_KEY_Shift_Lock, Qt::Key_Shift,
- XKB_KEY_Control_L, Qt::Key_Control,
- XKB_KEY_Control_R, Qt::Key_Control,
- XKB_KEY_Meta_L, Qt::Key_Meta,
- XKB_KEY_Meta_R, Qt::Key_Meta,
- XKB_KEY_Alt_L, Qt::Key_Alt,
- XKB_KEY_Alt_R, Qt::Key_Alt,
- XKB_KEY_Caps_Lock, Qt::Key_CapsLock,
- XKB_KEY_Num_Lock, Qt::Key_NumLock,
- XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock,
- XKB_KEY_Super_L, Qt::Key_Super_L,
- XKB_KEY_Super_R, Qt::Key_Super_R,
- XKB_KEY_Menu, Qt::Key_Menu,
- XKB_KEY_Hyper_L, Qt::Key_Hyper_L,
- XKB_KEY_Hyper_R, Qt::Key_Hyper_R,
- XKB_KEY_Help, Qt::Key_Help,
-
- XKB_KEY_KP_Space, Qt::Key_Space,
- XKB_KEY_KP_Tab, Qt::Key_Tab,
- XKB_KEY_KP_Enter, Qt::Key_Enter,
- XKB_KEY_KP_Home, Qt::Key_Home,
- XKB_KEY_KP_Left, Qt::Key_Left,
- XKB_KEY_KP_Up, Qt::Key_Up,
- XKB_KEY_KP_Right, Qt::Key_Right,
- XKB_KEY_KP_Down, Qt::Key_Down,
- XKB_KEY_KP_Prior, Qt::Key_PageUp,
- XKB_KEY_KP_Next, Qt::Key_PageDown,
- XKB_KEY_KP_End, Qt::Key_End,
- XKB_KEY_KP_Begin, Qt::Key_Clear,
- XKB_KEY_KP_Insert, Qt::Key_Insert,
- XKB_KEY_KP_Delete, Qt::Key_Delete,
- XKB_KEY_KP_Equal, Qt::Key_Equal,
- XKB_KEY_KP_Multiply, Qt::Key_Asterisk,
- XKB_KEY_KP_Add, Qt::Key_Plus,
- XKB_KEY_KP_Separator, Qt::Key_Comma,
- XKB_KEY_KP_Subtract, Qt::Key_Minus,
- XKB_KEY_KP_Decimal, Qt::Key_Period,
- XKB_KEY_KP_Divide, Qt::Key_Slash,
-
- XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr,
- XKB_KEY_Multi_key, Qt::Key_Multi_key,
- XKB_KEY_Codeinput, Qt::Key_Codeinput,
- XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate,
- XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate,
- XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate,
-
- XKB_KEY_Mode_switch, Qt::Key_Mode_switch,
- XKB_KEY_script_switch, Qt::Key_Mode_switch,
-
- XKB_KEY_XF86Back, Qt::Key_Back,
- XKB_KEY_XF86Forward, Qt::Key_Forward,
-
- XKB_KEY_XF86AudioPlay, Qt::Key_MediaTogglePlayPause, //there isn't a PlayPause keysym, however just play keys are not common
- XKB_KEY_XF86AudioPause, Qt::Key_MediaPause,
- XKB_KEY_XF86AudioStop, Qt::Key_MediaStop,
- XKB_KEY_XF86AudioPrev, Qt::Key_MediaPrevious,
- XKB_KEY_XF86AudioNext, Qt::Key_MediaNext,
- XKB_KEY_XF86AudioRewind, Qt::Key_MediaPrevious,
- XKB_KEY_XF86AudioForward, Qt::Key_MediaNext,
- XKB_KEY_XF86AudioRecord, Qt::Key_MediaRecord,
-
- XKB_KEY_XF86AudioMute, Qt::Key_VolumeMute,
- XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown,
- XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp,
-
- XKB_KEY_XF86AudioRandomPlay, Qt::Key_AudioRandomPlay,
- XKB_KEY_XF86AudioRepeat, Qt::Key_AudioRepeat,
-
- XKB_KEY_XF86ZoomIn, Qt::Key_ZoomIn,
- XKB_KEY_XF86ZoomOut, Qt::Key_ZoomOut,
-
- XKB_KEY_XF86Eject, Qt::Key_Eject,
-
- 0, 0
-};
-
-static int keysymToQtKey(xkb_keysym_t key)
-{
- int code = 0;
- int i = 0;
- while (KeyTbl[i]) {
- if (key == KeyTbl[i]) {
- code = (int)KeyTbl[i+1];
- break;
- }
- i += 2;
- }
-
- return code;
-}
-
-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);
- }
-
- return code;
-}
-
-#endif // QT_NO_WAYLAND_XKB
-
void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd, uint32_t size)
{
#ifndef QT_NO_WAYLAND_XKB
@@ -795,7 +643,7 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time,
if (utf32)
text = QString::fromUcs4(&utf32, 1);
- qtkey = keysymToQtKey(sym, modifiers, text);
+ qtkey = QWaylandXkb::keysymToQtKey(sym, modifiers, text);
QWindowSystemInterface::handleExtendedKeyEvent(window->window(),
time, type, qtkey,
diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp
index 303b9601a..f8c8bdc1f 100644
--- a/src/compositor/wayland_wrapper/qwlcompositor.cpp
+++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp
@@ -63,6 +63,7 @@
#include "qwaylandsurfaceview.h"
#include "qwaylandshmformathelper.h"
#include "qwaylandoutput.h"
+#include "qwlkeyboard_p.h"
#include <QWindow>
#include <QSocketNotifier>
@@ -98,12 +99,61 @@
#include "hardware_integration/qwlclientbufferintegrationfactory_p.h"
#include "hardware_integration/qwlserverbufferintegrationfactory_p.h"
+#include "../shared/qwaylandxkb.h"
+
QT_BEGIN_NAMESPACE
namespace QtWayland {
static Compositor *compositor;
+class WindowSystemEventHandler : public QWindowSystemEventHandler
+{
+public:
+ WindowSystemEventHandler(Compositor *c) : compositor(c) {}
+ bool sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) Q_DECL_OVERRIDE
+ {
+ if (e->type == QWindowSystemInterfacePrivate::Key) {
+ QWindowSystemInterfacePrivate::KeyEvent *ke = static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e);
+ Keyboard *keyb = compositor->defaultInputDevice()->keyboardDevice();
+
+ uint32_t code = ke->nativeScanCode;
+ bool isDown = ke->keyType == QEvent::KeyPress;
+
+#ifndef QT_NO_WAYLAND_XKB
+ QString text;
+ Qt::KeyboardModifiers modifiers = QWaylandXkb::modifiers(keyb->xkbState());
+
+ const xkb_keysym_t sym = xkb_state_key_get_one_sym(keyb->xkbState(), code);
+ uint utf32 = xkb_keysym_to_utf32(sym);
+ if (utf32)
+ text = QString::fromUcs4(&utf32, 1);
+ int qtkey = QWaylandXkb::keysymToQtKey(sym, modifiers, text);
+
+ ke->key = qtkey;
+ ke->modifiers = modifiers;
+ ke->nativeVirtualKey = sym;
+ ke->nativeModifiers = keyb->xkbModsMask();
+ ke->unicode = text;
+#endif
+ if (!ke->repeat)
+ keyb->keyEvent(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED);
+
+ QWindowSystemEventHandler::sendEvent(e);
+
+ if (!ke->repeat) {
+ keyb->updateKeymap();
+ keyb->updateModifierState(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED);
+ }
+ } else {
+ QWindowSystemEventHandler::sendEvent(e);
+ }
+ return true;
+ }
+
+ Compositor *compositor;
+};
+
Compositor *Compositor::instance()
{
return compositor;
@@ -128,10 +178,13 @@ Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::Ex
, m_qtkeyExtension(0)
, m_textInputManager()
, m_inputPanel()
+ , m_eventHandler(new WindowSystemEventHandler(this))
, m_retainSelection(false)
{
m_timer.start();
compositor = this;
+
+ QWindowSystemInterfacePrivate::installWindowSystemEventHandler(m_eventHandler.data());
}
void Compositor::init()
diff --git a/src/compositor/wayland_wrapper/qwlcompositor_p.h b/src/compositor/wayland_wrapper/qwlcompositor_p.h
index 04a9e317c..7360e7dca 100644
--- a/src/compositor/wayland_wrapper/qwlcompositor_p.h
+++ b/src/compositor/wayland_wrapper/qwlcompositor_p.h
@@ -66,6 +66,7 @@ class WindowManagerServerIntegration;
class QMimeData;
class QPlatformScreenBuffer;
class QWaylandSurface;
+class QWindowSystemEventHandler;
namespace QtWayland {
@@ -220,6 +221,7 @@ protected:
QScopedPointer<TextInputManager> m_textInputManager;
QScopedPointer<InputPanel> m_inputPanel;
QList<QWaylandGlobalInterface *> m_globals;
+ QScopedPointer<QWindowSystemEventHandler> m_eventHandler;
static void bind_func(struct wl_client *client, void *data,
uint32_t version, uint32_t id);
diff --git a/src/compositor/wayland_wrapper/qwlkeyboard.cpp b/src/compositor/wayland_wrapper/qwlkeyboard.cpp
index 5af3e8c29..bcee40fb4 100644
--- a/src/compositor/wayland_wrapper/qwlkeyboard.cpp
+++ b/src/compositor/wayland_wrapper/qwlkeyboard.cpp
@@ -223,12 +223,9 @@ void Keyboard::key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
}
}
-void Keyboard::sendKeyEvent(uint code, uint32_t state)
+void Keyboard::keyEvent(uint code, uint32_t state)
{
- uint32_t time = m_compositor->currentTimeMsecs();
- uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
uint key = code - 8;
- m_grab->key(serial, time, key, state);
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
m_keys << key;
} else {
@@ -238,11 +235,14 @@ void Keyboard::sendKeyEvent(uint code, uint32_t state)
}
}
}
- updateModifierState(code, state);
+}
- // If keys are no longer pressed, update the keymap
- if (m_pendingKeymap && m_keys.isEmpty())
- updateKeymap();
+void Keyboard::sendKeyEvent(uint code, uint32_t state)
+{
+ uint32_t time = m_compositor->currentTimeMsecs();
+ uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
+ uint key = code - 8;
+ m_grab->key(serial, time, key, state);
}
void Keyboard::modifiers(uint32_t serial, uint32_t mods_depressed,
@@ -286,6 +286,11 @@ void Keyboard::updateModifierState(uint code, uint32_t state)
void Keyboard::updateKeymap()
{
+ // There must be no keys pressed when changing the keymap,
+ // see http://lists.freedesktop.org/archives/wayland-devel/2013-October/011395.html
+ if (!m_pendingKeymap || !m_keys.isEmpty())
+ return;
+
m_pendingKeymap = false;
#ifndef QT_NO_WAYLAND_XKB
if (!m_context)
diff --git a/src/compositor/wayland_wrapper/qwlkeyboard_p.h b/src/compositor/wayland_wrapper/qwlkeyboard_p.h
index 44503114e..d394aad1b 100644
--- a/src/compositor/wayland_wrapper/qwlkeyboard_p.h
+++ b/src/compositor/wayland_wrapper/qwlkeyboard_p.h
@@ -99,10 +99,18 @@ public:
void modifiers(uint32_t serial, uint32_t mods_depressed,
uint32_t mods_latched, uint32_t mods_locked, uint32_t group);
+ void keyEvent(uint code, uint32_t state);
+ void updateModifierState(uint code, uint32_t state);
+ void updateKeymap();
+
void startGrab(KeyboardGrabber *grab);
void endGrab();
KeyboardGrabber *currentGrab() const;
+#ifndef QT_NO_WAYLAND_XKB
+ struct xkb_state *xkbState() const { return m_state; }
+ uint32_t xkbModsMask() const { return m_modsDepressed | m_modsLatched | m_modsLocked; }
+#endif
Q_SIGNALS:
void focusChanged(Surface *surface);
@@ -114,8 +122,6 @@ protected:
private:
void sendKeyEvent(uint code, uint32_t state);
- void updateModifierState(uint code, uint32_t state);
- void updateKeymap();
void focusDestroyed(void *data);
#ifndef QT_NO_WAYLAND_XKB
diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri
index d70facd5c..eb66f6949 100644
--- a/src/compositor/wayland_wrapper/wayland_wrapper.pri
+++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri
@@ -36,6 +36,7 @@ HEADERS += \
wayland_wrapper/qwltextinputmanager_p.h \
wayland_wrapper/qwltouch_p.h \
wayland_wrapper/qwllistener_p.h \
+ ../shared/qwaylandxkb.h \
SOURCES += \
wayland_wrapper/qwlcompositor.cpp \
@@ -64,6 +65,7 @@ SOURCES += \
wayland_wrapper/qwltextinputmanager.cpp \
wayland_wrapper/qwltouch.cpp \
wayland_wrapper/qwllistener.cpp \
+ ../shared/qwaylandxkb.cpp \
INCLUDEPATH += wayland_wrapper
diff --git a/src/shared/qwaylandxkb.cpp b/src/shared/qwaylandxkb.cpp
new file mode 100644
index 000000000..c947902bd
--- /dev/null
+++ b/src/shared/qwaylandxkb.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jolla Ltd
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwaylandxkb.h"
+
+#include <QString>
+
+#ifndef QT_NO_WAYLAND_XKB
+
+#include <xkbcommon/xkbcommon-keysyms.h>
+
+QT_BEGIN_NAMESPACE
+
+static const uint32_t KeyTbl[] = {
+ XKB_KEY_Escape, Qt::Key_Escape,
+ XKB_KEY_Tab, Qt::Key_Tab,
+ XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab,
+ XKB_KEY_BackSpace, Qt::Key_Backspace,
+ XKB_KEY_Return, Qt::Key_Return,
+ XKB_KEY_Insert, Qt::Key_Insert,
+ XKB_KEY_Delete, Qt::Key_Delete,
+ XKB_KEY_Clear, Qt::Key_Delete,
+ XKB_KEY_Pause, Qt::Key_Pause,
+ XKB_KEY_Print, Qt::Key_Print,
+
+ XKB_KEY_Home, Qt::Key_Home,
+ XKB_KEY_End, Qt::Key_End,
+ XKB_KEY_Left, Qt::Key_Left,
+ XKB_KEY_Up, Qt::Key_Up,
+ XKB_KEY_Right, Qt::Key_Right,
+ XKB_KEY_Down, Qt::Key_Down,
+ XKB_KEY_Prior, Qt::Key_PageUp,
+ XKB_KEY_Next, Qt::Key_PageDown,
+
+ XKB_KEY_Shift_L, Qt::Key_Shift,
+ XKB_KEY_Shift_R, Qt::Key_Shift,
+ XKB_KEY_Shift_Lock, Qt::Key_Shift,
+ XKB_KEY_Control_L, Qt::Key_Control,
+ XKB_KEY_Control_R, Qt::Key_Control,
+ XKB_KEY_Meta_L, Qt::Key_Meta,
+ XKB_KEY_Meta_R, Qt::Key_Meta,
+ XKB_KEY_Alt_L, Qt::Key_Alt,
+ XKB_KEY_Alt_R, Qt::Key_Alt,
+ XKB_KEY_Caps_Lock, Qt::Key_CapsLock,
+ XKB_KEY_Num_Lock, Qt::Key_NumLock,
+ XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock,
+ XKB_KEY_Super_L, Qt::Key_Super_L,
+ XKB_KEY_Super_R, Qt::Key_Super_R,
+ XKB_KEY_Menu, Qt::Key_Menu,
+ XKB_KEY_Hyper_L, Qt::Key_Hyper_L,
+ XKB_KEY_Hyper_R, Qt::Key_Hyper_R,
+ XKB_KEY_Help, Qt::Key_Help,
+
+ XKB_KEY_KP_Space, Qt::Key_Space,
+ XKB_KEY_KP_Tab, Qt::Key_Tab,
+ XKB_KEY_KP_Enter, Qt::Key_Enter,
+ XKB_KEY_KP_Home, Qt::Key_Home,
+ XKB_KEY_KP_Left, Qt::Key_Left,
+ XKB_KEY_KP_Up, Qt::Key_Up,
+ XKB_KEY_KP_Right, Qt::Key_Right,
+ XKB_KEY_KP_Down, Qt::Key_Down,
+ XKB_KEY_KP_Prior, Qt::Key_PageUp,
+ XKB_KEY_KP_Next, Qt::Key_PageDown,
+ XKB_KEY_KP_End, Qt::Key_End,
+ XKB_KEY_KP_Begin, Qt::Key_Clear,
+ XKB_KEY_KP_Insert, Qt::Key_Insert,
+ XKB_KEY_KP_Delete, Qt::Key_Delete,
+ XKB_KEY_KP_Equal, Qt::Key_Equal,
+ XKB_KEY_KP_Multiply, Qt::Key_Asterisk,
+ XKB_KEY_KP_Add, Qt::Key_Plus,
+ XKB_KEY_KP_Separator, Qt::Key_Comma,
+ XKB_KEY_KP_Subtract, Qt::Key_Minus,
+ XKB_KEY_KP_Decimal, Qt::Key_Period,
+ XKB_KEY_KP_Divide, Qt::Key_Slash,
+
+ XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr,
+ XKB_KEY_Multi_key, Qt::Key_Multi_key,
+ XKB_KEY_Codeinput, Qt::Key_Codeinput,
+ XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate,
+ XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate,
+ XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate,
+
+ XKB_KEY_Mode_switch, Qt::Key_Mode_switch,
+ XKB_KEY_script_switch, Qt::Key_Mode_switch,
+
+ XKB_KEY_XF86AudioPlay, Qt::Key_MediaTogglePlayPause, //there isn't a PlayPause keysym, however just play keys are not common
+ XKB_KEY_XF86AudioPause, Qt::Key_MediaPause,
+ XKB_KEY_XF86AudioStop, Qt::Key_MediaStop,
+ XKB_KEY_XF86AudioPrev, Qt::Key_MediaPrevious,
+ XKB_KEY_XF86AudioNext, Qt::Key_MediaNext,
+ XKB_KEY_XF86AudioRewind, Qt::Key_MediaPrevious,
+ XKB_KEY_XF86AudioForward, Qt::Key_MediaNext,
+ XKB_KEY_XF86AudioRecord, Qt::Key_MediaRecord,
+
+ XKB_KEY_XF86AudioMute, Qt::Key_VolumeMute,
+ XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown,
+ XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp,
+
+ XKB_KEY_XF86AudioRandomPlay, Qt::Key_AudioRandomPlay,
+ XKB_KEY_XF86AudioRepeat, Qt::Key_AudioRepeat,
+
+ XKB_KEY_XF86ZoomIn, Qt::Key_ZoomIn,
+ XKB_KEY_XF86ZoomOut, Qt::Key_ZoomOut,
+
+ XKB_KEY_XF86Eject, Qt::Key_Eject,
+
+ 0, 0
+};
+
+static int lookupKeysym(xkb_keysym_t key)
+{
+ int code = 0;
+ int i = 0;
+ while (KeyTbl[i]) {
+ if (key == KeyTbl[i]) {
+ code = (int)KeyTbl[i+1];
+ break;
+ }
+ i += 2;
+ }
+
+ return code;
+}
+
+int QWaylandXkb::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 = lookupKeysym(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 = lookupKeysym(keysym);
+ }
+
+ return code;
+}
+
+Qt::KeyboardModifiers QWaylandXkb::modifiers(struct xkb_state *state)
+{
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+
+ xkb_state_component cstate = static_cast<xkb_state_component>(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED | XKB_STATE_LOCKED);
+
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT, cstate))
+ modifiers |= Qt::ShiftModifier;
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, cstate))
+ modifiers |= Qt::ControlModifier;
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, cstate))
+ modifiers |= Qt::AltModifier;
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, cstate))
+ modifiers |= Qt::MetaModifier;
+
+ return modifiers;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_WAYLAND_XKB
diff --git a/src/shared/qwaylandxkb.h b/src/shared/qwaylandxkb.h
new file mode 100644
index 000000000..91e69ab03
--- /dev/null
+++ b/src/shared/qwaylandxkb.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Copyright (C) 2015 Jolla Ltd
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDXKB_H
+#define QWAYLANDXKB_H
+
+#ifndef QT_NO_WAYLAND_XKB
+
+#include <Qt>
+#include <xkbcommon/xkbcommon.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandXkb
+{
+public:
+ static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text);
+ static Qt::KeyboardModifiers modifiers(struct xkb_state *state);
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_WAYLAND_XKB
+
+#endif