summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGatis Paeglis <gatis.paeglis@qt.io>2018-11-30 12:14:51 +0100
committerGatis Paeglis <gatis.paeglis@qt.io>2019-03-01 14:31:28 +0000
commita34e81ab8be6445877e040b1afb85deeaa725f86 (patch)
tree39c1dbb4103c1cdfb3a044404994b277a40e1b83
parentf9421f0968b8067ca79d83dc75e35092ac4a4948 (diff)
platformsupport/input: add xkbcommon utilities lib
xcb/eglfs/wayland - all use XKB keyboard configs and APIs. There is a lot of duplicated and naturally a diverging code. This patch adds a helper library to avoid all the mentioned problems and unify feature set between these platforms. qlibinputkeyboard: Added a fixup for 2803cdf758dbae1006a0c50300af12dac9f71531. From spec: "keysyms, when bound to modifiers, affect the rules [..]", meaning we can't look at keys in isolation, but have to check if bounding exists in the keymap. This is done by using xkb_state_mod_name_is_active() API, but that API has its limitations - https://github.com/xkbcommon/libxkbcommon/issues/88 I will fix this separately in the LTS (5.12) branch. We need to read the modifier state before the key action. This patch fixes a regression introduced by aforementioned patch, which caused modifiers being reported wrongly in QKeyEvent::modifiers(). qtwayland: Moved toKeysym(QKeyEvent) from qtwayland repository into this library. For this and other key mapping functionality wayland was duplicating the key table. All of that will be removed from qtwayland, and calls will be replaced to use this lib. Adjusted toKeysym() to fix QTBUG-71301. Qt keys don't map to ASCII codes, so first we need search in our key table, instead of mapping from unicode. lookupStringNoKeysymTransformations(): fixed off-by-one error, where we were including terminating NUL in QString. Fixes: QTBUG-71301 Task-number: QTBUG-65503 Change-Id: Idfddea5b34ad620235dc08c0b9e5a0669111821a Reviewed-by: Johan Helsing <johan.helsing@qt.io>
-rw-r--r--src/platformsupport/input/input-support.pro35
-rw-r--r--src/platformsupport/input/input.pro37
-rw-r--r--src/platformsupport/input/libinput/libinput.pri5
-rw-r--r--src/platformsupport/input/libinput/qlibinputkeyboard.cpp185
-rw-r--r--src/platformsupport/input/libinput/qlibinputkeyboard_p.h8
-rw-r--r--src/platformsupport/input/xkbcommon/qxkbcommon.cpp797
-rw-r--r--src/platformsupport/input/xkbcommon/qxkbcommon_3rdparty.cpp (renamed from src/plugins/platforms/xcb/qxcbxkbcommon.h)28
-rw-r--r--src/platformsupport/input/xkbcommon/qxkbcommon_p.h118
-rw-r--r--src/platformsupport/input/xkbcommon/xkbcommon.pro23
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp723
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h35
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro4
-rw-r--r--sync.profile1
13 files changed, 1043 insertions, 956 deletions
diff --git a/src/platformsupport/input/input-support.pro b/src/platformsupport/input/input-support.pro
new file mode 100644
index 0000000000..3d39210b9e
--- /dev/null
+++ b/src/platformsupport/input/input-support.pro
@@ -0,0 +1,35 @@
+TARGET = QtInputSupport
+MODULE = input_support
+
+QT = core-private gui-private devicediscovery_support-private
+CONFIG += static internal_module
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
+
+qtConfig(evdev) {
+ include($$PWD/evdevmouse/evdevmouse.pri)
+ include($$PWD/evdevkeyboard/evdevkeyboard.pri)
+ include($$PWD/evdevtouch/evdevtouch.pri)
+ qtConfig(tabletevent) {
+ include($$PWD/evdevtablet/evdevtablet.pri)
+ }
+}
+
+qtConfig(tslib) {
+ include($$PWD/tslib/tslib.pri)
+}
+
+qtConfig(libinput) {
+ include($$PWD/libinput/libinput.pri)
+}
+
+qtConfig(evdev)|qtConfig(libinput) {
+ include($$PWD/shared/shared.pri)
+}
+
+qtConfig(integrityhid) {
+ include($$PWD/integrityhid/integrityhid.pri)
+}
+
+load(qt_module)
diff --git a/src/platformsupport/input/input.pro b/src/platformsupport/input/input.pro
index 3d39210b9e..138c04dea3 100644
--- a/src/platformsupport/input/input.pro
+++ b/src/platformsupport/input/input.pro
@@ -1,35 +1,8 @@
-TARGET = QtInputSupport
-MODULE = input_support
+TEMPLATE = subdirs
+QT_FOR_CONFIG += gui-private
-QT = core-private gui-private devicediscovery_support-private
-CONFIG += static internal_module
+qtConfig(xkbcommon): SUBDIRS += xkbcommon
-DEFINES += QT_NO_CAST_FROM_ASCII
-PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
+SUBDIRS += input-support.pro ### FIXME - QTBUG-52657
-qtConfig(evdev) {
- include($$PWD/evdevmouse/evdevmouse.pri)
- include($$PWD/evdevkeyboard/evdevkeyboard.pri)
- include($$PWD/evdevtouch/evdevtouch.pri)
- qtConfig(tabletevent) {
- include($$PWD/evdevtablet/evdevtablet.pri)
- }
-}
-
-qtConfig(tslib) {
- include($$PWD/tslib/tslib.pri)
-}
-
-qtConfig(libinput) {
- include($$PWD/libinput/libinput.pri)
-}
-
-qtConfig(evdev)|qtConfig(libinput) {
- include($$PWD/shared/shared.pri)
-}
-
-qtConfig(integrityhid) {
- include($$PWD/integrityhid/integrityhid.pri)
-}
-
-load(qt_module)
+CONFIG += ordered
diff --git a/src/platformsupport/input/libinput/libinput.pri b/src/platformsupport/input/libinput/libinput.pri
index 476f20c1b8..f80b5f41d9 100644
--- a/src/platformsupport/input/libinput/libinput.pri
+++ b/src/platformsupport/input/libinput/libinput.pri
@@ -14,4 +14,7 @@ QMAKE_USE_PRIVATE += libudev libinput
INCLUDEPATH += $$PWD/../shared
-qtConfig(xkbcommon): QMAKE_USE_PRIVATE += xkbcommon
+qtConfig(xkbcommon): {
+ QMAKE_USE_PRIVATE += xkbcommon
+ QT += xkbcommon_support-private
+}
diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp
index baef769bc9..6586b084f1 100644
--- a/src/platformsupport/input/libinput/qlibinputkeyboard.cpp
+++ b/src/platformsupport/input/libinput/qlibinputkeyboard.cpp
@@ -47,6 +47,7 @@
#if QT_CONFIG(xkbcommon)
#include <xkbcommon/xkbcommon-keysyms.h>
#include <xkbcommon/xkbcommon-names.h>
+#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#endif
QT_BEGIN_NAMESPACE
@@ -56,88 +57,7 @@ Q_DECLARE_LOGGING_CATEGORY(qLcLibInput)
const int REPEAT_DELAY = 500;
const int REPEAT_RATE = 100;
-#if QT_CONFIG(xkbcommon)
-struct KeyTabEntry {
- int xkbkey;
- int qtkey;
-};
-
-static inline bool operator==(const KeyTabEntry &a, const KeyTabEntry &b)
-{
- return a.xkbkey == b.xkbkey;
-}
-
-static const KeyTabEntry keyTab[] = {
- { 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 },
-};
-#endif
-
QLibInputKeyboard::QLibInputKeyboard()
-#if QT_CONFIG(xkbcommon)
- : m_ctx(0),
- m_keymap(0),
- m_state(0),
- m_mods(Qt::NoModifier)
-#endif
{
#if QT_CONFIG(xkbcommon)
qCDebug(qLcLibInput) << "Using xkbcommon for key mapping";
@@ -148,18 +68,14 @@ QLibInputKeyboard::QLibInputKeyboard()
}
m_keymap = xkb_keymap_new_from_names(m_ctx, nullptr, XKB_KEYMAP_COMPILE_NO_FLAGS);
if (!m_keymap) {
- qWarning("Failed to compile keymap");
+ qCWarning(qLcLibInput, "Failed to compile keymap");
return;
}
m_state = xkb_state_new(m_keymap);
if (!m_state) {
- qWarning("Failed to create xkb state");
+ qCWarning(qLcLibInput, "Failed to create xkb state");
return;
}
- m_modindex[0] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_CTRL);
- m_modindex[1] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_ALT);
- m_modindex[2] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_SHIFT);
- m_modindex[3] = xkb_keymap_mod_get_index(m_keymap, XKB_MOD_NAME_LOGO);
m_repeatTimer.setSingleShot(true);
connect(&m_repeatTimer, &QTimer::timeout, this, &QLibInputKeyboard::handleRepeat);
@@ -186,52 +102,33 @@ void QLibInputKeyboard::processKey(libinput_event_keyboard *e)
if (!m_ctx || !m_keymap || !m_state)
return;
- const uint32_t k = libinput_event_keyboard_get_key(e) + 8;
+ const uint32_t keycode = libinput_event_keyboard_get_key(e) + 8;
+ const xkb_keysym_t sym = xkb_state_key_get_one_sym(m_state, keycode);
const bool pressed = libinput_event_keyboard_get_key_state(e) == LIBINPUT_KEY_STATE_PRESSED;
- QVarLengthArray<char, 32> chars(32);
- const int size = xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size());
- if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL
- chars.resize(size + 1);
- xkb_state_key_get_utf8(m_state, k, chars.data(), chars.size());
- }
- const QString text = QString::fromUtf8(chars.constData(), size);
-
- const xkb_keysym_t sym = xkb_state_key_get_one_sym(m_state, k);
+ // Modifiers here is the modifier state before the event, i.e. not
+ // including the current key in case it is a modifier. See the XOR
+ // logic in QKeyEvent::modifiers(). ### QTBUG-73826
+ Qt::KeyboardModifiers modifiers = QXkbCommon::modifiers(m_state);
- // mods here is the modifier state before the event, i.e. not
- // including the current key in case it is a modifier.
- Qt::KeyboardModifiers mods = Qt::NoModifier;
- const int qtkey = keysymToQtKey(sym, &mods, text);
+ const QString text = QXkbCommon::lookupString(m_state, keycode);
+ const int qtkey = QXkbCommon::keysymToQtKey(sym, modifiers, m_state, keycode);
- if (qtkey == Qt::Key_Control)
- mods |= Qt::ControlModifier;
- if (qtkey == Qt::Key_Alt)
- mods |= Qt::AltModifier;
- if (qtkey == Qt::Key_Shift)
- mods |= Qt::ShiftModifier;
- if (qtkey == Qt::Key_Meta)
- mods |= Qt::MetaModifier;
- xkb_state_update_key(m_state, k, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);
+ xkb_state_update_key(m_state, keycode, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);
- if (mods != Qt::NoModifier) {
- if (pressed)
- m_mods |= mods;
- else
- m_mods &= ~mods;
+ Qt::KeyboardModifiers modifiersAfterStateChange = QXkbCommon::modifiers(m_state);
+ QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(modifiersAfterStateChange);
- QGuiApplicationPrivate::inputDeviceManager()->setKeyboardModifiers(m_mods);
- }
QWindowSystemInterface::handleExtendedKeyEvent(nullptr,
pressed ? QEvent::KeyPress : QEvent::KeyRelease,
- qtkey, m_mods, k, sym, m_mods, text);
+ qtkey, modifiers, keycode, sym, modifiers, text);
- if (pressed && xkb_keymap_key_repeats(m_keymap, k)) {
+ if (pressed && xkb_keymap_key_repeats(m_keymap, keycode)) {
m_repeatData.qtkey = qtkey;
- m_repeatData.mods = mods;
- m_repeatData.nativeScanCode = k;
+ m_repeatData.mods = modifiers;
+ m_repeatData.nativeScanCode = keycode;
m_repeatData.virtualKey = sym;
- m_repeatData.nativeMods = mods;
+ m_repeatData.nativeMods = modifiers;
m_repeatData.unicodeText = text;
m_repeatData.repeatCount = 1;
m_repeatTimer.setInterval(REPEAT_DELAY);
@@ -256,50 +153,6 @@ void QLibInputKeyboard::handleRepeat()
m_repeatTimer.setInterval(REPEAT_RATE);
m_repeatTimer.start();
}
-
-int QLibInputKeyboard::keysymToQtKey(xkb_keysym_t key) const
-{
- const size_t elemCount = sizeof(keyTab) / sizeof(KeyTabEntry);
- KeyTabEntry e;
- e.xkbkey = key;
- const KeyTabEntry *result = std::find(keyTab, keyTab + elemCount, e);
- return result != keyTab + elemCount ? result->qtkey : 0;
-}
-
-int QLibInputKeyboard::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers *modifiers, const QString &text) const
-{
- int code = 0;
-#if QT_CONFIG(textcodec)
- QTextCodec *systemCodec = QTextCodec::codecForLocale();
-#endif
- if (keysym < 128 || (keysym < 256
-#if QT_CONFIG(textcodec)
- && systemCodec->mibEnum() == 4
-#endif
- )) {
- // upper-case key, if known
- code = isprint((int)keysym) ? toupper((int)keysym) : 0;
- } else if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
- // function keys
- 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_longsolidusoverlay)) {
- code = text.unicode()->toUpper().unicode();
- } else {
- // any other keys
- code = keysymToQtKey(keysym);
- }
- return code;
-}
#endif
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/libinput/qlibinputkeyboard_p.h b/src/platformsupport/input/libinput/qlibinputkeyboard_p.h
index 14ae71b545..7521902e02 100644
--- a/src/platformsupport/input/libinput/qlibinputkeyboard_p.h
+++ b/src/platformsupport/input/libinput/qlibinputkeyboard_p.h
@@ -79,10 +79,9 @@ private:
int keysymToQtKey(xkb_keysym_t key) const;
int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers *modifiers, const QString &text) const;
- xkb_context *m_ctx;
- xkb_keymap *m_keymap;
- xkb_state *m_state;
- xkb_mod_index_t m_modindex[4];
+ xkb_context *m_ctx = nullptr;
+ xkb_keymap *m_keymap = nullptr;
+ xkb_state *m_state = nullptr;
QTimer m_repeatTimer;
@@ -95,7 +94,6 @@ private:
QString unicodeText;
int repeatCount;
} m_repeatData;
- Qt::KeyboardModifiers m_mods;
#endif
};
diff --git a/src/platformsupport/input/xkbcommon/qxkbcommon.cpp b/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
new file mode 100644
index 0000000000..4bee868fa9
--- /dev/null
+++ b/src/platformsupport/input/xkbcommon/qxkbcommon.cpp
@@ -0,0 +1,797 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxkbcommon_p.h"
+
+#include <private/qmakearray_p.h>
+
+#include <QtGui/QKeyEvent>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcXkbcommon, "qt.xkbcommon")
+
+static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
+ xkb_state *state, xkb_keycode_t code,
+ bool superAsMeta, bool hyperAsMeta);
+
+typedef struct xkb2qt
+{
+ unsigned int xkb;
+ unsigned int qt;
+
+ constexpr bool operator <=(const xkb2qt &that) const noexcept
+ {
+ return xkb <= that.xkb;
+ }
+
+ constexpr bool operator <(const xkb2qt &that) const noexcept
+ {
+ return xkb < that.xkb;
+ }
+} xkb2qt_t;
+
+template<std::size_t Xkb, std::size_t Qt>
+struct Xkb2Qt
+{
+ using Type = xkb2qt_t;
+ static constexpr Type data() noexcept { return Type{Xkb, Qt}; }
+};
+
+static constexpr const auto KeyTbl = qMakeArray(
+ QSortedData<
+ // misc keys
+
+ Xkb2Qt<XKB_KEY_Escape, Qt::Key_Escape>,
+ Xkb2Qt<XKB_KEY_Tab, Qt::Key_Tab>,
+ Xkb2Qt<XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab>,
+ Xkb2Qt<XKB_KEY_BackSpace, Qt::Key_Backspace>,
+ Xkb2Qt<XKB_KEY_Return, Qt::Key_Return>,
+ Xkb2Qt<XKB_KEY_Insert, Qt::Key_Insert>,
+ Xkb2Qt<XKB_KEY_Delete, Qt::Key_Delete>,
+ Xkb2Qt<XKB_KEY_Clear, Qt::Key_Delete>,
+ Xkb2Qt<XKB_KEY_Pause, Qt::Key_Pause>,
+ Xkb2Qt<XKB_KEY_Print, Qt::Key_Print>,
+ Xkb2Qt<0x1005FF60, Qt::Key_SysReq>, // hardcoded Sun SysReq
+ Xkb2Qt<0x1007ff00, Qt::Key_SysReq>, // hardcoded X386 SysReq
+
+ // cursor movement
+
+ Xkb2Qt<XKB_KEY_Home, Qt::Key_Home>,
+ Xkb2Qt<XKB_KEY_End, Qt::Key_End>,
+ Xkb2Qt<XKB_KEY_Left, Qt::Key_Left>,
+ Xkb2Qt<XKB_KEY_Up, Qt::Key_Up>,
+ Xkb2Qt<XKB_KEY_Right, Qt::Key_Right>,
+ Xkb2Qt<XKB_KEY_Down, Qt::Key_Down>,
+ Xkb2Qt<XKB_KEY_Prior, Qt::Key_PageUp>,
+ Xkb2Qt<XKB_KEY_Next, Qt::Key_PageDown>,
+
+ // modifiers
+
+ Xkb2Qt<XKB_KEY_Shift_L, Qt::Key_Shift>,
+ Xkb2Qt<XKB_KEY_Shift_R, Qt::Key_Shift>,
+ Xkb2Qt<XKB_KEY_Shift_Lock, Qt::Key_Shift>,
+ Xkb2Qt<XKB_KEY_Control_L, Qt::Key_Control>,
+ Xkb2Qt<XKB_KEY_Control_R, Qt::Key_Control>,
+ Xkb2Qt<XKB_KEY_Meta_L, Qt::Key_Meta>,
+ Xkb2Qt<XKB_KEY_Meta_R, Qt::Key_Meta>,
+ Xkb2Qt<XKB_KEY_Alt_L, Qt::Key_Alt>,
+ Xkb2Qt<XKB_KEY_Alt_R, Qt::Key_Alt>,
+ Xkb2Qt<XKB_KEY_Caps_Lock, Qt::Key_CapsLock>,
+ Xkb2Qt<XKB_KEY_Num_Lock, Qt::Key_NumLock>,
+ Xkb2Qt<XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock>,
+ Xkb2Qt<XKB_KEY_Super_L, Qt::Key_Super_L>,
+ Xkb2Qt<XKB_KEY_Super_R, Qt::Key_Super_R>,
+ Xkb2Qt<XKB_KEY_Menu, Qt::Key_Menu>,
+ Xkb2Qt<XKB_KEY_Hyper_L, Qt::Key_Hyper_L>,
+ Xkb2Qt<XKB_KEY_Hyper_R, Qt::Key_Hyper_R>,
+ Xkb2Qt<XKB_KEY_Help, Qt::Key_Help>,
+ Xkb2Qt<0x1000FF74, Qt::Key_Backtab>, // hardcoded HP backtab
+ Xkb2Qt<0x1005FF10, Qt::Key_F11>, // hardcoded Sun F36 (labeled F11)
+ Xkb2Qt<0x1005FF11, Qt::Key_F12>, // hardcoded Sun F37 (labeled F12)
+
+ // numeric and function keypad keys
+
+ Xkb2Qt<XKB_KEY_KP_Space, Qt::Key_Space>,
+ Xkb2Qt<XKB_KEY_KP_Tab, Qt::Key_Tab>,
+ Xkb2Qt<XKB_KEY_KP_Enter, Qt::Key_Enter>,
+ Xkb2Qt<XKB_KEY_KP_Home, Qt::Key_Home>,
+ Xkb2Qt<XKB_KEY_KP_Left, Qt::Key_Left>,
+ Xkb2Qt<XKB_KEY_KP_Up, Qt::Key_Up>,
+ Xkb2Qt<XKB_KEY_KP_Right, Qt::Key_Right>,
+ Xkb2Qt<XKB_KEY_KP_Down, Qt::Key_Down>,
+ Xkb2Qt<XKB_KEY_KP_Prior, Qt::Key_PageUp>,
+ Xkb2Qt<XKB_KEY_KP_Next, Qt::Key_PageDown>,
+ Xkb2Qt<XKB_KEY_KP_End, Qt::Key_End>,
+ Xkb2Qt<XKB_KEY_KP_Begin, Qt::Key_Clear>,
+ Xkb2Qt<XKB_KEY_KP_Insert, Qt::Key_Insert>,
+ Xkb2Qt<XKB_KEY_KP_Delete, Qt::Key_Delete>,
+ Xkb2Qt<XKB_KEY_KP_Equal, Qt::Key_Equal>,
+ Xkb2Qt<XKB_KEY_KP_Multiply, Qt::Key_Asterisk>,
+ Xkb2Qt<XKB_KEY_KP_Add, Qt::Key_Plus>,
+ Xkb2Qt<XKB_KEY_KP_Separator, Qt::Key_Comma>,
+ Xkb2Qt<XKB_KEY_KP_Subtract, Qt::Key_Minus>,
+ Xkb2Qt<XKB_KEY_KP_Decimal, Qt::Key_Period>,
+ Xkb2Qt<XKB_KEY_KP_Divide, Qt::Key_Slash>,
+
+ // special non-XF86 function keys
+
+ Xkb2Qt<XKB_KEY_Undo, Qt::Key_Undo>,
+ Xkb2Qt<XKB_KEY_Redo, Qt::Key_Redo>,
+ Xkb2Qt<XKB_KEY_Find, Qt::Key_Find>,
+ Xkb2Qt<XKB_KEY_Cancel, Qt::Key_Cancel>,
+
+ // International input method support keys
+
+ // International & multi-key character composition
+ Xkb2Qt<XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr>,
+ Xkb2Qt<XKB_KEY_Multi_key, Qt::Key_Multi_key>,
+ Xkb2Qt<XKB_KEY_Codeinput, Qt::Key_Codeinput>,
+ Xkb2Qt<XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate>,
+ Xkb2Qt<XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate>,
+ Xkb2Qt<XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate>,
+
+ // Misc Functions
+ Xkb2Qt<XKB_KEY_Mode_switch, Qt::Key_Mode_switch>,
+ Xkb2Qt<XKB_KEY_script_switch, Qt::Key_Mode_switch>,
+
+ // Japanese keyboard support
+ Xkb2Qt<XKB_KEY_Kanji, Qt::Key_Kanji>,
+ Xkb2Qt<XKB_KEY_Muhenkan, Qt::Key_Muhenkan>,
+ //Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan_Mode>,
+ Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan>,
+ Xkb2Qt<XKB_KEY_Henkan, Qt::Key_Henkan>,
+ Xkb2Qt<XKB_KEY_Romaji, Qt::Key_Romaji>,
+ Xkb2Qt<XKB_KEY_Hiragana, Qt::Key_Hiragana>,
+ Xkb2Qt<XKB_KEY_Katakana, Qt::Key_Katakana>,
+ Xkb2Qt<XKB_KEY_Hiragana_Katakana, Qt::Key_Hiragana_Katakana>,
+ Xkb2Qt<XKB_KEY_Zenkaku, Qt::Key_Zenkaku>,
+ Xkb2Qt<XKB_KEY_Hankaku, Qt::Key_Hankaku>,
+ Xkb2Qt<XKB_KEY_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku>,
+ Xkb2Qt<XKB_KEY_Touroku, Qt::Key_Touroku>,
+ Xkb2Qt<XKB_KEY_Massyo, Qt::Key_Massyo>,
+ Xkb2Qt<XKB_KEY_Kana_Lock, Qt::Key_Kana_Lock>,
+ Xkb2Qt<XKB_KEY_Kana_Shift, Qt::Key_Kana_Shift>,
+ Xkb2Qt<XKB_KEY_Eisu_Shift, Qt::Key_Eisu_Shift>,
+ Xkb2Qt<XKB_KEY_Eisu_toggle, Qt::Key_Eisu_toggle>,
+ //Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Kanji_Bangou>,
+ //Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_Zen_Koho>,
+ //Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_Mae_Koho>,
+ Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Codeinput>,
+ Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_MultipleCandidate>,
+ Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_PreviousCandidate>,
+
+ // Korean keyboard support
+ Xkb2Qt<XKB_KEY_Hangul, Qt::Key_Hangul>,
+ Xkb2Qt<XKB_KEY_Hangul_Start, Qt::Key_Hangul_Start>,
+ Xkb2Qt<XKB_KEY_Hangul_End, Qt::Key_Hangul_End>,
+ Xkb2Qt<XKB_KEY_Hangul_Hanja, Qt::Key_Hangul_Hanja>,
+ Xkb2Qt<XKB_KEY_Hangul_Jamo, Qt::Key_Hangul_Jamo>,
+ Xkb2Qt<XKB_KEY_Hangul_Romaja, Qt::Key_Hangul_Romaja>,
+ //Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Hangul_Codeinput>,
+ Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Codeinput>,
+ Xkb2Qt<XKB_KEY_Hangul_Jeonja, Qt::Key_Hangul_Jeonja>,
+ Xkb2Qt<XKB_KEY_Hangul_Banja, Qt::Key_Hangul_Banja>,
+ Xkb2Qt<XKB_KEY_Hangul_PreHanja, Qt::Key_Hangul_PreHanja>,
+ Xkb2Qt<XKB_KEY_Hangul_PostHanja, Qt::Key_Hangul_PostHanja>,
+ //Xkb2Qt<XKB_KEY_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate>,
+ //Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate>,
+ //Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_SingleCandidate, Qt::Key_SingleCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate>,
+ Xkb2Qt<XKB_KEY_Hangul_Special, Qt::Key_Hangul_Special>,
+ //Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Hangul_switch>,
+ Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Mode_switch>,
+
+ // dead keys
+ Xkb2Qt<XKB_KEY_dead_grave, Qt::Key_Dead_Grave>,
+ Xkb2Qt<XKB_KEY_dead_acute, Qt::Key_Dead_Acute>,
+ Xkb2Qt<XKB_KEY_dead_circumflex, Qt::Key_Dead_Circumflex>,
+ Xkb2Qt<XKB_KEY_dead_tilde, Qt::Key_Dead_Tilde>,
+ Xkb2Qt<XKB_KEY_dead_macron, Qt::Key_Dead_Macron>,
+ Xkb2Qt<XKB_KEY_dead_breve, Qt::Key_Dead_Breve>,
+ Xkb2Qt<XKB_KEY_dead_abovedot, Qt::Key_Dead_Abovedot>,
+ Xkb2Qt<XKB_KEY_dead_diaeresis, Qt::Key_Dead_Diaeresis>,
+ Xkb2Qt<XKB_KEY_dead_abovering, Qt::Key_Dead_Abovering>,
+ Xkb2Qt<XKB_KEY_dead_doubleacute, Qt::Key_Dead_Doubleacute>,
+ Xkb2Qt<XKB_KEY_dead_caron, Qt::Key_Dead_Caron>,
+ Xkb2Qt<XKB_KEY_dead_cedilla, Qt::Key_Dead_Cedilla>,
+ Xkb2Qt<XKB_KEY_dead_ogonek, Qt::Key_Dead_Ogonek>,
+ Xkb2Qt<XKB_KEY_dead_iota, Qt::Key_Dead_Iota>,
+ Xkb2Qt<XKB_KEY_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound>,
+ Xkb2Qt<XKB_KEY_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound>,
+ Xkb2Qt<XKB_KEY_dead_belowdot, Qt::Key_Dead_Belowdot>,
+ Xkb2Qt<XKB_KEY_dead_hook, Qt::Key_Dead_Hook>,
+ Xkb2Qt<XKB_KEY_dead_horn, Qt::Key_Dead_Horn>,
+ Xkb2Qt<XKB_KEY_dead_stroke, Qt::Key_Dead_Stroke>,
+ Xkb2Qt<XKB_KEY_dead_abovecomma, Qt::Key_Dead_Abovecomma>,
+ Xkb2Qt<XKB_KEY_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma>,
+ Xkb2Qt<XKB_KEY_dead_doublegrave, Qt::Key_Dead_Doublegrave>,
+ Xkb2Qt<XKB_KEY_dead_belowring, Qt::Key_Dead_Belowring>,
+ Xkb2Qt<XKB_KEY_dead_belowmacron, Qt::Key_Dead_Belowmacron>,
+ Xkb2Qt<XKB_KEY_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex>,
+ Xkb2Qt<XKB_KEY_dead_belowtilde, Qt::Key_Dead_Belowtilde>,
+ Xkb2Qt<XKB_KEY_dead_belowbreve, Qt::Key_Dead_Belowbreve>,
+ Xkb2Qt<XKB_KEY_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis>,
+ Xkb2Qt<XKB_KEY_dead_invertedbreve, Qt::Key_Dead_Invertedbreve>,
+ Xkb2Qt<XKB_KEY_dead_belowcomma, Qt::Key_Dead_Belowcomma>,
+ Xkb2Qt<XKB_KEY_dead_currency, Qt::Key_Dead_Currency>,
+ Xkb2Qt<XKB_KEY_dead_a, Qt::Key_Dead_a>,
+ Xkb2Qt<XKB_KEY_dead_A, Qt::Key_Dead_A>,
+ Xkb2Qt<XKB_KEY_dead_e, Qt::Key_Dead_e>,
+ Xkb2Qt<XKB_KEY_dead_E, Qt::Key_Dead_E>,
+ Xkb2Qt<XKB_KEY_dead_i, Qt::Key_Dead_i>,
+ Xkb2Qt<XKB_KEY_dead_I, Qt::Key_Dead_I>,
+ Xkb2Qt<XKB_KEY_dead_o, Qt::Key_Dead_o>,
+ Xkb2Qt<XKB_KEY_dead_O, Qt::Key_Dead_O>,
+ Xkb2Qt<XKB_KEY_dead_u, Qt::Key_Dead_u>,
+ Xkb2Qt<XKB_KEY_dead_U, Qt::Key_Dead_U>,
+ Xkb2Qt<XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa>,
+ Xkb2Qt<XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa>,
+ Xkb2Qt<XKB_KEY_dead_greek, Qt::Key_Dead_Greek>,
+ Xkb2Qt<XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline>,
+ Xkb2Qt<XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline>,
+ Xkb2Qt<XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline>,
+ Xkb2Qt<XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay>,
+
+ // Special keys from X.org - This include multimedia keys,
+ // wireless/bluetooth/uwb keys, special launcher keys, etc.
+ Xkb2Qt<XKB_KEY_XF86Back, Qt::Key_Back>,
+ Xkb2Qt<XKB_KEY_XF86Forward, Qt::Key_Forward>,
+ Xkb2Qt<XKB_KEY_XF86Stop, Qt::Key_Stop>,
+ Xkb2Qt<XKB_KEY_XF86Refresh, Qt::Key_Refresh>,
+ Xkb2Qt<XKB_KEY_XF86Favorites, Qt::Key_Favorites>,
+ Xkb2Qt<XKB_KEY_XF86AudioMedia, Qt::Key_LaunchMedia>,
+ Xkb2Qt<XKB_KEY_XF86OpenURL, Qt::Key_OpenUrl>,
+ Xkb2Qt<XKB_KEY_XF86HomePage, Qt::Key_HomePage>,
+ Xkb2Qt<XKB_KEY_XF86Search, Qt::Key_Search>,
+ Xkb2Qt<XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown>,
+ Xkb2Qt<XKB_KEY_XF86AudioMute, Qt::Key_VolumeMute>,
+ Xkb2Qt<XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp>,
+ Xkb2Qt<XKB_KEY_XF86AudioPlay, Qt::Key_MediaPlay>,
+ Xkb2Qt<XKB_KEY_XF86AudioStop, Qt::Key_MediaStop>,
+ Xkb2Qt<XKB_KEY_XF86AudioPrev, Qt::Key_MediaPrevious>,
+ Xkb2Qt<XKB_KEY_XF86AudioNext, Qt::Key_MediaNext>,
+ Xkb2Qt<XKB_KEY_XF86AudioRecord, Qt::Key_MediaRecord>,
+ Xkb2Qt<XKB_KEY_XF86AudioPause, Qt::Key_MediaPause>,
+ Xkb2Qt<XKB_KEY_XF86Mail, Qt::Key_LaunchMail>,
+ Xkb2Qt<XKB_KEY_XF86MyComputer, Qt::Key_Launch0>, // ### Qt 6: remap properly
+ Xkb2Qt<XKB_KEY_XF86Calculator, Qt::Key_Launch1>,
+ Xkb2Qt<XKB_KEY_XF86Memo, Qt::Key_Memo>,
+ Xkb2Qt<XKB_KEY_XF86ToDoList, Qt::Key_ToDoList>,
+ Xkb2Qt<XKB_KEY_XF86Calendar, Qt::Key_Calendar>,
+ Xkb2Qt<XKB_KEY_XF86PowerDown, Qt::Key_PowerDown>,
+ Xkb2Qt<XKB_KEY_XF86ContrastAdjust, Qt::Key_ContrastAdjust>,
+ Xkb2Qt<XKB_KEY_XF86Standby, Qt::Key_Standby>,
+ Xkb2Qt<XKB_KEY_XF86MonBrightnessUp, Qt::Key_MonBrightnessUp>,
+ Xkb2Qt<XKB_KEY_XF86MonBrightnessDown, Qt::Key_MonBrightnessDown>,
+ Xkb2Qt<XKB_KEY_XF86KbdLightOnOff, Qt::Key_KeyboardLightOnOff>,
+ Xkb2Qt<XKB_KEY_XF86KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp>,
+ Xkb2Qt<XKB_KEY_XF86KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown>,
+ Xkb2Qt<XKB_KEY_XF86PowerOff, Qt::Key_PowerOff>,
+ Xkb2Qt<XKB_KEY_XF86WakeUp, Qt::Key_WakeUp>,
+ Xkb2Qt<XKB_KEY_XF86Eject, Qt::Key_Eject>,
+ Xkb2Qt<XKB_KEY_XF86ScreenSaver, Qt::Key_ScreenSaver>,
+ Xkb2Qt<XKB_KEY_XF86WWW, Qt::Key_WWW>,
+ Xkb2Qt<XKB_KEY_XF86Sleep, Qt::Key_Sleep>,
+ Xkb2Qt<XKB_KEY_XF86LightBulb, Qt::Key_LightBulb>,
+ Xkb2Qt<XKB_KEY_XF86Shop, Qt::Key_Shop>,
+ Xkb2Qt<XKB_KEY_XF86History, Qt::Key_History>,
+ Xkb2Qt<XKB_KEY_XF86AddFavorite, Qt::Key_AddFavorite>,
+ Xkb2Qt<XKB_KEY_XF86HotLinks, Qt::Key_HotLinks>,
+ Xkb2Qt<XKB_KEY_XF86BrightnessAdjust, Qt::Key_BrightnessAdjust>,
+ Xkb2Qt<XKB_KEY_XF86Finance, Qt::Key_Finance>,
+ Xkb2Qt<XKB_KEY_XF86Community, Qt::Key_Community>,
+ Xkb2Qt<XKB_KEY_XF86AudioRewind, Qt::Key_AudioRewind>,
+ Xkb2Qt<XKB_KEY_XF86BackForward, Qt::Key_BackForward>,
+ Xkb2Qt<XKB_KEY_XF86ApplicationLeft, Qt::Key_ApplicationLeft>,
+ Xkb2Qt<XKB_KEY_XF86ApplicationRight, Qt::Key_ApplicationRight>,
+ Xkb2Qt<XKB_KEY_XF86Book, Qt::Key_Book>,
+ Xkb2Qt<XKB_KEY_XF86CD, Qt::Key_CD>,
+ Xkb2Qt<XKB_KEY_XF86Calculater, Qt::Key_Calculator>,
+ Xkb2Qt<XKB_KEY_XF86Clear, Qt::Key_Clear>,
+ Xkb2Qt<XKB_KEY_XF86ClearGrab, Qt::Key_ClearGrab>,
+ Xkb2Qt<XKB_KEY_XF86Close, Qt::Key_Close>,
+ Xkb2Qt<XKB_KEY_XF86Copy, Qt::Key_Copy>,
+ Xkb2Qt<XKB_KEY_XF86Cut, Qt::Key_Cut>,
+ Xkb2Qt<XKB_KEY_XF86Display, Qt::Key_Display>,
+ Xkb2Qt<XKB_KEY_XF86DOS, Qt::Key_DOS>,
+ Xkb2Qt<XKB_KEY_XF86Documents, Qt::Key_Documents>,
+ Xkb2Qt<XKB_KEY_XF86Excel, Qt::Key_Excel>,
+ Xkb2Qt<XKB_KEY_XF86Explorer, Qt::Key_Explorer>,
+ Xkb2Qt<XKB_KEY_XF86Game, Qt::Key_Game>,
+ Xkb2Qt<XKB_KEY_XF86Go, Qt::Key_Go>,
+ Xkb2Qt<XKB_KEY_XF86iTouch, Qt::Key_iTouch>,
+ Xkb2Qt<XKB_KEY_XF86LogOff, Qt::Key_LogOff>,
+ Xkb2Qt<XKB_KEY_XF86Market, Qt::Key_Market>,
+ Xkb2Qt<XKB_KEY_XF86Meeting, Qt::Key_Meeting>,
+ Xkb2Qt<XKB_KEY_XF86MenuKB, Qt::Key_MenuKB>,
+ Xkb2Qt<XKB_KEY_XF86MenuPB, Qt::Key_MenuPB>,
+ Xkb2Qt<XKB_KEY_XF86MySites, Qt::Key_MySites>,
+ Xkb2Qt<XKB_KEY_XF86New, Qt::Key_New>,
+ Xkb2Qt<XKB_KEY_XF86News, Qt::Key_News>,
+ Xkb2Qt<XKB_KEY_XF86OfficeHome, Qt::Key_OfficeHome>,
+ Xkb2Qt<XKB_KEY_XF86Open, Qt::Key_Open>,
+ Xkb2Qt<XKB_KEY_XF86Option, Qt::Key_Option>,
+ Xkb2Qt<XKB_KEY_XF86Paste, Qt::Key_Paste>,
+ Xkb2Qt<XKB_KEY_XF86Phone, Qt::Key_Phone>,
+ Xkb2Qt<XKB_KEY_XF86Reply, Qt::Key_Reply>,
+ Xkb2Qt<XKB_KEY_XF86Reload, Qt::Key_Reload>,
+ Xkb2Qt<XKB_KEY_XF86RotateWindows, Qt::Key_RotateWindows>,
+ Xkb2Qt<XKB_KEY_XF86RotationPB, Qt::Key_RotationPB>,
+ Xkb2Qt<XKB_KEY_XF86RotationKB, Qt::Key_RotationKB>,
+ Xkb2Qt<XKB_KEY_XF86Save, Qt::Key_Save>,
+ Xkb2Qt<XKB_KEY_XF86Send, Qt::Key_Send>,
+ Xkb2Qt<XKB_KEY_XF86Spell, Qt::Key_Spell>,
+ Xkb2Qt<XKB_KEY_XF86SplitScreen, Qt::Key_SplitScreen>,
+ Xkb2Qt<XKB_KEY_XF86Support, Qt::Key_Support>,
+ Xkb2Qt<XKB_KEY_XF86TaskPane, Qt::Key_TaskPane>,
+ Xkb2Qt<XKB_KEY_XF86Terminal, Qt::Key_Terminal>,
+ Xkb2Qt<XKB_KEY_XF86Tools, Qt::Key_Tools>,
+ Xkb2Qt<XKB_KEY_XF86Travel, Qt::Key_Travel>,
+ Xkb2Qt<XKB_KEY_XF86Video, Qt::Key_Video>,
+ Xkb2Qt<XKB_KEY_XF86Word, Qt::Key_Word>,
+ Xkb2Qt<XKB_KEY_XF86Xfer, Qt::Key_Xfer>,
+ Xkb2Qt<XKB_KEY_XF86ZoomIn, Qt::Key_ZoomIn>,
+ Xkb2Qt<XKB_KEY_XF86ZoomOut, Qt::Key_ZoomOut>,
+ Xkb2Qt<XKB_KEY_XF86Away, Qt::Key_Away>,
+ Xkb2Qt<XKB_KEY_XF86Messenger, Qt::Key_Messenger>,
+ Xkb2Qt<XKB_KEY_XF86WebCam, Qt::Key_WebCam>,
+ Xkb2Qt<XKB_KEY_XF86MailForward, Qt::Key_MailForward>,
+ Xkb2Qt<XKB_KEY_XF86Pictures, Qt::Key_Pictures>,
+ Xkb2Qt<XKB_KEY_XF86Music, Qt::Key_Music>,
+ Xkb2Qt<XKB_KEY_XF86Battery, Qt::Key_Battery>,
+ Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
+ Xkb2Qt<XKB_KEY_XF86WLAN, Qt::Key_WLAN>,
+ Xkb2Qt<XKB_KEY_XF86UWB, Qt::Key_UWB>,
+ Xkb2Qt<XKB_KEY_XF86AudioForward, Qt::Key_AudioForward>,
+ Xkb2Qt<XKB_KEY_XF86AudioRepeat, Qt::Key_AudioRepeat>,
+ Xkb2Qt<XKB_KEY_XF86AudioRandomPlay, Qt::Key_AudioRandomPlay>,
+ Xkb2Qt<XKB_KEY_XF86Subtitle, Qt::Key_Subtitle>,
+ Xkb2Qt<XKB_KEY_XF86AudioCycleTrack, Qt::Key_AudioCycleTrack>,
+ Xkb2Qt<XKB_KEY_XF86Time, Qt::Key_Time>,
+ Xkb2Qt<XKB_KEY_XF86Select, Qt::Key_Select>,
+ Xkb2Qt<XKB_KEY_XF86View, Qt::Key_View>,
+ Xkb2Qt<XKB_KEY_XF86TopMenu, Qt::Key_TopMenu>,
+ Xkb2Qt<XKB_KEY_XF86Red, Qt::Key_Red>,
+ Xkb2Qt<XKB_KEY_XF86Green, Qt::Key_Green>,
+ Xkb2Qt<XKB_KEY_XF86Yellow, Qt::Key_Yellow>,
+ Xkb2Qt<XKB_KEY_XF86Blue, Qt::Key_Blue>,
+ Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
+ Xkb2Qt<XKB_KEY_XF86Suspend, Qt::Key_Suspend>,
+ Xkb2Qt<XKB_KEY_XF86Hibernate, Qt::Key_Hibernate>,
+ Xkb2Qt<XKB_KEY_XF86TouchpadToggle, Qt::Key_TouchpadToggle>,
+ Xkb2Qt<XKB_KEY_XF86TouchpadOn, Qt::Key_TouchpadOn>,
+ Xkb2Qt<XKB_KEY_XF86TouchpadOff, Qt::Key_TouchpadOff>,
+ Xkb2Qt<XKB_KEY_XF86AudioMicMute, Qt::Key_MicMute>,
+ Xkb2Qt<XKB_KEY_XF86Launch0, Qt::Key_Launch2>, // ### Qt 6: remap properly
+ Xkb2Qt<XKB_KEY_XF86Launch1, Qt::Key_Launch3>,
+ Xkb2Qt<XKB_KEY_XF86Launch2, Qt::Key_Launch4>,
+ Xkb2Qt<XKB_KEY_XF86Launch3, Qt::Key_Launch5>,
+ Xkb2Qt<XKB_KEY_XF86Launch4, Qt::Key_Launch6>,
+ Xkb2Qt<XKB_KEY_XF86Launch5, Qt::Key_Launch7>,
+ Xkb2Qt<XKB_KEY_XF86Launch6, Qt::Key_Launch8>,
+ Xkb2Qt<XKB_KEY_XF86Launch7, Qt::Key_Launch9>,
+ Xkb2Qt<XKB_KEY_XF86Launch8, Qt::Key_LaunchA>,
+ Xkb2Qt<XKB_KEY_XF86Launch9, Qt::Key_LaunchB>,
+ Xkb2Qt<XKB_KEY_XF86LaunchA, Qt::Key_LaunchC>,
+ Xkb2Qt<XKB_KEY_XF86LaunchB, Qt::Key_LaunchD>,
+ Xkb2Qt<XKB_KEY_XF86LaunchC, Qt::Key_LaunchE>,
+ Xkb2Qt<XKB_KEY_XF86LaunchD, Qt::Key_LaunchF>,
+ Xkb2Qt<XKB_KEY_XF86LaunchE, Qt::Key_LaunchG>,
+ Xkb2Qt<XKB_KEY_XF86LaunchF, Qt::Key_LaunchH>
+ >::Data{}
+);
+
+xkb_keysym_t QXkbCommon::qxkbcommon_xkb_keysym_to_upper(xkb_keysym_t ks)
+{
+ xkb_keysym_t lower, upper;
+
+ xkbcommon_XConvertCase(ks, &lower, &upper);
+
+ return upper;
+}
+
+QString QXkbCommon::lookupString(struct xkb_state *state, xkb_keycode_t code)
+{
+ QVarLengthArray<char, 32> chars(32);
+ const int size = xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
+ if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL
+ chars.resize(size + 1);
+ xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
+ }
+ return QString::fromUtf8(chars.constData(), size);
+}
+
+QString QXkbCommon::lookupStringNoKeysymTransformations(xkb_keysym_t keysym)
+{
+ QVarLengthArray<char, 32> chars(32);
+ const int size = xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
+ if (size == 0)
+ return QString(); // the keysym does not have a Unicode representation
+
+ if (Q_UNLIKELY(size > chars.size())) {
+ chars.resize(size);
+ xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
+ }
+ return QString::fromUtf8(chars.constData(), size - 1);
+}
+
+QVector<xkb_keysym_t> QXkbCommon::toKeysym(QKeyEvent *event)
+{
+ QVector<xkb_keysym_t> keysyms;
+ int qtKey = event->key();
+
+ if (qtKey >= Qt::Key_F1 && qtKey <= Qt::Key_F35) {
+ keysyms.append(XKB_KEY_F1 + (qtKey - Qt::Key_F1));
+ } else if (event->modifiers() & Qt::KeypadModifier) {
+ if (qtKey >= Qt::Key_0 && qtKey <= Qt::Key_9)
+ keysyms.append(XKB_KEY_KP_0 + (qtKey - Qt::Key_0));
+ } else if (isLatin(qtKey) && event->text().isUpper()) {
+ keysyms.append(qtKey);
+ }
+
+ if (!keysyms.isEmpty())
+ return keysyms;
+
+ // check if we have a direct mapping
+ auto it = std::find_if(KeyTbl.cbegin(), KeyTbl.cend(), [&qtKey](xkb2qt_t elem) {
+ return elem.qt == static_cast<uint>(qtKey);
+ });
+ if (it != KeyTbl.end()) {
+ keysyms.append(it->xkb);
+ return keysyms;
+ }
+
+ QVector<uint> ucs4;
+ if (event->text().isEmpty())
+ ucs4.append(qtKey);
+ else
+ ucs4 = event->text().toUcs4();
+
+ // From libxkbcommon keysym-utf.c:
+ // "We allow to represent any UCS character in the range U-00000000 to
+ // U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff."
+ for (uint utf32 : qAsConst(ucs4))
+ keysyms.append(utf32 | 0x01000000);
+
+ return keysyms;
+}
+
+int QXkbCommon::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers)
+{
+ return keysymToQtKey(keysym, modifiers, nullptr, 0);
+}
+
+int QXkbCommon::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
+ xkb_state *state, xkb_keycode_t code,
+ bool superAsMeta, bool hyperAsMeta)
+{
+ // Note 1: All standard key sequences on linux (as defined in platform theme)
+ // that use a latin character also contain a control modifier, which is why
+ // checking for Qt::ControlModifier is sufficient here. It is possible to
+ // override QPlatformTheme::keyBindings() and provide custom sequences for
+ // QKeySequence::StandardKey. Custom sequences probably should respect this
+ // convention (alternatively, we could test against other modifiers here).
+ // Note 2: The possibleKeys() shorcut mechanism is not affected by this value
+ // adjustment and does its own thing.
+ if (modifiers & Qt::ControlModifier) {
+ // With standard shortcuts we should prefer a latin character, this is
+ // for checks like "some qkeyevent == QKeySequence::Copy" to work even
+ // when using for example 'russian' keyboard layout.
+ if (!QXkbCommon::isLatin(keysym)) {
+ xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
+ if (latinKeysym != XKB_KEY_NoSymbol)
+ keysym = latinKeysym;
+ }
+ }
+
+ return keysymToQtKey_internal(keysym, modifiers, state, code, superAsMeta, hyperAsMeta);
+}
+
+static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
+ xkb_state *state, xkb_keycode_t code,
+ bool superAsMeta, bool hyperAsMeta)
+{
+ int qtKey = 0;
+
+ // lookup from direct mapping
+ if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
+ // function keys
+ qtKey = Qt::Key_F1 + (keysym - XKB_KEY_F1);
+ } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) {
+ // numeric keypad keys
+ qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
+ } else if (QXkbCommon::isLatin(keysym)) {
+ qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym);
+ } else {
+ // check if we have a direct mapping
+ xkb2qt_t searchKey{keysym, 0};
+ auto it = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
+ if (it != KeyTbl.end() && !(searchKey < *it))
+ qtKey = it->qt;
+ }
+
+ if (qtKey)
+ return qtKey;
+
+ // lookup from unicode
+ QString text;
+ if (!state || modifiers & Qt::ControlModifier) {
+ // Control modifier changes the text to ASCII control character, therefore we
+ // can't use this text to map keysym to a qt key. We can use the same keysym
+ // (it is not affectd by transformation) to obtain untransformed text. For details
+ // see "Appendix A. Default Symbol Transformations" in the XKB specification.
+ text = QXkbCommon::lookupStringNoKeysymTransformations(keysym);
+ } else {
+ text = QXkbCommon::lookupString(state, code);
+ }
+ if (!text.isEmpty()) {
+ if (text.unicode()->isDigit()) {
+ // Ensures that also non-latin digits are mapped to corresponding qt keys,
+ // e.g CTRL + ۲ (arabic two), is mapped to CTRL + Qt::Key_2.
+ qtKey = Qt::Key_0 + text.unicode()->digitValue();
+ } else {
+ qtKey = text.unicode()->toUpper().unicode();
+ }
+ }
+
+ // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
+ if (superAsMeta && (qtKey == Qt::Key_Super_L || qtKey == Qt::Key_Super_R))
+ qtKey = Qt::Key_Meta;
+ if (hyperAsMeta && (qtKey == Qt::Key_Hyper_L || qtKey == Qt::Key_Hyper_R))
+ qtKey = Qt::Key_Meta;
+
+ return qtKey;
+}
+
+Qt::KeyboardModifiers QXkbCommon::modifiers(struct xkb_state *state)
+{
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier;
+
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_CTRL, XKB_STATE_MODS_EFFECTIVE) > 0)
+ modifiers |= Qt::ControlModifier;
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_ALT, XKB_STATE_MODS_EFFECTIVE) > 0)
+ modifiers |= Qt::AltModifier;
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_SHIFT, XKB_STATE_MODS_EFFECTIVE) > 0)
+ modifiers |= Qt::ShiftModifier;
+ if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, XKB_STATE_MODS_EFFECTIVE) > 0)
+ modifiers |= Qt::MetaModifier;
+
+ return modifiers;
+}
+
+// Possible modifier states.
+static const Qt::KeyboardModifiers ModsTbl[] = {
+ Qt::NoModifier, // 0
+ Qt::ShiftModifier, // 1
+ Qt::ControlModifier, // 2
+ Qt::ControlModifier | Qt::ShiftModifier, // 3
+ Qt::AltModifier, // 4
+ Qt::AltModifier | Qt::ShiftModifier, // 5
+ Qt::AltModifier | Qt::ControlModifier, // 6
+ Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
+ Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts
+};
+
+QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event,
+ bool superAsMeta, bool hyperAsMeta)
+{
+ QList<int> result;
+ quint32 keycode = event->nativeScanCode();
+ Qt::KeyboardModifiers modifiers = event->modifiers();
+ xkb_keymap *keymap = xkb_state_get_keymap(state);
+ // turn off the modifier bits which doesn't participate in shortcuts
+ Qt::KeyboardModifiers notNeeded = Qt::KeypadModifier | Qt::GroupSwitchModifier;
+ modifiers &= ~notNeeded;
+ // create a fresh kb state and test against the relevant modifier combinations
+ ScopedXKBState scopedXkbQueryState(xkb_state_new(keymap));
+ xkb_state *queryState = scopedXkbQueryState.get();
+ if (!queryState) {
+ qCWarning(lcXkbcommon) << Q_FUNC_INFO << "failed to compile xkb keymap";
+ return result;
+ }
+ // get kb state from the master state and update the temporary state
+ xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(state, XKB_STATE_LAYOUT_LOCKED);
+ xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED);
+ xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED);
+ xkb_mod_mask_t depressedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_DEPRESSED);
+ xkb_state_update_mask(queryState, depressedMods, latchedMods, lockedMods, 0, 0, lockedLayout);
+ // handle shortcuts for level three and above
+ xkb_layout_index_t layoutIndex = xkb_state_key_get_layout(queryState, keycode);
+ xkb_level_index_t levelIndex = 0;
+ if (layoutIndex != XKB_LAYOUT_INVALID) {
+ levelIndex = xkb_state_key_get_level(queryState, keycode, layoutIndex);
+ if (levelIndex == XKB_LEVEL_INVALID)
+ levelIndex = 0;
+ }
+ if (levelIndex <= 1)
+ xkb_state_update_mask(queryState, 0, latchedMods, lockedMods, 0, 0, lockedLayout);
+
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(queryState, keycode);
+ if (sym == XKB_KEY_NoSymbol)
+ return result;
+
+ int baseQtKey = keysymToQtKey_internal(sym, modifiers, queryState, keycode, superAsMeta, hyperAsMeta);
+ if (baseQtKey)
+ result += (baseQtKey + modifiers);
+
+ xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(keymap, "Shift");
+ xkb_mod_index_t altMod = xkb_keymap_mod_get_index(keymap, "Alt");
+ xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(keymap, "Control");
+ xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(keymap, "Meta");
+
+ Q_ASSERT(shiftMod < 32);
+ Q_ASSERT(altMod < 32);
+ Q_ASSERT(controlMod < 32);
+
+ xkb_mod_mask_t depressed;
+ int qtKey = 0;
+ // obtain a list of possible shortcuts for the given key event
+ for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) {
+ Qt::KeyboardModifiers neededMods = ModsTbl[i];
+ if ((modifiers & neededMods) == neededMods) {
+ if (i == 8) {
+ if (isLatin(baseQtKey))
+ continue;
+ // add a latin key as a fall back key
+ sym = lookupLatinKeysym(state, keycode);
+ } else {
+ depressed = 0;
+ if (neededMods & Qt::AltModifier)
+ depressed |= (1 << altMod);
+ if (neededMods & Qt::ShiftModifier)
+ depressed |= (1 << shiftMod);
+ if (neededMods & Qt::ControlModifier)
+ depressed |= (1 << controlMod);
+ if (metaMod < 32 && neededMods & Qt::MetaModifier)
+ depressed |= (1 << metaMod);
+ xkb_state_update_mask(queryState, depressed, latchedMods, lockedMods, 0, 0, lockedLayout);
+ sym = xkb_state_key_get_one_sym(queryState, keycode);
+ }
+ if (sym == XKB_KEY_NoSymbol)
+ continue;
+
+ Qt::KeyboardModifiers mods = modifiers & ~neededMods;
+ qtKey = keysymToQtKey_internal(sym, mods, queryState, keycode, superAsMeta, hyperAsMeta);
+ if (!qtKey || qtKey == baseQtKey)
+ continue;
+
+ // catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +,
+ // but Ctrl++ is more specific than +, so we should skip the last one
+ bool ambiguous = false;
+ for (int shortcut : qAsConst(result)) {
+ if (int(shortcut & ~Qt::KeyboardModifierMask) == qtKey && (shortcut & mods) == mods) {
+ ambiguous = true;
+ break;
+ }
+ }
+ if (ambiguous)
+ continue;
+
+ result += (qtKey + mods);
+ }
+ }
+
+ return result;
+}
+
+void QXkbCommon::verifyHasLatinLayout(xkb_keymap *keymap)
+{
+ const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(keymap);
+ const xkb_keycode_t minKeycode = xkb_keymap_min_keycode(keymap);
+ const xkb_keycode_t maxKeycode = xkb_keymap_max_keycode(keymap);
+
+ const xkb_keysym_t *keysyms = nullptr;
+ int nrLatinKeys = 0;
+ for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
+ for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
+ xkb_keymap_key_get_syms_by_level(keymap, code, layout, 0, &keysyms);
+ if (keysyms && isLatin(keysyms[0]))
+ nrLatinKeys++;
+ if (nrLatinKeys > 10) // arbitrarily chosen threshold
+ return;
+ }
+ }
+ // This means that lookupLatinKeysym() will not find anything and latin
+ // key shortcuts might not work. This is a bug in the affected desktop
+ // environment. Usually can be solved via system settings by adding e.g. 'us'
+ // layout to the list of seleced layouts, or by using command line, "setxkbmap
+ // -layout rus,en". The position of latin key based layout in the list of the
+ // selected layouts is irrelevant. Properly functioning desktop environments
+ // handle this behind the scenes, even if no latin key based layout has been
+ // explicitly listed in the selected layouts.
+ qCDebug(lcXkbcommon, "no keyboard layouts with latin keys present");
+}
+
+xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode)
+{
+ xkb_layout_index_t layout;
+ xkb_keysym_t sym = XKB_KEY_NoSymbol;
+ xkb_keymap *keymap = xkb_state_get_keymap(state);
+ const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(keymap, keycode);
+ const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(state, keycode);
+ // Look at user layouts in the order in which they are defined in system
+ // settings to find a latin keysym.
+ for (layout = 0; layout < layoutCount; ++layout) {
+ if (layout == currentLayout)
+ continue;
+ const xkb_keysym_t *syms = nullptr;
+ xkb_level_index_t level = xkb_state_key_get_level(state, keycode, layout);
+ if (xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms) != 1)
+ continue;
+ if (isLatin(syms[0])) {
+ sym = syms[0];
+ break;
+ }
+ }
+
+ if (sym == XKB_KEY_NoSymbol)
+ return sym;
+
+ xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED);
+ xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LOCKED);
+
+ // Check for uniqueness, consider the following setup:
+ // setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active).
+ // In this setup, the user would expect to trigger a ctrl+q shortcut by pressing ctrl+<physical x key>,
+ // because "US dvorak" is higher up in the layout settings list. This check verifies that an obtained
+ // 'sym' can not be acquired by any other layout higher up in the user's layout list. If it can be acquired
+ // then the obtained key is not unique. This prevents ctrl+<physical q key> from generating a ctrl+q
+ // shortcut in the above described setup. We don't want ctrl+<physical x key> and ctrl+<physical q key> to
+ // generate the same shortcut event in this case.
+ const xkb_keycode_t minKeycode = xkb_keymap_min_keycode(keymap);
+ const xkb_keycode_t maxKeycode = xkb_keymap_max_keycode(keymap);
+ ScopedXKBState queryState(xkb_state_new(keymap));
+ for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) {
+ xkb_state_update_mask(queryState.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout);
+ for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
+ xkb_keysym_t prevSym = xkb_state_key_get_one_sym(queryState.get(), code);
+ if (prevSym == sym) {
+ sym = XKB_KEY_NoSymbol;
+ break;
+ }
+ }
+ }
+
+ return sym;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbxkbcommon.h b/src/platformsupport/input/xkbcommon/qxkbcommon_3rdparty.cpp
index 422c0c0f12..08f43b3b72 100644
--- a/src/plugins/platforms/xcb/qxcbxkbcommon.h
+++ b/src/platformsupport/input/xkbcommon/qxkbcommon_3rdparty.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
@@ -37,10 +37,7 @@
**
****************************************************************************/
-/* XConvertCase was copied from src/3rdparty/xkbcommon/src/keysym.c,
- which contains the following license information:
-
- Copyright 1985, 1987, 1990, 1998 The Open Group
+/* Copyright 1985, 1987, 1990, 1998 The Open Group
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -89,6 +86,7 @@
*/
/*
+ XConvertCase was copied from src/3rdparty/xkbcommon/src/keysym.c
The following code modifications were applied:
XConvertCase() was renamed to xkbcommon_XConvertCase(), to not confuse it
@@ -99,10 +97,9 @@
results instead of using the less complete version from keysym.c
*/
-#include <xkbcommon/xkbcommon.h>
-#include <QtCore/QChar>
+#include "qxkbcommon_p.h"
-QT_BEGIN_NAMESPACE
+#include <QtCore/QChar>
static void qt_UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *upper)
{
@@ -110,7 +107,7 @@ static void qt_UCSConvertCase(uint32_t code, xkb_keysym_t *lower, xkb_keysym_t *
*upper = QChar::toUpper(code);
}
-void xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper)
+void QXkbCommon::xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper)
{
/* Latin 1 keysym */
if (sym < 0x100) {
@@ -220,14 +217,3 @@ void xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t
break;
}
}
-
-xkb_keysym_t xkbcommon_xkb_keysym_to_upper(xkb_keysym_t ks)
-{
- xkb_keysym_t lower, upper;
-
- xkbcommon_XConvertCase(ks, &lower, &upper);
-
- return upper;
-}
-
-QT_END_NAMESPACE
diff --git a/src/platformsupport/input/xkbcommon/qxkbcommon_p.h b/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
new file mode 100644
index 0000000000..475c51ad91
--- /dev/null
+++ b/src/platformsupport/input/xkbcommon/qxkbcommon_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXKBCOMMON_P_H
+#define QXKBCOMMON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QString>
+#include <QtCore/QVector>
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QList>
+
+#include <xkbcommon/xkbcommon.h>
+
+#include <memory>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(lcXkbcommon)
+
+class QKeyEvent;
+
+class QXkbCommon
+{
+public:
+ static QString lookupString(struct xkb_state *state, xkb_keycode_t code);
+ static QString lookupStringNoKeysymTransformations(xkb_keysym_t keysym);
+
+ static QVector<xkb_keysym_t> toKeysym(QKeyEvent *event);
+
+ static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers);
+ static int keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
+ xkb_state *state, xkb_keycode_t code,
+ bool superAsMeta = false, bool hyperAsMeta = false);
+
+ // xkbcommon_* API is part of libxkbcommon internals, with modifications as
+ // desribed in the header of the implementation file.
+ static void xkbcommon_XConvertCase(xkb_keysym_t sym, xkb_keysym_t *lower, xkb_keysym_t *upper);
+ static xkb_keysym_t qxkbcommon_xkb_keysym_to_upper(xkb_keysym_t ks);
+
+ static Qt::KeyboardModifiers modifiers(struct xkb_state *state);
+
+ static QList<int> possibleKeys(xkb_state *state, const QKeyEvent *event,
+ bool superAsMeta = false, bool hyperAsMeta = false);
+
+ static void verifyHasLatinLayout(xkb_keymap *keymap);
+ static xkb_keysym_t lookupLatinKeysym(xkb_state *state, xkb_keycode_t keycode);
+
+ static bool isLatin(xkb_keysym_t sym) {
+ return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z'));
+ }
+ static bool isKeypad(xkb_keysym_t sym) {
+ return sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9;
+ }
+
+ struct XKBStateDeleter {
+ void operator()(struct xkb_state *state) const { return xkb_state_unref(state); }
+ };
+ struct XKBKeymapDeleter {
+ void operator()(struct xkb_keymap *keymap) const { return xkb_keymap_unref(keymap); }
+ };
+ struct XKBContextDeleter {
+ void operator()(struct xkb_context *context) const { return xkb_context_unref(context); }
+ };
+ using ScopedXKBState = std::unique_ptr<struct xkb_state, XKBStateDeleter>;
+ using ScopedXKBKeymap = std::unique_ptr<struct xkb_keymap, XKBKeymapDeleter>;
+ using ScopedXKBContext = std::unique_ptr<struct xkb_context, XKBContextDeleter>;
+};
+
+QT_END_NAMESPACE
+
+#endif // QXKBCOMMON_P_H
diff --git a/src/platformsupport/input/xkbcommon/xkbcommon.pro b/src/platformsupport/input/xkbcommon/xkbcommon.pro
new file mode 100644
index 0000000000..2f5d132b5c
--- /dev/null
+++ b/src/platformsupport/input/xkbcommon/xkbcommon.pro
@@ -0,0 +1,23 @@
+TARGET = QtXkbCommonSupport
+MODULE = xkbcommon_support
+
+QT = core-private gui-private
+CONFIG += static internal_module
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+PRECOMPILED_HEADER = ../../../corelib/global/qt_pch.h
+
+QMAKE_USE_PRIVATE += xkbcommon
+
+HEADERS += \
+ qxkbcommon_p.h
+
+SOURCES += \
+ qxkbcommon.cpp \
+ qxkbcommon_3rdparty.cpp
+
+# qxkbcommon.cpp::KeyTbl has more than 256 levels of expansion and older
+# Clang uses that as a limit (it's 1024 in current versions).
+clang:!intel_icc: QMAKE_CXXFLAGS += -ftemplate-depth=1024
+
+load(qt_module)
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index c5dc7b21ad..6eb31d67bd 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -39,7 +39,6 @@
#include "qxcbkeyboard.h"
#include "qxcbwindow.h"
#include "qxcbscreen.h"
-#include "qxcbxkbcommon.h"
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatforminputcontext.h>
@@ -49,404 +48,20 @@
#include <QtCore/QMetaEnum>
#include <private/qguiapplication_p.h>
-#include <private/qmakearray_p.h>
-#include <xkbcommon/xkbcommon-keysyms.h>
+#if QT_CONFIG(xkb)
+#include <xkbcommon/xkbcommon-x11.h>
+#endif
#if QT_CONFIG(xcb_xinput)
#include <xcb/xinput.h>
#endif
-QT_BEGIN_NAMESPACE
-
-typedef struct xkb2qt
-{
- unsigned int xkb;
- unsigned int qt;
-
- constexpr bool operator <=(const xkb2qt &that) const noexcept
- {
- return xkb <= that.xkb;
- }
-
- constexpr bool operator <(const xkb2qt &that) const noexcept
- {
- return xkb < that.xkb;
- }
-} xkb2qt_t;
-template<std::size_t Xkb, std::size_t Qt>
-struct Xkb2Qt
-{
- using Type = xkb2qt_t;
- static constexpr Type data() noexcept { return Type{Xkb, Qt}; }
-};
-
-static constexpr const auto KeyTbl = qMakeArray(
- QSortedData<
- // misc keys
-
- Xkb2Qt<XKB_KEY_Escape, Qt::Key_Escape>,
- Xkb2Qt<XKB_KEY_Tab, Qt::Key_Tab>,
- Xkb2Qt<XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab>,
- Xkb2Qt<XKB_KEY_BackSpace, Qt::Key_Backspace>,
- Xkb2Qt<XKB_KEY_Return, Qt::Key_Return>,
- Xkb2Qt<XKB_KEY_Insert, Qt::Key_Insert>,
- Xkb2Qt<XKB_KEY_Delete, Qt::Key_Delete>,
- Xkb2Qt<XKB_KEY_Clear, Qt::Key_Delete>,
- Xkb2Qt<XKB_KEY_Pause, Qt::Key_Pause>,
- Xkb2Qt<XKB_KEY_Print, Qt::Key_Print>,
- Xkb2Qt<0x1005FF60, Qt::Key_SysReq>, // hardcoded Sun SysReq
- Xkb2Qt<0x1007ff00, Qt::Key_SysReq>, // hardcoded X386 SysReq
-
- // cursor movement
-
- Xkb2Qt<XKB_KEY_Home, Qt::Key_Home>,
- Xkb2Qt<XKB_KEY_End, Qt::Key_End>,
- Xkb2Qt<XKB_KEY_Left, Qt::Key_Left>,
- Xkb2Qt<XKB_KEY_Up, Qt::Key_Up>,
- Xkb2Qt<XKB_KEY_Right, Qt::Key_Right>,
- Xkb2Qt<XKB_KEY_Down, Qt::Key_Down>,
- Xkb2Qt<XKB_KEY_Prior, Qt::Key_PageUp>,
- Xkb2Qt<XKB_KEY_Next, Qt::Key_PageDown>,
-
- // modifiers
-
- Xkb2Qt<XKB_KEY_Shift_L, Qt::Key_Shift>,
- Xkb2Qt<XKB_KEY_Shift_R, Qt::Key_Shift>,
- Xkb2Qt<XKB_KEY_Shift_Lock, Qt::Key_Shift>,
- Xkb2Qt<XKB_KEY_Control_L, Qt::Key_Control>,
- Xkb2Qt<XKB_KEY_Control_R, Qt::Key_Control>,
- Xkb2Qt<XKB_KEY_Meta_L, Qt::Key_Meta>,
- Xkb2Qt<XKB_KEY_Meta_R, Qt::Key_Meta>,
- Xkb2Qt<XKB_KEY_Alt_L, Qt::Key_Alt>,
- Xkb2Qt<XKB_KEY_Alt_R, Qt::Key_Alt>,
- Xkb2Qt<XKB_KEY_Caps_Lock, Qt::Key_CapsLock>,
- Xkb2Qt<XKB_KEY_Num_Lock, Qt::Key_NumLock>,
- Xkb2Qt<XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock>,
- Xkb2Qt<XKB_KEY_Super_L, Qt::Key_Super_L>,
- Xkb2Qt<XKB_KEY_Super_R, Qt::Key_Super_R>,
- Xkb2Qt<XKB_KEY_Menu, Qt::Key_Menu>,
- Xkb2Qt<XKB_KEY_Hyper_L, Qt::Key_Hyper_L>,
- Xkb2Qt<XKB_KEY_Hyper_R, Qt::Key_Hyper_R>,
- Xkb2Qt<XKB_KEY_Help, Qt::Key_Help>,
- Xkb2Qt<0x1000FF74, Qt::Key_Backtab>, // hardcoded HP backtab
- Xkb2Qt<0x1005FF10, Qt::Key_F11>, // hardcoded Sun F36 (labeled F11)
- Xkb2Qt<0x1005FF11, Qt::Key_F12>, // hardcoded Sun F37 (labeled F12)
-
- // numeric and function keypad keys
-
- Xkb2Qt<XKB_KEY_KP_Space, Qt::Key_Space>,
- Xkb2Qt<XKB_KEY_KP_Tab, Qt::Key_Tab>,
- Xkb2Qt<XKB_KEY_KP_Enter, Qt::Key_Enter>,
- //Xkb2Qt<XKB_KEY_KP_F1, Qt::Key_F1>,
- //Xkb2Qt<XKB_KEY_KP_F2, Qt::Key_F2>,
- //Xkb2Qt<XKB_KEY_KP_F3, Qt::Key_F3>,
- //Xkb2Qt<XKB_KEY_KP_F4, Qt::Key_F4>,
- Xkb2Qt<XKB_KEY_KP_Home, Qt::Key_Home>,
- Xkb2Qt<XKB_KEY_KP_Left, Qt::Key_Left>,
- Xkb2Qt<XKB_KEY_KP_Up, Qt::Key_Up>,
- Xkb2Qt<XKB_KEY_KP_Right, Qt::Key_Right>,
- Xkb2Qt<XKB_KEY_KP_Down, Qt::Key_Down>,
- Xkb2Qt<XKB_KEY_KP_Prior, Qt::Key_PageUp>,
- Xkb2Qt<XKB_KEY_KP_Next, Qt::Key_PageDown>,
- Xkb2Qt<XKB_KEY_KP_End, Qt::Key_End>,
- Xkb2Qt<XKB_KEY_KP_Begin, Qt::Key_Clear>,
- Xkb2Qt<XKB_KEY_KP_Insert, Qt::Key_Insert>,
- Xkb2Qt<XKB_KEY_KP_Delete, Qt::Key_Delete>,
- Xkb2Qt<XKB_KEY_KP_Equal, Qt::Key_Equal>,
- Xkb2Qt<XKB_KEY_KP_Multiply, Qt::Key_Asterisk>,
- Xkb2Qt<XKB_KEY_KP_Add, Qt::Key_Plus>,
- Xkb2Qt<XKB_KEY_KP_Separator, Qt::Key_Comma>,
- Xkb2Qt<XKB_KEY_KP_Subtract, Qt::Key_Minus>,
- Xkb2Qt<XKB_KEY_KP_Decimal, Qt::Key_Period>,
- Xkb2Qt<XKB_KEY_KP_Divide, Qt::Key_Slash>,
-
- // special non-XF86 function keys
-
- Xkb2Qt<XKB_KEY_Undo, Qt::Key_Undo>,
- Xkb2Qt<XKB_KEY_Redo, Qt::Key_Redo>,
- Xkb2Qt<XKB_KEY_Find, Qt::Key_Find>,
- Xkb2Qt<XKB_KEY_Cancel, Qt::Key_Cancel>,
-
- // International input method support keys
-
- // International & multi-key character composition
- Xkb2Qt<XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr>,
- Xkb2Qt<XKB_KEY_Multi_key, Qt::Key_Multi_key>,
- Xkb2Qt<XKB_KEY_Codeinput, Qt::Key_Codeinput>,
- Xkb2Qt<XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate>,
- Xkb2Qt<XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate>,
- Xkb2Qt<XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate>,
-
- // Misc Functions
- Xkb2Qt<XKB_KEY_Mode_switch, Qt::Key_Mode_switch>,
- Xkb2Qt<XKB_KEY_script_switch, Qt::Key_Mode_switch>,
-
- // Japanese keyboard support
- Xkb2Qt<XKB_KEY_Kanji, Qt::Key_Kanji>,
- Xkb2Qt<XKB_KEY_Muhenkan, Qt::Key_Muhenkan>,
- //Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan_Mode>,
- Xkb2Qt<XKB_KEY_Henkan_Mode, Qt::Key_Henkan>,
- Xkb2Qt<XKB_KEY_Henkan, Qt::Key_Henkan>,
- Xkb2Qt<XKB_KEY_Romaji, Qt::Key_Romaji>,
- Xkb2Qt<XKB_KEY_Hiragana, Qt::Key_Hiragana>,
- Xkb2Qt<XKB_KEY_Katakana, Qt::Key_Katakana>,
- Xkb2Qt<XKB_KEY_Hiragana_Katakana, Qt::Key_Hiragana_Katakana>,
- Xkb2Qt<XKB_KEY_Zenkaku, Qt::Key_Zenkaku>,
- Xkb2Qt<XKB_KEY_Hankaku, Qt::Key_Hankaku>,
- Xkb2Qt<XKB_KEY_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku>,
- Xkb2Qt<XKB_KEY_Touroku, Qt::Key_Touroku>,
- Xkb2Qt<XKB_KEY_Massyo, Qt::Key_Massyo>,
- Xkb2Qt<XKB_KEY_Kana_Lock, Qt::Key_Kana_Lock>,
- Xkb2Qt<XKB_KEY_Kana_Shift, Qt::Key_Kana_Shift>,
- Xkb2Qt<XKB_KEY_Eisu_Shift, Qt::Key_Eisu_Shift>,
- Xkb2Qt<XKB_KEY_Eisu_toggle, Qt::Key_Eisu_toggle>,
- //Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Kanji_Bangou>,
- //Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_Zen_Koho>,
- //Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_Mae_Koho>,
- Xkb2Qt<XKB_KEY_Kanji_Bangou, Qt::Key_Codeinput>,
- Xkb2Qt<XKB_KEY_Zen_Koho, Qt::Key_MultipleCandidate>,
- Xkb2Qt<XKB_KEY_Mae_Koho, Qt::Key_PreviousCandidate>,
-
- // Korean keyboard support
- Xkb2Qt<XKB_KEY_Hangul, Qt::Key_Hangul>,
- Xkb2Qt<XKB_KEY_Hangul_Start, Qt::Key_Hangul_Start>,
- Xkb2Qt<XKB_KEY_Hangul_End, Qt::Key_Hangul_End>,
- Xkb2Qt<XKB_KEY_Hangul_Hanja, Qt::Key_Hangul_Hanja>,
- Xkb2Qt<XKB_KEY_Hangul_Jamo, Qt::Key_Hangul_Jamo>,
- Xkb2Qt<XKB_KEY_Hangul_Romaja, Qt::Key_Hangul_Romaja>,
- //Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Hangul_Codeinput>,
- Xkb2Qt<XKB_KEY_Hangul_Codeinput, Qt::Key_Codeinput>,
- Xkb2Qt<XKB_KEY_Hangul_Jeonja, Qt::Key_Hangul_Jeonja>,
- Xkb2Qt<XKB_KEY_Hangul_Banja, Qt::Key_Hangul_Banja>,
- Xkb2Qt<XKB_KEY_Hangul_PreHanja, Qt::Key_Hangul_PreHanja>,
- Xkb2Qt<XKB_KEY_Hangul_PostHanja, Qt::Key_Hangul_PostHanja>,
- //Xkb2Qt<XKB_KEY_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate>,
- //Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate>,
- //Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate>,
- Xkb2Qt<XKB_KEY_Hangul_SingleCandidate, Qt::Key_SingleCandidate>,
- Xkb2Qt<XKB_KEY_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate>,
- Xkb2Qt<XKB_KEY_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate>,
- Xkb2Qt<XKB_KEY_Hangul_Special, Qt::Key_Hangul_Special>,
- //Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Hangul_switch>,
- Xkb2Qt<XKB_KEY_Hangul_switch, Qt::Key_Mode_switch>,
-
- // dead keys
- Xkb2Qt<XKB_KEY_dead_grave, Qt::Key_Dead_Grave>,
- Xkb2Qt<XKB_KEY_dead_acute, Qt::Key_Dead_Acute>,
- Xkb2Qt<XKB_KEY_dead_circumflex, Qt::Key_Dead_Circumflex>,
- Xkb2Qt<XKB_KEY_dead_tilde, Qt::Key_Dead_Tilde>,
- Xkb2Qt<XKB_KEY_dead_macron, Qt::Key_Dead_Macron>,
- Xkb2Qt<XKB_KEY_dead_breve, Qt::Key_Dead_Breve>,
- Xkb2Qt<XKB_KEY_dead_abovedot, Qt::Key_Dead_Abovedot>,
- Xkb2Qt<XKB_KEY_dead_diaeresis, Qt::Key_Dead_Diaeresis>,
- Xkb2Qt<XKB_KEY_dead_abovering, Qt::Key_Dead_Abovering>,
- Xkb2Qt<XKB_KEY_dead_doubleacute, Qt::Key_Dead_Doubleacute>,
- Xkb2Qt<XKB_KEY_dead_caron, Qt::Key_Dead_Caron>,
- Xkb2Qt<XKB_KEY_dead_cedilla, Qt::Key_Dead_Cedilla>,
- Xkb2Qt<XKB_KEY_dead_ogonek, Qt::Key_Dead_Ogonek>,
- Xkb2Qt<XKB_KEY_dead_iota, Qt::Key_Dead_Iota>,
- Xkb2Qt<XKB_KEY_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound>,
- Xkb2Qt<XKB_KEY_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound>,
- Xkb2Qt<XKB_KEY_dead_belowdot, Qt::Key_Dead_Belowdot>,
- Xkb2Qt<XKB_KEY_dead_hook, Qt::Key_Dead_Hook>,
- Xkb2Qt<XKB_KEY_dead_horn, Qt::Key_Dead_Horn>,
- Xkb2Qt<XKB_KEY_dead_stroke, Qt::Key_Dead_Stroke>,
- Xkb2Qt<XKB_KEY_dead_abovecomma, Qt::Key_Dead_Abovecomma>,
- Xkb2Qt<XKB_KEY_dead_abovereversedcomma, Qt::Key_Dead_Abovereversedcomma>,
- Xkb2Qt<XKB_KEY_dead_doublegrave, Qt::Key_Dead_Doublegrave>,
- Xkb2Qt<XKB_KEY_dead_belowring, Qt::Key_Dead_Belowring>,
- Xkb2Qt<XKB_KEY_dead_belowmacron, Qt::Key_Dead_Belowmacron>,
- Xkb2Qt<XKB_KEY_dead_belowcircumflex, Qt::Key_Dead_Belowcircumflex>,
- Xkb2Qt<XKB_KEY_dead_belowtilde, Qt::Key_Dead_Belowtilde>,
- Xkb2Qt<XKB_KEY_dead_belowbreve, Qt::Key_Dead_Belowbreve>,
- Xkb2Qt<XKB_KEY_dead_belowdiaeresis, Qt::Key_Dead_Belowdiaeresis>,
- Xkb2Qt<XKB_KEY_dead_invertedbreve, Qt::Key_Dead_Invertedbreve>,
- Xkb2Qt<XKB_KEY_dead_belowcomma, Qt::Key_Dead_Belowcomma>,
- Xkb2Qt<XKB_KEY_dead_currency, Qt::Key_Dead_Currency>,
- Xkb2Qt<XKB_KEY_dead_a, Qt::Key_Dead_a>,
- Xkb2Qt<XKB_KEY_dead_A, Qt::Key_Dead_A>,
- Xkb2Qt<XKB_KEY_dead_e, Qt::Key_Dead_e>,
- Xkb2Qt<XKB_KEY_dead_E, Qt::Key_Dead_E>,
- Xkb2Qt<XKB_KEY_dead_i, Qt::Key_Dead_i>,
- Xkb2Qt<XKB_KEY_dead_I, Qt::Key_Dead_I>,
- Xkb2Qt<XKB_KEY_dead_o, Qt::Key_Dead_o>,
- Xkb2Qt<XKB_KEY_dead_O, Qt::Key_Dead_O>,
- Xkb2Qt<XKB_KEY_dead_u, Qt::Key_Dead_u>,
- Xkb2Qt<XKB_KEY_dead_U, Qt::Key_Dead_U>,
- Xkb2Qt<XKB_KEY_dead_small_schwa, Qt::Key_Dead_Small_Schwa>,
- Xkb2Qt<XKB_KEY_dead_capital_schwa, Qt::Key_Dead_Capital_Schwa>,
- Xkb2Qt<XKB_KEY_dead_greek, Qt::Key_Dead_Greek>,
- Xkb2Qt<XKB_KEY_dead_lowline, Qt::Key_Dead_Lowline>,
- Xkb2Qt<XKB_KEY_dead_aboveverticalline, Qt::Key_Dead_Aboveverticalline>,
- Xkb2Qt<XKB_KEY_dead_belowverticalline, Qt::Key_Dead_Belowverticalline>,
- Xkb2Qt<XKB_KEY_dead_longsolidusoverlay, Qt::Key_Dead_Longsolidusoverlay>,
-
- // Special keys from X.org - This include multimedia keys,
- // wireless/bluetooth/uwb keys, special launcher keys, etc.
- Xkb2Qt<XKB_KEY_XF86Back, Qt::Key_Back>,
- Xkb2Qt<XKB_KEY_XF86Forward, Qt::Key_Forward>,
- Xkb2Qt<XKB_KEY_XF86Stop, Qt::Key_Stop>,
- Xkb2Qt<XKB_KEY_XF86Refresh, Qt::Key_Refresh>,
- Xkb2Qt<XKB_KEY_XF86Favorites, Qt::Key_Favorites>,
- Xkb2Qt<XKB_KEY_XF86AudioMedia, Qt::Key_LaunchMedia>,
- Xkb2Qt<XKB_KEY_XF86OpenURL, Qt::Key_OpenUrl>,
- Xkb2Qt<XKB_KEY_XF86HomePage, Qt::Key_HomePage>,
- Xkb2Qt<XKB_KEY_XF86Search, Qt::Key_Search>,
- Xkb2Qt<XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown>,
- Xkb2Qt<XKB_KEY_XF86AudioMute, Qt::Key_VolumeMute>,
- Xkb2Qt<XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp>,
- Xkb2Qt<XKB_KEY_XF86AudioPlay, Qt::Key_MediaPlay>,
- Xkb2Qt<XKB_KEY_XF86AudioStop, Qt::Key_MediaStop>,
- Xkb2Qt<XKB_KEY_XF86AudioPrev, Qt::Key_MediaPrevious>,
- Xkb2Qt<XKB_KEY_XF86AudioNext, Qt::Key_MediaNext>,
- Xkb2Qt<XKB_KEY_XF86AudioRecord, Qt::Key_MediaRecord>,
- Xkb2Qt<XKB_KEY_XF86AudioPause, Qt::Key_MediaPause>,
- Xkb2Qt<XKB_KEY_XF86Mail, Qt::Key_LaunchMail>,
- Xkb2Qt<XKB_KEY_XF86MyComputer, Qt::Key_Launch0>, // ### Qt 6: remap properly
- Xkb2Qt<XKB_KEY_XF86Calculator, Qt::Key_Launch1>,
- Xkb2Qt<XKB_KEY_XF86Memo, Qt::Key_Memo>,
- Xkb2Qt<XKB_KEY_XF86ToDoList, Qt::Key_ToDoList>,
- Xkb2Qt<XKB_KEY_XF86Calendar, Qt::Key_Calendar>,
- Xkb2Qt<XKB_KEY_XF86PowerDown, Qt::Key_PowerDown>,
- Xkb2Qt<XKB_KEY_XF86ContrastAdjust, Qt::Key_ContrastAdjust>,
- Xkb2Qt<XKB_KEY_XF86Standby, Qt::Key_Standby>,
- Xkb2Qt<XKB_KEY_XF86MonBrightnessUp, Qt::Key_MonBrightnessUp>,
- Xkb2Qt<XKB_KEY_XF86MonBrightnessDown, Qt::Key_MonBrightnessDown>,
- Xkb2Qt<XKB_KEY_XF86KbdLightOnOff, Qt::Key_KeyboardLightOnOff>,
- Xkb2Qt<XKB_KEY_XF86KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp>,
- Xkb2Qt<XKB_KEY_XF86KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown>,
- Xkb2Qt<XKB_KEY_XF86PowerOff, Qt::Key_PowerOff>,
- Xkb2Qt<XKB_KEY_XF86WakeUp, Qt::Key_WakeUp>,
- Xkb2Qt<XKB_KEY_XF86Eject, Qt::Key_Eject>,
- Xkb2Qt<XKB_KEY_XF86ScreenSaver, Qt::Key_ScreenSaver>,
- Xkb2Qt<XKB_KEY_XF86WWW, Qt::Key_WWW>,
- Xkb2Qt<XKB_KEY_XF86Sleep, Qt::Key_Sleep>,
- Xkb2Qt<XKB_KEY_XF86LightBulb, Qt::Key_LightBulb>,
- Xkb2Qt<XKB_KEY_XF86Shop, Qt::Key_Shop>,
- Xkb2Qt<XKB_KEY_XF86History, Qt::Key_History>,
- Xkb2Qt<XKB_KEY_XF86AddFavorite, Qt::Key_AddFavorite>,
- Xkb2Qt<XKB_KEY_XF86HotLinks, Qt::Key_HotLinks>,
- Xkb2Qt<XKB_KEY_XF86BrightnessAdjust, Qt::Key_BrightnessAdjust>,
- Xkb2Qt<XKB_KEY_XF86Finance, Qt::Key_Finance>,
- Xkb2Qt<XKB_KEY_XF86Community, Qt::Key_Community>,
- Xkb2Qt<XKB_KEY_XF86AudioRewind, Qt::Key_AudioRewind>,
- Xkb2Qt<XKB_KEY_XF86BackForward, Qt::Key_BackForward>,
- Xkb2Qt<XKB_KEY_XF86ApplicationLeft, Qt::Key_ApplicationLeft>,
- Xkb2Qt<XKB_KEY_XF86ApplicationRight, Qt::Key_ApplicationRight>,
- Xkb2Qt<XKB_KEY_XF86Book, Qt::Key_Book>,
- Xkb2Qt<XKB_KEY_XF86CD, Qt::Key_CD>,
- Xkb2Qt<XKB_KEY_XF86Calculater, Qt::Key_Calculator>,
- Xkb2Qt<XKB_KEY_XF86Clear, Qt::Key_Clear>,
- Xkb2Qt<XKB_KEY_XF86ClearGrab, Qt::Key_ClearGrab>,
- Xkb2Qt<XKB_KEY_XF86Close, Qt::Key_Close>,
- Xkb2Qt<XKB_KEY_XF86Copy, Qt::Key_Copy>,
- Xkb2Qt<XKB_KEY_XF86Cut, Qt::Key_Cut>,
- Xkb2Qt<XKB_KEY_XF86Display, Qt::Key_Display>,
- Xkb2Qt<XKB_KEY_XF86DOS, Qt::Key_DOS>,
- Xkb2Qt<XKB_KEY_XF86Documents, Qt::Key_Documents>,
- Xkb2Qt<XKB_KEY_XF86Excel, Qt::Key_Excel>,
- Xkb2Qt<XKB_KEY_XF86Explorer, Qt::Key_Explorer>,
- Xkb2Qt<XKB_KEY_XF86Game, Qt::Key_Game>,
- Xkb2Qt<XKB_KEY_XF86Go, Qt::Key_Go>,
- Xkb2Qt<XKB_KEY_XF86iTouch, Qt::Key_iTouch>,
- Xkb2Qt<XKB_KEY_XF86LogOff, Qt::Key_LogOff>,
- Xkb2Qt<XKB_KEY_XF86Market, Qt::Key_Market>,
- Xkb2Qt<XKB_KEY_XF86Meeting, Qt::Key_Meeting>,
- Xkb2Qt<XKB_KEY_XF86MenuKB, Qt::Key_MenuKB>,
- Xkb2Qt<XKB_KEY_XF86MenuPB, Qt::Key_MenuPB>,
- Xkb2Qt<XKB_KEY_XF86MySites, Qt::Key_MySites>,
- Xkb2Qt<XKB_KEY_XF86New, Qt::Key_New>,
- Xkb2Qt<XKB_KEY_XF86News, Qt::Key_News>,
- Xkb2Qt<XKB_KEY_XF86OfficeHome, Qt::Key_OfficeHome>,
- Xkb2Qt<XKB_KEY_XF86Open, Qt::Key_Open>,
- Xkb2Qt<XKB_KEY_XF86Option, Qt::Key_Option>,
- Xkb2Qt<XKB_KEY_XF86Paste, Qt::Key_Paste>,
- Xkb2Qt<XKB_KEY_XF86Phone, Qt::Key_Phone>,
- Xkb2Qt<XKB_KEY_XF86Reply, Qt::Key_Reply>,
- Xkb2Qt<XKB_KEY_XF86Reload, Qt::Key_Reload>,
- Xkb2Qt<XKB_KEY_XF86RotateWindows, Qt::Key_RotateWindows>,
- Xkb2Qt<XKB_KEY_XF86RotationPB, Qt::Key_RotationPB>,
- Xkb2Qt<XKB_KEY_XF86RotationKB, Qt::Key_RotationKB>,
- Xkb2Qt<XKB_KEY_XF86Save, Qt::Key_Save>,
- Xkb2Qt<XKB_KEY_XF86Send, Qt::Key_Send>,
- Xkb2Qt<XKB_KEY_XF86Spell, Qt::Key_Spell>,
- Xkb2Qt<XKB_KEY_XF86SplitScreen, Qt::Key_SplitScreen>,
- Xkb2Qt<XKB_KEY_XF86Support, Qt::Key_Support>,
- Xkb2Qt<XKB_KEY_XF86TaskPane, Qt::Key_TaskPane>,
- Xkb2Qt<XKB_KEY_XF86Terminal, Qt::Key_Terminal>,
- Xkb2Qt<XKB_KEY_XF86Tools, Qt::Key_Tools>,
- Xkb2Qt<XKB_KEY_XF86Travel, Qt::Key_Travel>,
- Xkb2Qt<XKB_KEY_XF86Video, Qt::Key_Video>,
- Xkb2Qt<XKB_KEY_XF86Word, Qt::Key_Word>,
- Xkb2Qt<XKB_KEY_XF86Xfer, Qt::Key_Xfer>,
- Xkb2Qt<XKB_KEY_XF86ZoomIn, Qt::Key_ZoomIn>,
- Xkb2Qt<XKB_KEY_XF86ZoomOut, Qt::Key_ZoomOut>,
- Xkb2Qt<XKB_KEY_XF86Away, Qt::Key_Away>,
- Xkb2Qt<XKB_KEY_XF86Messenger, Qt::Key_Messenger>,
- Xkb2Qt<XKB_KEY_XF86WebCam, Qt::Key_WebCam>,
- Xkb2Qt<XKB_KEY_XF86MailForward, Qt::Key_MailForward>,
- Xkb2Qt<XKB_KEY_XF86Pictures, Qt::Key_Pictures>,
- Xkb2Qt<XKB_KEY_XF86Music, Qt::Key_Music>,
- Xkb2Qt<XKB_KEY_XF86Battery, Qt::Key_Battery>,
- Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
- Xkb2Qt<XKB_KEY_XF86WLAN, Qt::Key_WLAN>,
- Xkb2Qt<XKB_KEY_XF86UWB, Qt::Key_UWB>,
- Xkb2Qt<XKB_KEY_XF86AudioForward, Qt::Key_AudioForward>,
- Xkb2Qt<XKB_KEY_XF86AudioRepeat, Qt::Key_AudioRepeat>,
- Xkb2Qt<XKB_KEY_XF86AudioRandomPlay, Qt::Key_AudioRandomPlay>,
- Xkb2Qt<XKB_KEY_XF86Subtitle, Qt::Key_Subtitle>,
- Xkb2Qt<XKB_KEY_XF86AudioCycleTrack, Qt::Key_AudioCycleTrack>,
- Xkb2Qt<XKB_KEY_XF86Time, Qt::Key_Time>,
- Xkb2Qt<XKB_KEY_XF86Select, Qt::Key_Select>,
- Xkb2Qt<XKB_KEY_XF86View, Qt::Key_View>,
- Xkb2Qt<XKB_KEY_XF86TopMenu, Qt::Key_TopMenu>,
- Xkb2Qt<XKB_KEY_XF86Red, Qt::Key_Red>,
- Xkb2Qt<XKB_KEY_XF86Green, Qt::Key_Green>,
- Xkb2Qt<XKB_KEY_XF86Yellow, Qt::Key_Yellow>,
- Xkb2Qt<XKB_KEY_XF86Blue, Qt::Key_Blue>,
- Xkb2Qt<XKB_KEY_XF86Bluetooth, Qt::Key_Bluetooth>,
- Xkb2Qt<XKB_KEY_XF86Suspend, Qt::Key_Suspend>,
- Xkb2Qt<XKB_KEY_XF86Hibernate, Qt::Key_Hibernate>,
- Xkb2Qt<XKB_KEY_XF86TouchpadToggle, Qt::Key_TouchpadToggle>,
- Xkb2Qt<XKB_KEY_XF86TouchpadOn, Qt::Key_TouchpadOn>,
- Xkb2Qt<XKB_KEY_XF86TouchpadOff, Qt::Key_TouchpadOff>,
- Xkb2Qt<XKB_KEY_XF86AudioMicMute, Qt::Key_MicMute>,
- Xkb2Qt<XKB_KEY_XF86Launch0, Qt::Key_Launch2>, // ### Qt 6: remap properly
- Xkb2Qt<XKB_KEY_XF86Launch1, Qt::Key_Launch3>,
- Xkb2Qt<XKB_KEY_XF86Launch2, Qt::Key_Launch4>,
- Xkb2Qt<XKB_KEY_XF86Launch3, Qt::Key_Launch5>,
- Xkb2Qt<XKB_KEY_XF86Launch4, Qt::Key_Launch6>,
- Xkb2Qt<XKB_KEY_XF86Launch5, Qt::Key_Launch7>,
- Xkb2Qt<XKB_KEY_XF86Launch6, Qt::Key_Launch8>,
- Xkb2Qt<XKB_KEY_XF86Launch7, Qt::Key_Launch9>,
- Xkb2Qt<XKB_KEY_XF86Launch8, Qt::Key_LaunchA>,
- Xkb2Qt<XKB_KEY_XF86Launch9, Qt::Key_LaunchB>,
- Xkb2Qt<XKB_KEY_XF86LaunchA, Qt::Key_LaunchC>,
- Xkb2Qt<XKB_KEY_XF86LaunchB, Qt::Key_LaunchD>,
- Xkb2Qt<XKB_KEY_XF86LaunchC, Qt::Key_LaunchE>,
- Xkb2Qt<XKB_KEY_XF86LaunchD, Qt::Key_LaunchF>,
- Xkb2Qt<XKB_KEY_XF86LaunchE, Qt::Key_LaunchG>,
- Xkb2Qt<XKB_KEY_XF86LaunchF, Qt::Key_LaunchH>
- >::Data{}
-);
-
-// Possible modifier states.
-static const Qt::KeyboardModifiers ModsTbl[] = {
- Qt::NoModifier, // 0
- Qt::ShiftModifier, // 1
- Qt::ControlModifier, // 2
- Qt::ControlModifier | Qt::ShiftModifier, // 3
- Qt::AltModifier, // 4
- Qt::AltModifier | Qt::ShiftModifier, // 5
- Qt::AltModifier | Qt::ControlModifier, // 6
- Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7
- Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts
-};
+QT_BEGIN_NAMESPACE
Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const
{
- Qt::KeyboardModifiers ret = 0;
+ Qt::KeyboardModifiers ret = Qt::NoModifier;
if (s & XCB_MOD_MASK_SHIFT)
ret |= Qt::ShiftModifier;
if (s & XCB_MOD_MASK_CONTROL)
@@ -473,7 +88,7 @@ static xcb_keysym_t getUnshiftedXKey(xcb_keysym_t unshifted, xcb_keysym_t shifte
xcb_keysym_t xlower;
xcb_keysym_t xupper;
- xkbcommon_XConvertCase(unshifted, &xlower, &xupper);
+ QXkbCommon::xkbcommon_XConvertCase(unshifted, &xlower, &xupper);
if (xlower != xupper // Check if symbol is cased
&& unshifted == xupper) { // Unshifted must be upper case
@@ -805,7 +420,12 @@ void QXcbKeyboard::updateKeymap()
updateXKBMods();
- checkForLatinLayout();
+ QXkbCommon::verifyHasLatinLayout(m_xkbKeymap.get());
+}
+
+QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
+{
+ return QXkbCommon::possibleKeys(m_xkbState.get(), event, m_superAsMeta, m_hyperAsMeta);
}
#if QT_CONFIG(xkb)
@@ -918,272 +538,6 @@ void QXcbKeyboard::updateXKBMods()
xkb_mods.mod5 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod5");
}
-static bool isLatin(xkb_keysym_t sym)
-{
- return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z'));
-}
-
-void QXcbKeyboard::checkForLatinLayout() const
-{
- const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(m_xkbKeymap.get());
- const xcb_keycode_t minKeycode = xkb_keymap_min_keycode(m_xkbKeymap.get());
- const xcb_keycode_t maxKeycode = xkb_keymap_max_keycode(m_xkbKeymap.get());
-
- const xkb_keysym_t *keysyms = nullptr;
- int nrLatinKeys = 0;
- for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
- for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
- xkb_keymap_key_get_syms_by_level(m_xkbKeymap.get(), code, layout, 0, &keysyms);
- if (keysyms && isLatin(keysyms[0]))
- nrLatinKeys++;
- if (nrLatinKeys > 10) // arbitrarily chosen threshold
- return;
- }
- }
- // This means that lookupLatinKeysym() will not find anything and latin
- // key shortcuts might not work. This is a bug in the affected desktop
- // environment. Usually can be solved via system settings by adding e.g. 'us'
- // layout to the list of seleced layouts, or by using command line, "setxkbmap
- // -layout rus,en". The position of latin key based layout in the list of the
- // selected layouts is irrelevant. Properly functioning desktop environments
- // handle this behind the scenes, even if no latin key based layout has been
- // explicitly listed in the selected layouts.
- qCWarning(lcQpaKeyboard, "no keyboard layouts with latin keys present");
-}
-
-xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
-{
- xkb_layout_index_t layout;
- xkb_keysym_t sym = XKB_KEY_NoSymbol;
- const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(m_xkbKeymap.get(), keycode);
- const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(m_xkbState.get(), keycode);
- // Look at user layouts in the order in which they are defined in system
- // settings to find a latin keysym.
- for (layout = 0; layout < layoutCount; ++layout) {
- if (layout == currentLayout)
- continue;
- const xkb_keysym_t *syms;
- xkb_level_index_t level = xkb_state_key_get_level(m_xkbState.get(), keycode, layout);
- if (xkb_keymap_key_get_syms_by_level(m_xkbKeymap.get(), keycode, layout, level, &syms) != 1)
- continue;
- if (isLatin(syms[0])) {
- sym = syms[0];
- break;
- }
- }
-
- if (sym == XKB_KEY_NoSymbol)
- return sym;
-
- xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LATCHED);
- xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LOCKED);
-
- // Check for uniqueness, consider the following setup:
- // setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active).
- // In this setup, the user would expect to trigger a ctrl+q shortcut by pressing ctrl+<physical x key>,
- // because "US dvorak" is higher up in the layout settings list. This check verifies that an obtained
- // 'sym' can not be acquired by any other layout higher up in the user's layout list. If it can be acquired
- // then the obtained key is not unique. This prevents ctrl+<physical q key> from generating a ctrl+q
- // shortcut in the above described setup. We don't want ctrl+<physical x key> and ctrl+<physical q key> to
- // generate the same shortcut event in this case.
- const xcb_keycode_t minKeycode = xkb_keymap_min_keycode(m_xkbKeymap.get());
- const xcb_keycode_t maxKeycode = xkb_keymap_max_keycode(m_xkbKeymap.get());
- ScopedXKBState state(xkb_state_new(m_xkbKeymap.get()));
- for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) {
- xkb_state_update_mask(state.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout);
- for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
- xkb_keysym_t prevSym = xkb_state_key_get_one_sym(state.get(), code);
- if (prevSym == sym) {
- sym = XKB_KEY_NoSymbol;
- break;
- }
- }
- }
-
- return sym;
-}
-
-static const char *qtKeyName(int qtKey)
-{
- int keyEnumIndex = qt_getQtMetaObject()->indexOfEnumerator("Key");
- QMetaEnum keyEnum = qt_getQtMetaObject()->enumerator(keyEnumIndex);
- return keyEnum.valueToKey(qtKey);
-}
-
-QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
-{
- // turn off the modifier bits which doesn't participate in shortcuts
- Qt::KeyboardModifiers notNeeded = Qt::KeypadModifier | Qt::GroupSwitchModifier;
- Qt::KeyboardModifiers modifiers = event->modifiers() &= ~notNeeded;
- // create a fresh kb state and test against the relevant modifier combinations
- struct xkb_state *kb_state = xkb_state_new(m_xkbKeymap.get());
- if (!kb_state) {
- qWarning("QXcbKeyboard: failed to compile xkb keymap!");
- return QList<int>();
- }
- // get kb state from the master xkb_state and update the temporary kb_state
- xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(m_xkbState.get(), XKB_STATE_LAYOUT_LOCKED);
- xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LATCHED);
- xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LOCKED);
- xkb_mod_mask_t depressedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_DEPRESSED);
-
- xkb_state_update_mask(kb_state, depressedMods, latchedMods, lockedMods, 0, 0, lockedLayout);
- quint32 keycode = event->nativeScanCode();
- // handle shortcuts for level three and above
- xkb_layout_index_t layoutIndex = xkb_state_key_get_layout(kb_state, keycode);
- xkb_level_index_t levelIndex = 0;
- if (layoutIndex != XKB_LAYOUT_INVALID) {
- levelIndex = xkb_state_key_get_level(kb_state, keycode, layoutIndex);
- if (levelIndex == XKB_LEVEL_INVALID)
- levelIndex = 0;
- }
- if (levelIndex <= 1)
- xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods, 0, 0, lockedLayout);
-
- xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, keycode);
- if (sym == XKB_KEY_NoSymbol) {
- xkb_state_unref(kb_state);
- return QList<int>();
- }
-
- QList<int> result;
- int baseQtKey = keysymToQtKey(sym, modifiers, kb_state, keycode);
- if (baseQtKey)
- result += (baseQtKey + modifiers);
-
- xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Shift");
- xkb_mod_index_t altMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Alt");
- xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Control");
- xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Meta");
-
- Q_ASSERT(shiftMod < 32);
- Q_ASSERT(altMod < 32);
- Q_ASSERT(controlMod < 32);
-
- xkb_mod_mask_t depressed;
- int qtKey = 0;
- // obtain a list of possible shortcuts for the given key event
- for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) {
- Qt::KeyboardModifiers neededMods = ModsTbl[i];
- if ((modifiers & neededMods) == neededMods) {
- if (i == 8) {
- if (isLatin(baseQtKey))
- continue;
- // add a latin key as a fall back key
- sym = lookupLatinKeysym(keycode);
- } else {
- depressed = 0;
- if (neededMods & Qt::AltModifier)
- depressed |= (1 << altMod);
- if (neededMods & Qt::ShiftModifier)
- depressed |= (1 << shiftMod);
- if (neededMods & Qt::ControlModifier)
- depressed |= (1 << controlMod);
- if (metaMod < 32 && neededMods & Qt::MetaModifier)
- depressed |= (1 << metaMod);
- xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, 0, 0, lockedLayout);
- sym = xkb_state_key_get_one_sym(kb_state, keycode);
- }
- if (sym == XKB_KEY_NoSymbol)
- continue;
-
- Qt::KeyboardModifiers mods = modifiers & ~neededMods;
- qtKey = keysymToQtKey(sym, mods, kb_state, keycode);
- if (!qtKey || qtKey == baseQtKey)
- continue;
-
- // catch only more specific shortcuts, i.e. Ctrl+Shift+= also generates Ctrl++ and +,
- // but Ctrl++ is more specific than +, so we should skip the last one
- bool ambiguous = false;
- for (int shortcut : qAsConst(result)) {
- if (int(shortcut & ~Qt::KeyboardModifierMask) == qtKey && (shortcut & mods) == mods) {
- ambiguous = true;
- break;
- }
- }
- if (ambiguous)
- continue;
-
- result += (qtKey + mods);
- }
- }
- xkb_state_unref(kb_state);
- return result;
-}
-
-int QXcbKeyboard::keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
- struct xkb_state *state, xcb_keycode_t code) const
-{
- int qtKey = 0;
-
- // lookup from direct mapping
- if (keysym >= XKB_KEY_F1 && keysym <= XKB_KEY_F35) {
- // function keys
- qtKey = Qt::Key_F1 + (keysym - XKB_KEY_F1);
- } else if (keysym >= XKB_KEY_KP_0 && keysym <= XKB_KEY_KP_9) {
- // numeric keypad keys
- qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0);
- } else if (isLatin(keysym)) {
- qtKey = xkbcommon_xkb_keysym_to_upper(keysym);
- } else {
- // check if we have a direct mapping
- xkb2qt_t searchKey{keysym, 0};
- auto it = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
- if (it != KeyTbl.end() && !(searchKey < *it))
- qtKey = it->qt;
- }
-
- QString text;
- bool fromUnicode = qtKey == 0;
- if (fromUnicode) { // lookup from unicode
- if (modifiers & Qt::ControlModifier) {
- // Control modifier changes the text to ASCII control character, therefore we
- // can't use this text to map keysym to a qt key. We can use the same keysym
- // (it is not affectd by transformation) to obtain untransformed text. For details
- // see "Appendix A. Default Symbol Transformations" in the XKB specification.
- text = lookupStringNoKeysymTransformations(keysym);
- } else {
- text = lookupString(state, code);
- }
- if (!text.isEmpty()) {
- if (text.unicode()->isDigit()) {
- // Ensures that also non-latin digits are mapped to corresponding qt keys,
- // e.g CTRL + ۲ (arabic two), is mapped to CTRL + Qt::Key_2.
- qtKey = Qt::Key_0 + text.unicode()->digitValue();
- } else {
- qtKey = text.unicode()->toUpper().unicode();
- }
- }
- }
-
- if (rmod_masks.meta) {
- // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
- if (rmod_masks.meta == rmod_masks.super && (qtKey == Qt::Key_Super_L
- || qtKey == Qt::Key_Super_R)) {
- qtKey = Qt::Key_Meta;
- } else if (rmod_masks.meta == rmod_masks.hyper && (qtKey == Qt::Key_Hyper_L
- || qtKey == Qt::Key_Hyper_R)) {
- qtKey = Qt::Key_Meta;
- }
- }
-
- if (Q_UNLIKELY(lcQpaKeyboard().isDebugEnabled())) {
- char keysymName[64];
- xkb_keysym_get_name(keysym, keysymName, sizeof(keysymName));
- QString keysymInHex = QString(QStringLiteral("0x%1")).arg(keysym, 0, 16);
- if (qtKeyName(qtKey)) {
- qCDebug(lcQpaKeyboard).nospace() << "keysym: " << keysymName << "("
- << keysymInHex << ") mapped to Qt::" << qtKeyName(qtKey) << " | text: " << text
- << " | qt key: " << qtKey << " mapped from unicode number: " << fromUnicode;
- } else {
- qCDebug(lcQpaKeyboard).nospace() << "no Qt::Key for keysym: " << keysymName
- << "(" << keysymInHex << ") | text: " << text << " | qt key: " << qtKey;
- }
- }
-
- return qtKey;
-}
-
QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
: QXcbObject(connection)
{
@@ -1514,6 +868,12 @@ void QXcbKeyboard::resolveMaskConflicts()
rmod_masks.meta = rmod_masks.hyper;
}
}
+
+ // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
+ if (rmod_masks.meta && rmod_masks.meta == rmod_masks.super)
+ m_superAsMeta = true;
+ if (rmod_masks.meta && rmod_masks.meta == rmod_masks.hyper)
+ m_hyperAsMeta = true;
}
void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, xcb_keycode_t code,
@@ -1529,7 +889,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
if (type == QEvent::KeyPress)
targetWindow->updateNetWmUserTime(time);
- ScopedXKBState sendEventState;
+ QXkbCommon::ScopedXKBState sendEventState;
if (fromSendEvent) {
// Have a temporary keyboard state filled in from state
// this way we allow for synthetic events to have different state
@@ -1546,30 +906,13 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
struct xkb_state *xkbState = fromSendEvent ? sendEventState.get() : m_xkbState.get();
xcb_keysym_t sym = xkb_state_key_get_one_sym(xkbState, code);
- QString text = lookupString(xkbState, code);
+ QString text = QXkbCommon::lookupString(xkbState, code);
Qt::KeyboardModifiers modifiers = translateModifiers(state);
- if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_9)
+ if (QXkbCommon::isKeypad(sym))
modifiers |= Qt::KeypadModifier;
- // Note 1: All standard key sequences on linux (as defined in platform theme)
- // that use a latin character also contain a control modifier, which is why
- // checking for Qt::ControlModifier is sufficient here. It is possible to
- // override QPlatformTheme::keyBindings() and provide custom sequences for
- // QKeySequence::StandardKey. Custom sequences probably should respect this
- // convention (alternatively, we could test against other modifiers here).
- // Note 2: The possibleKeys() shorcut mechanism is not affected by this value
- // adjustment and does its own thing.
- xcb_keysym_t latinKeysym = XKB_KEY_NoSymbol;
- if (modifiers & Qt::ControlModifier) {
- // With standard shortcuts we should prefer a latin character, this is
- // in checks like "event == QKeySequence::Copy".
- if (!isLatin(sym))
- latinKeysym = lookupLatinKeysym(code);
- }
-
- int qtcode = keysymToQtKey(latinKeysym != XKB_KEY_NoSymbol ? latinKeysym : sym,
- modifiers, xkbState, code);
+ int qtcode = QXkbCommon::keysymToQtKey(sym, modifiers, xkbState, code, m_superAsMeta, m_hyperAsMeta);
if (type == QEvent::KeyPress) {
if (m_isAutoRepeat && m_autoRepeatCode != code)
@@ -1611,28 +954,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
}
}
-QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code) const
-{
- QVarLengthArray<char, 32> chars(32);
- const int size = xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
- if (Q_UNLIKELY(size + 1 > chars.size())) { // +1 for NUL
- chars.resize(size + 1);
- xkb_state_key_get_utf8(state, code, chars.data(), chars.size());
- }
- return QString::fromUtf8(chars.constData(), size);
-}
-
-QString QXcbKeyboard::lookupStringNoKeysymTransformations(xkb_keysym_t keysym) const
-{
- QVarLengthArray<char, 32> chars(32);
- const int size = xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
- if (Q_UNLIKELY(size > chars.size())) {
- chars.resize(size);
- xkb_keysym_to_utf8(keysym, chars.data(), chars.size());
- }
- return QString::fromUtf8(chars.constData(), size);
-}
-
static bool fromSendEvent(const void *event)
{
// From X11 protocol: Every event contains an 8-bit type code. The most
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index f8490592b7..75071d045f 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -50,16 +50,12 @@
#endif
#include <xkbcommon/xkbcommon.h>
-#if QT_CONFIG(xkb)
-#include <xkbcommon/xkbcommon-x11.h>
-#endif
+#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#include <QEvent>
QT_BEGIN_NAMESPACE
-class QWindow;
-
class QXcbKeyboard : public QXcbObject
{
public:
@@ -75,7 +71,7 @@ public:
Qt::KeyboardModifiers translateModifiers(int s) const;
void updateKeymap(xcb_mapping_notify_event_t *event);
void updateKeymap();
- QList<int> possibleKeys(const QKeyEvent *e) const;
+ QList<int> possibleKeys(const QKeyEvent *event) const;
// when XKEYBOARD not present on the X server
void updateXKBMods();
@@ -96,10 +92,6 @@ protected:
quint16 state, xcb_timestamp_t time, bool fromSendEvent);
void resolveMaskConflicts();
- QString lookupString(struct xkb_state *state, xcb_keycode_t code) const;
- QString lookupStringNoKeysymTransformations(xkb_keysym_t keysym) const;
- int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
- struct xkb_state *state, xcb_keycode_t code) const;
typedef QMap<xcb_keysym_t, int> KeysymModifierMap;
struct xkb_keymap *keymapFromCore(const KeysymModifierMap &keysymMods);
@@ -111,9 +103,6 @@ protected:
void updateVModMapping();
void updateVModToRModMapping();
- xkb_keysym_t lookupLatinKeysym(xkb_keycode_t keycode) const;
- void checkForLatinLayout() const;
-
private:
bool m_config = false;
bool m_isAutoRepeat = false;
@@ -148,22 +137,12 @@ private:
int core_device_id;
#endif
- struct XKBStateDeleter {
- void operator()(struct xkb_state *state) const { return xkb_state_unref(state); }
- };
- struct XKBKeymapDeleter {
- void operator()(struct xkb_keymap *keymap) const { return xkb_keymap_unref(keymap); }
- };
- struct XKBContextDeleter {
- void operator()(struct xkb_context *context) const { return xkb_context_unref(context); }
- };
- using ScopedXKBState = std::unique_ptr<struct xkb_state, XKBStateDeleter>;
- using ScopedXKBKeymap = std::unique_ptr<struct xkb_keymap, XKBKeymapDeleter>;
- using ScopedXKBContext = std::unique_ptr<struct xkb_context, XKBContextDeleter>;
+ QXkbCommon::ScopedXKBState m_xkbState;
+ QXkbCommon::ScopedXKBKeymap m_xkbKeymap;
+ QXkbCommon::ScopedXKBContext m_xkbContext;
- ScopedXKBState m_xkbState;
- ScopedXKBKeymap m_xkbKeymap;
- ScopedXKBContext m_xkbContext;
+ bool m_superAsMeta = false;
+ bool m_hyperAsMeta = false;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index db3d6629b3..34c671c8c7 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -6,7 +6,8 @@ QT += \
core-private gui-private \
service_support-private theme_support-private \
fontdatabase_support-private \
- edid_support-private
+ edid_support-private \
+ xkbcommon_support-private
qtHaveModule(linuxaccessibility_support-private): \
QT += linuxaccessibility_support-private
@@ -52,7 +53,6 @@ HEADERS = \
qxcbimage.h \
qxcbxsettings.h \
qxcbsystemtraytracker.h \
- qxcbxkbcommon.h \
qxcbeventqueue.h \
qxcbeventdispatcher.h \
qxcbconnection_basic.h \
diff --git a/sync.profile b/sync.profile
index a6d0e2a4a7..e6fc285573 100644
--- a/sync.profile
+++ b/sync.profile
@@ -18,6 +18,7 @@
"QtEventDispatcherSupport" => "$basedir/src/platformsupport/eventdispatchers",
"QtFontDatabaseSupport" => "$basedir/src/platformsupport/fontdatabases",
"QtInputSupport" => "$basedir/src/platformsupport/input",
+ "QtXkbCommonSupport" => "$basedir/src/platformsupport/input/xkbcommon",
"QtPlatformCompositorSupport" => "$basedir/src/platformsupport/platformcompositor",
"QtServiceSupport" => "$basedir/src/platformsupport/services",
"QtThemeSupport" => "$basedir/src/platformsupport/themes",