diff --git a/layouts/template.json b/layouts/template.json index 09aa80b..1d60dda 100644 --- a/layouts/template.json +++ b/layouts/template.json @@ -88,12 +88,12 @@ {"type": "keys", "row": 1} ], [ - {"type": "capslock", "label": "caps lock", "width": 1.75, "stretch": true}, + {"type": "capslock", "label": "caps lock", "width": 1.75}, {"type": "keys", "row": 2}, {"type": "enter", "width": 1.75, "stretch": true} ], [ - {"type": "shift", "width": 2.25, "stretch": true}, + {"type": "shift", "width": 2.25}, {"type": "keys", "row": 3}, {"type": "shift", "width": 2.25, "stretch": true} ], diff --git a/src/layout/LayoutBuilder.cpp b/src/layout/LayoutBuilder.cpp index 42347a8..cb2ba57 100644 --- a/src/layout/LayoutBuilder.cpp +++ b/src/layout/LayoutBuilder.cpp @@ -2,6 +2,8 @@ #include +#include + namespace { // Letters without a Unicode decomposition, and the key they belong under. @@ -53,8 +55,10 @@ QList letterKeys(const KeymapKeys &keymap, int row, const QStringList &f } // A full row: every typing key, the shifted symbol shown (and flickable) above. -QList rowKeys(const KeymapKeys &keymap, int row) +// `withLessGreater` tells whether the ISO key left of Z is among them. +QList rowKeys(const KeymapKeys &keymap, int row, bool *withLessGreater) { + *withLessGreater = false; QSet elsewhere; // LSGT often repeats a pair that exists elsewhere (US: < >) for (const auto &keys : keymap.rows) { for (const KeymapKey &key : keys) { @@ -67,6 +71,7 @@ QList rowKeys(const KeymapKeys &keymap, int row) for (const KeymapKey &source : keymap.rows.value(row)) { if (source.position == KeymapKey::Position::LessGreater && elsewhere.contains(source.lower)) continue; + *withLessGreater |= source.position == KeymapKey::Position::LessGreater; KeyDef key = characterKey(source); // Show (and flick for) a shifted level that isn't just the capital letter: ! on 1, " on sk รด. if (!source.deadUpper && source.upper != source.lower && source.upper != source.lower.toUpper()) @@ -82,8 +87,14 @@ Row expandPlaceholders(const Row &row, const KeymapKeys &keymap) for (const KeyDef &key : row) { if (key.type == KeyType::Letters) result += letterKeys(keymap, key.lettersRow, key.flicks); - else if (key.type == KeyType::Keys) - result += rowKeys(keymap, key.lettersRow); + else if (key.type == KeyType::Keys) { + bool withLessGreater = false; + const QList keys = rowKeys(keymap, key.lettersRow, &withLessGreater); + // As on ISO keyboards, that key takes its room from the one before it (left shift). + if (withLessGreater && !result.isEmpty()) + result.back().width = std::max(1.0, result.back().width - 1); + result += keys; + } else result.append(key); } diff --git a/tests/tst_layoutbuilder.cpp b/tests/tst_layoutbuilder.cpp index ddea0e0..b212924 100644 --- a/tests/tst_layoutbuilder.cpp +++ b/tests/tst_layoutbuilder.cpp @@ -110,6 +110,20 @@ private Q_SLOTS: 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);