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