diff --git a/src/client/client.pro b/src/client/client.pro
index 29016c9c8ec96c94c9a17a7c998be6c690a8a104..ba17b21c57cf2bd84b0946e12be1b223b7659a6a 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 009ef670e7d5587344ff6291b1c97849d6078383..9ac678c93b53185094685e012a7e833c9f3c799c 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 303b9601a35ecd40d5676ca0335182eb6c32d4ec..f8c8bdc1f63ee2c9c9269e5f26a2e0ea2a591001 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 04a9e317c6056da817165b7536364cc52e1d6458..7360e7dca6bafbd8eee2b7b6720885acafd7e27a 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 5af3e8c29cb5be42812215b2a2b31d06d35bb9e3..bcee40fb405e11d3968c672112f6e639ebfc45de 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 44503114eda454f5ea28adc01c870a1ee3d7de48..d394aad1b8fc5f1a6b8b4d76d0a210ce5fa43909 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 d70facd5c708348d1810dfbd489e74ece53109d5..eb66f69495d4469c1d324e2e9b980bb8351b48f6 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 0000000000000000000000000000000000000000..c947902bdef4327bc51dc16f5085e0b14e074d24
--- /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 0000000000000000000000000000000000000000..91e69ab0378aa68fd4296781d46792b7252701f8
--- /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