File indexing completed on 2024-04-14 03:56:52
0001 /* This file is part of the KDE libraries 0002 SPDX-FileCopyrightText: 2017 David Faure <faure@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "kkeyserver.h" 0008 #include <QTest> 0009 #include <private/qtx11extras_p.h> 0010 0011 #include <X11/keysym.h> 0012 #include <xcb/xcb_keysyms.h> 0013 0014 class KKeyServerTest : public QObject 0015 { 0016 Q_OBJECT 0017 private Q_SLOTS: 0018 0019 void initTestCase() 0020 { 0021 m_keySymbols = xcb_key_symbols_alloc(QX11Info::connection()); 0022 0023 // This makes me wonder why we have KKeyServer::modXShift :-) 0024 QCOMPARE(XCB_MOD_MASK_SHIFT, xcb_mod_mask_t(KKeyServer::modXShift())); 0025 } 0026 0027 void cleanupTestCase() 0028 { 0029 if (m_keySymbols) { 0030 xcb_key_symbols_free(m_keySymbols); 0031 } 0032 } 0033 0034 void keyQtToSymX_data() 0035 { 0036 QTest::addColumn<int>("keyQt"); 0037 QTest::addColumn<uint>("modX"); 0038 QTest::addColumn<uint>("additionalState"); // set to XCB_MOD_MASK_SHIFT if shift would indeed be pressed for this shortcut 0039 QTest::addColumn<int>("keySymX"); 0040 0041 const uint numLock = KKeyServer::modXNumLock(); 0042 0043 // clang-format off 0044 // Before adding any testcase below, check what `kcmshell5 keys` records, to make sure it matches 0045 QTest::newRow("a") << int(Qt::Key_A) << uint(0) << numLock << XK_A; 0046 QTest::newRow("CTRL_F1") << QKeyCombination(Qt::ControlModifier|Qt::Key_F1).toCombined() << KKeyServer::modXCtrl() << numLock << XK_F1; 0047 QTest::newRow("CTRL_1") << QKeyCombination(Qt::ControlModifier|Qt::Key_1).toCombined() << KKeyServer::modXCtrl() << numLock << XK_1; 0048 QTest::newRow("CTRL_keypad_1") << QKeyCombination(Qt::ControlModifier|Qt::KeypadModifier|Qt::Key_1).toCombined() << KKeyServer::modXCtrl() << numLock << XK_KP_1; 0049 QTest::newRow("CTRL_keypad_slash") << QKeyCombination(Qt::ControlModifier|Qt::KeypadModifier|Qt::Key_Slash).toCombined() << KKeyServer::modXCtrl() << numLock << XK_KP_Divide; 0050 QTest::newRow("CTRL_SHIFT_keypad_end") << QKeyCombination(Qt::ControlModifier|Qt::ShiftModifier|Qt::KeypadModifier|Qt::Key_End).toCombined() << (KKeyServer::modXCtrl()|KKeyServer::modXShift()) << numLock << XK_KP_End; 0051 QTest::newRow("CTRL_keypad_end_no_numlock") << QKeyCombination(Qt::ControlModifier|Qt::KeypadModifier|Qt::Key_End).toCombined() << (KKeyServer::modXCtrl()) << uint(0) << XK_KP_End; 0052 QTest::newRow("CTRL_ampersand") << QKeyCombination(Qt::ControlModifier|Qt::Key_Ampersand).toCombined() << KKeyServer::modXCtrl() << uint(XCB_MOD_MASK_SHIFT|numLock) << XK_ampersand; 0053 QTest::newRow("ALT_SHIFT_right") << QKeyCombination(Qt::AltModifier|Qt::ShiftModifier|Qt::Key_Right).toCombined() << (KKeyServer::modXAlt() | KKeyServer::modXShift()) << numLock << XK_Right; 0054 QTest::newRow("CTRL_SHIFT_right") << QKeyCombination(Qt::ControlModifier|Qt::ShiftModifier|Qt::Key_Right).toCombined() << (KKeyServer::modXCtrl() | KKeyServer::modXShift()) << numLock << XK_Right; 0055 QTest::newRow("META_SHIFT_print") << QKeyCombination(Qt::MetaModifier|Qt::ShiftModifier|Qt::Key_Print).toCombined() << (KKeyServer::modXMeta() | KKeyServer::modXShift()) << numLock << XK_Print; 0056 QTest::newRow("ALT_Tab") << QKeyCombination(Qt::AltModifier|Qt::Key_Tab).toCombined() << (KKeyServer::modXAlt()) << numLock << XK_Tab; 0057 QTest::newRow("ALT_Shift_Tab") << QKeyCombination(Qt::AltModifier|Qt::ShiftModifier|Qt::Key_Tab).toCombined() << (KKeyServer::modXAlt() | KKeyServer::modXShift()) << numLock << XK_Tab; 0058 // clang-format on 0059 } 0060 0061 void keyQtToSymX() 0062 { 0063 QFETCH(int, keyQt); 0064 QFETCH(uint, modX); 0065 QFETCH(int, keySymX); 0066 int sym; 0067 QVERIFY(KKeyServer::keyQtToSymX(keyQt, &sym)); 0068 QCOMPARE(QString::number(sym, 16), QString::number(keySymX, 16)); 0069 uint mod; 0070 QVERIFY(KKeyServer::keyQtToModX(keyQt, &mod)); 0071 QCOMPARE(mod, modX); 0072 } 0073 0074 void symXToKeyQt_data() 0075 { 0076 keyQtToSymX_data(); 0077 } 0078 0079 void symXToKeyQt() 0080 { 0081 QFETCH(int, keyQt); 0082 QFETCH(uint, modX); 0083 QFETCH(int, keySymX); 0084 int keyCodeQt; 0085 0086 // qDebug() << "modX=" << modX << "keySymX=0x" << QString::number(keySymX, 16) << "keyQt=0x" << QString::number(keyQt, 16); 0087 0088 QVERIFY(KKeyServer::symXModXToKeyQt(keySymX, modX, &keyCodeQt)); 0089 QCOMPARE(keyCodeQt, keyQt); 0090 } 0091 0092 void keyQtToSymXsCalculatorKey() 0093 { 0094 // Should return both XF86XK_Calculator and XF86XK_Calculater 0095 QList<int> keyCodes = KKeyServer::keyQtToSymXs(Qt::Key_Calculator); 0096 QVERIFY(keyCodes.size() == 2); 0097 QVERIFY(keyCodes[0] != keyCodes[1]); 0098 int keyCodeQt; 0099 0100 QVERIFY(KKeyServer::symXModXToKeyQt(keyCodes[0], 0, &keyCodeQt)); 0101 QCOMPARE(keyCodeQt, int(Qt::Key_Calculator)); 0102 QVERIFY(KKeyServer::symXModXToKeyQt(keyCodes[1], 0, &keyCodeQt)); 0103 QCOMPARE(keyCodeQt, int(Qt::Key_Calculator)); 0104 } 0105 0106 void keyQtToSymXs_data() 0107 { 0108 keyQtToSymX_data(); 0109 } 0110 0111 void keyQtToSymXs() 0112 { 0113 QFETCH(int, keyQt); 0114 QFETCH(uint, modX); 0115 QFETCH(int, keySymX); 0116 QList<int> syms = KKeyServer::keyQtToSymXs(keyQt); 0117 QVERIFY(syms.size() > 0); 0118 QCOMPARE(QString::number(syms[0], 16), QString::number(keySymX, 16)); 0119 uint mod; 0120 QVERIFY(KKeyServer::keyQtToModX(keyQt, &mod)); 0121 QCOMPARE(mod, modX); 0122 } 0123 0124 void decodeXcbEvent_data() 0125 { 0126 keyQtToSymX_data(); 0127 } 0128 0129 void decodeXcbEvent() 0130 { 0131 QFETCH(int, keyQt); 0132 QFETCH(uint, modX); 0133 QFETCH(uint, additionalState); 0134 QFETCH(int, keySymX); 0135 0136 xcb_keycode_t *keyCodes = xcb_key_symbols_get_keycode(m_keySymbols, keySymX); 0137 QVERIFY(keyCodes); 0138 const xcb_keycode_t keyCodeX = keyCodes[0]; 0139 QVERIFY(keyCodeX != XCB_NO_SYMBOL); 0140 free(keyCodes); 0141 0142 xcb_key_press_event_t event{XCB_KEY_PRESS, 0143 keyCodeX, 0144 0, 0145 0 /*time*/, 0146 0 /*root*/, 0147 0 /*event*/, 0148 0 /*child*/, 0149 0 /*root_x*/, 0150 0 /*root_y*/, 0151 0 /*event_x*/, 0152 0 /*event_y*/, 0153 uint16_t(modX | additionalState), 0154 0 /*same_screen*/, 0155 0 /*pad0*/}; 0156 0157 int decodedKeyQt; 0158 const bool ok = KKeyServer::xcbKeyPressEventToQt(&event, &decodedKeyQt); 0159 QVERIFY(ok); 0160 if (decodedKeyQt != keyQt) { 0161 qDebug() << "given modX=" << modX << "keySymX=0x" << QString::number(keySymX, 16) << "I expected keyQt=0x" << QString::number(keyQt, 16) 0162 << QKeySequence(keyQt).toString() << "got" << QString::number(decodedKeyQt, 16) << QKeySequence(decodedKeyQt).toString(); 0163 } 0164 QCOMPARE(decodedKeyQt, keyQt); 0165 } 0166 0167 private: 0168 xcb_key_symbols_t *m_keySymbols; 0169 }; 0170 0171 QTEST_MAIN(KKeyServerTest) 0172 0173 #include "kkeyserver_x11_unittest.moc"