diff options
author | Giulio Camuffo <giulio.camuffo@jollamobile.com> | 2015-04-22 13:45:28 +0300 |
---|---|---|
committer | Giulio Camuffo <giulio.camuffo@jollamobile.com> | 2015-07-23 07:29:02 +0000 |
commit | e57908347009dd1199bd167eeb518f7a5d2ff6d6 (patch) | |
tree | ff51d36f8ec2bf6eb09df5cd3c7c3b4d253610d0 | |
parent | 9f19981d2a237cdc4d2c9c3a1b2418a472c7b841 (diff) | |
download | qtwayland-e57908347009dd1199bd167eeb518f7a5d2ff6d6.tar.gz qtwayland-e57908347009dd1199bd167eeb518f7a5d2ff6d6.tar.bz2 qtwayland-e57908347009dd1199bd167eeb518f7a5d2ff6d6.zip |
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.pro | 2 | ||||
-rw-r--r-- | src/client/qwaylandinputdevice.cpp | 158 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlcompositor.cpp | 53 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlcompositor_p.h | 2 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlkeyboard.cpp | 21 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/qwlkeyboard_p.h | 10 | ||||
-rw-r--r-- | src/compositor/wayland_wrapper/wayland_wrapper.pri | 2 | ||||
-rw-r--r-- | src/shared/qwaylandxkb.cpp | 202 | ||||
-rw-r--r-- | src/shared/qwaylandxkb.h | 56 |
9 files changed, 341 insertions, 165 deletions
diff --git a/src/client/client.pro b/src/client/client.pro index 29016c9c..ba17b21c 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 009ef670..9ac678c9 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 303b9601..f8c8bdc1 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 04a9e317..7360e7dc 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 5af3e8c2..bcee40fb 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 44503114..d394aad1 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 d70facd5..eb66f694 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 00000000..c947902b --- /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 00000000..91e69ab0 --- /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 |