#include "TestLayouts.h" #include #include using namespace Qt::StringLiterals; namespace { QString rowLetters(const Layout &layout, int row) { QString letters; for (const KeyDef &key : layout.layers.first().rows[row]) { if (key.type == KeyType::Character && key.label.front().isLetter()) letters += key.label; } return letters; } const KeyDef &letterKey(const Layout &layout, const QString &label) { for (const Row &row : layout.layers.first().rows) { for (const KeyDef &key : row) { if (key.label == label) return key; } } qFatal("no key %s", qPrintable(label)); } } // namespace class TestLayoutBuilder : public QObject { Q_OBJECT private Q_SLOTS: void readsLetterRowsFromKeymap() { const Layout us = TestLayouts::build("us"); QCOMPARE(rowLetters(us, 0), u"qwertyuiop"); QCOMPARE(rowLetters(us, 1), u"asdfghjkl"); QCOMPARE(rowLetters(us, 2), u"zxcvbnm"); const Layout sk = TestLayouts::build("sk"); QCOMPARE(sk.name, u"Slovak"); QCOMPARE(rowLetters(sk, 0), u"qwertzuiopúä"); QCOMPARE(rowLetters(sk, 1), u"asdfghjklô"); QCOMPARE(rowLetters(sk, 2), u"yxcvbnm"); const Layout se = TestLayouts::build("se"); QCOMPARE(rowLetters(se, 0), u"qwertyuiopå"); QCOMPARE(rowLetters(se, 1), u"asdfghjklöä"); } void shiftedFormComesFromKeymap() { QCOMPARE(letterKey(TestLayouts::build("sk"), u"ô"_s).shifted, u"Ô"); } void flicksFollowColumns() { const Layout sk = TestLayouts::build("sk"); QCOMPARE(letterKey(sk, u"q"_s).flick, u"1"); QCOMPARE(letterKey(sk, u"p"_s).flick, u"0"); QVERIFY(letterKey(sk, u"ú"_s).flick.isEmpty()); // more letters than flicks } void numberRowLettersBecomeAlternates() { const Layout sk = TestLayouts::build("sk"); // The keymap's own letters come first: they're what this language types. QCOMPARE(letterKey(sk, u"s"_s).alternates.first(), u"š"); QCOMPARE(letterKey(sk, u"l"_s).alternates.first(), u"ľ"); QCOMPARE(letterKey(sk, u"n"_s).alternates.first(), u"ň"); // BKSL on sk QCOMPARE(letterKey(sk, u"e"_s).alternates.first(), u"é"); QCOMPARE(letterKey(sk, u"y"_s).alternates.first(), u"ý"); } void lettersWithoutDecompositionFindTheirBase() { QCOMPARE(letterKey(TestLayouts::build("de"), u"s"_s).alternates.first(), u"ß"); } void alternatesSkipLettersThatHaveKeys() { const Layout se = TestLayouts::build("se"); const QStringList a = letterKey(se, u"a"_s).alternates; QVERIFY(!a.contains(u"ä"_s)); QVERIFY(!a.contains(u"å"_s)); QVERIFY(a.contains(u"á"_s)); } void fullModeHasEveryTypingKey() { const Layout us = TestLayouts::build("us", KeyboardMode::Full); const auto labels = [&](int row) { QString text; for (const KeyDef &key : us.layers.first().rows[row]) { if (key.type == KeyType::Character) text += key.label; } return text; }; QCOMPARE(labels(0), u"`1234567890-="); QCOMPARE(labels(1), u"qwertyuiop[]\\"); QCOMPARE(labels(2), u"asdfghjkl;'"); QCOMPARE(labels(3), u"zxcvbnm,./"); // LSGT (< >) repeats , . shifted: left out QCOMPARE(letterKey(us, u"1"_s).flick, u"!"); QCOMPARE(letterKey(us, u"1"_s).shifted, u"!"); } void fullModeRowsStagger() { // The key ahead of A, and of the first key on the Z row: like a hardware keyboard, // with the ISO key (sk: |) taking its room from left shift. const auto offsets = [](const Layout &layout) { const QList &rows = layout.layers.first().rows; return std::pair{rows[2].first().width, rows[3].first().width}; }; QCOMPARE(offsets(TestLayouts::build("us", KeyboardMode::Full)), std::pair(1.75, 2.25)); const Layout sk = TestLayouts::build("sk", KeyboardMode::Full); QCOMPARE(offsets(sk), std::pair(1.75, 1.25)); QCOMPARE(sk.layers.first().rows[3].at(1).label, u"\\"_s); } void fullModeKeepsDeadKeysAndKeymapShift() { const Layout sk = TestLayouts::build("sk", KeyboardMode::Full); const KeyDef acute = letterKey(sk, u"´"_s); QCOMPARE(acute.dead, quint32(XKB_KEY_dead_acute)); QCOMPARE(acute.deadShifted, quint32(XKB_KEY_dead_caron)); QCOMPARE(letterKey(sk, u"ô"_s).shifted, u"\""); // as the physical key QCOMPARE(letterKey(sk, u"ľ"_s).shifted, u"2"); // Number-row letters are still long-press choices on their base letter. QCOMPARE(letterKey(sk, u"t"_s).alternates.first(), u"ť"); QCOMPARE(letterKey(sk, u"l"_s).alternates.first(), u"ľ"); } void fullModeLettersFlickToTheirAltGrSymbol() { const Layout sk = TestLayouts::build("sk", KeyboardMode::Full); const KeyDef j = letterKey(sk, u"j"_s); QCOMPARE(j.altGr, u"'"); QCOMPARE(j.flick, u"'"); QCOMPARE(j.text({ShiftLevel::None, true}), u"'"); QCOMPARE(letterKey(sk, u"ô"_s).flick, u"\""); // keys with a shifted symbol keep it const KeyDef plus = letterKey(sk, u"+"_s); QCOMPARE(plus.deadAt({ShiftLevel::Shifted, true}), quint32(XKB_KEY_dead_tilde)); QCOMPARE(plus.text({ShiftLevel::None, true}), u"!"); } void noPlaceholdersRemain() { for (const Layer &layer : TestLayouts::build("us").layers) { for (const Row &row : layer.rows) { for (const KeyDef &key : row) QVERIFY(key.type != KeyType::Letters); } } } }; QTEST_GUILESS_MAIN(TestLayoutBuilder) #include "tst_layoutbuilder.moc"