diff options
Diffstat (limited to 'src/gui/platform/unix/qxkbcommon.cpp')
-rw-r--r-- | src/gui/platform/unix/qxkbcommon.cpp | 116 |
1 files changed, 58 insertions, 58 deletions
diff --git a/src/gui/platform/unix/qxkbcommon.cpp b/src/gui/platform/unix/qxkbcommon.cpp index 3db84097c7..ed29db3005 100644 --- a/src/gui/platform/unix/qxkbcommon.cpp +++ b/src/gui/platform/unix/qxkbcommon.cpp @@ -1,47 +1,14 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qxkbcommon_p.h" #include <private/qmakearray_p.h> +#include <QtCore/private/qstringiterator_p.h> +#include <QtCore/qvarlengtharray.h> #include <QtCore/QMetaMethod> + #include <QtGui/QKeyEvent> #include <QtGui/private/qguiapplication_p.h> @@ -50,8 +17,6 @@ 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); @@ -272,10 +237,14 @@ static constexpr const auto KeyTbl = qMakeArray( 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>, +/* The following four XKB_KEY_dead keys got removed in libxkbcommon 1.6.0 + The define check is kind of version check here. */ +#ifdef XKB_KEY_dead_lowline 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>, +#endif // Special keys from X.org - This include multimedia keys, // wireless/bluetooth/uwb keys, special launcher keys, etc. @@ -331,6 +300,7 @@ static constexpr const auto KeyTbl = qMakeArray( Xkb2Qt<XKB_KEY_XF86Book, Qt::Key_Book>, Xkb2Qt<XKB_KEY_XF86CD, Qt::Key_CD>, Xkb2Qt<XKB_KEY_XF86Calculater, Qt::Key_Calculator>, + Xkb2Qt<XKB_KEY_XF86Calculator, Qt::Key_Calculator>, Xkb2Qt<XKB_KEY_XF86Clear, Qt::Key_Clear>, Xkb2Qt<XKB_KEY_XF86ClearGrab, Qt::Key_ClearGrab>, Xkb2Qt<XKB_KEY_XF86Close, Qt::Key_Close>, @@ -494,7 +464,7 @@ QList<xkb_keysym_t> QXkbCommon::toKeysym(QKeyEvent *event) // 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)) + for (uint utf32 : std::as_const(ucs4)) keysyms.append(utf32 | 0x01000000); return keysyms; @@ -545,13 +515,27 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod // numeric keypad keys qtKey = Qt::Key_0 + (keysym - XKB_KEY_KP_0); } else if (QXkbCommon::isLatin1(keysym)) { + // Most Qt::Key values are determined by their upper-case version, + // where this is in the Latin-1 repertoire. So start with that: qtKey = QXkbCommon::qxkbcommon_xkb_keysym_to_upper(keysym); + // However, Key_mu and Key_ydiaeresis are U+00B5 MICRO SIGN and + // U+00FF LATIN SMALL LETTER Y WITH DIAERESIS, both lower-case, + // with upper-case forms outside Latin-1, so use them as they are + // since they're the Qt::Key values. + if (!QXkbCommon::isLatin1(qtKey)) + qtKey = 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; + + // 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; } if (qtKey) @@ -574,20 +558,16 @@ static int keysymToQtKey_internal(xkb_keysym_t keysym, Qt::KeyboardModifiers mod // 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(); + text = text.toUpper(); + QStringIterator i(text); + qtKey = i.next(0); } } - // 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 QXkbCommon::modifiers(struct xkb_state *state, xkb_keysym_t keysym) { Qt::KeyboardModifiers modifiers = Qt::NoModifier; @@ -600,6 +580,9 @@ Qt::KeyboardModifiers QXkbCommon::modifiers(struct xkb_state *state) if (xkb_state_mod_name_is_active(state, XKB_MOD_NAME_LOGO, XKB_STATE_MODS_EFFECTIVE) > 0) modifiers |= Qt::MetaModifier; + if (isKeypad(keysym)) + modifiers |= Qt::KeypadModifier; + return modifiers; } @@ -616,10 +599,24 @@ static const Qt::KeyboardModifiers ModsTbl[] = { Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts }; +/* + Compatibility until all sub modules have transitioned to new API below +*/ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event, bool superAsMeta, bool hyperAsMeta) { QList<int> result; + auto keyCombinations = possibleKeyCombinations(state, event, superAsMeta, hyperAsMeta); + for (auto keyCombination : keyCombinations) + result << keyCombination.toCombined(); + + return result; +} + +QList<QKeyCombination> QXkbCommon::possibleKeyCombinations(xkb_state *state, const QKeyEvent *event, + bool superAsMeta, bool hyperAsMeta) +{ + QList<QKeyCombination> result; quint32 keycode = event->nativeScanCode(); if (!keycode) return result; @@ -633,7 +630,7 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event, ScopedXKBState scopedXkbQueryState(xkb_state_new(keymap)); xkb_state *queryState = scopedXkbQueryState.get(); if (!queryState) { - qCWarning(lcXkbcommon) << Q_FUNC_INFO << "failed to compile xkb keymap"; + qCWarning(lcQpaKeyMapper) << Q_FUNC_INFO << "failed to compile xkb keymap"; return result; } // get kb state from the master state and update the temporary state @@ -659,7 +656,7 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event, int baseQtKey = keysymToQtKey_internal(sym, modifiers, queryState, keycode, superAsMeta, hyperAsMeta); if (baseQtKey) - result += (baseQtKey + int(modifiers)); + result += QKeyCombination::fromCombined(baseQtKey + int(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"); @@ -705,8 +702,9 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event, // 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) { + for (auto keyCombination : std::as_const(result)) { + if (keyCombination.key() == qtKey + && (keyCombination.keyboardModifiers() & mods) == mods) { ambiguous = true; break; } @@ -714,7 +712,7 @@ QList<int> QXkbCommon::possibleKeys(xkb_state *state, const QKeyEvent *event, if (ambiguous) continue; - result += (qtKey + int(mods)); + result += QKeyCombination::fromCombined(qtKey + int(mods)); } } @@ -741,18 +739,20 @@ void QXkbCommon::verifyHasLatinLayout(xkb_keymap *keymap) // 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 to the list of selected 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"); + qCDebug(lcQpaKeyMapper, "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; + if (!state) + return sym; 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); @@ -810,7 +810,7 @@ void QXkbCommon::setXkbContext(QPlatformInputContext *inputContext, struct xkb_c const char *const inputContextClassName = "QComposeInputContext"; const char *const normalizedSignature = "setXkbContext(xkb_context*)"; - if (inputContext->objectName() != QLatin1String(inputContextClassName)) + if (inputContext->objectName() != QLatin1StringView(inputContextClassName)) return; static const QMetaMethod setXkbContext = [&]() { @@ -818,7 +818,7 @@ void QXkbCommon::setXkbContext(QPlatformInputContext *inputContext, struct xkb_c QMetaMethod method = inputContext->metaObject()->method(methodIndex); Q_ASSERT(method.isValid()); if (!method.isValid()) - qCWarning(lcXkbcommon) << normalizedSignature << "not found on" << inputContextClassName; + qCWarning(lcQpaKeyMapper) << normalizedSignature << "not found on" << inputContextClassName; return method; }(); |