Full keyboard: stagger the letter rows like a hardware keyboard
- The ISO key left of Z takes its room from left shift (2.25 → 1.25 + 1), so ISO layouts no longer make the shift row the widest - Caps lock and left shift keep their width; only right-hand keys stretch, so A no longer lines up with the key below it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,12 +88,12 @@
|
|||||||
{"type": "keys", "row": 1}
|
{"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": "keys", "row": 2},
|
||||||
{"type": "enter", "width": 1.75, "stretch": true}
|
{"type": "enter", "width": 1.75, "stretch": true}
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{"type": "shift", "width": 2.25, "stretch": true},
|
{"type": "shift", "width": 2.25},
|
||||||
{"type": "keys", "row": 3},
|
{"type": "keys", "row": 3},
|
||||||
{"type": "shift", "width": 2.25, "stretch": true}
|
{"type": "shift", "width": 2.25, "stretch": true}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Letters without a Unicode decomposition, and the key they belong under.
|
// Letters without a Unicode decomposition, and the key they belong under.
|
||||||
@@ -53,8 +55,10 @@ QList<KeyDef> letterKeys(const KeymapKeys &keymap, int row, const QStringList &f
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A full row: every typing key, the shifted symbol shown (and flickable) above.
|
// A full row: every typing key, the shifted symbol shown (and flickable) above.
|
||||||
QList<KeyDef> rowKeys(const KeymapKeys &keymap, int row)
|
// `withLessGreater` tells whether the ISO key left of Z is among them.
|
||||||
|
QList<KeyDef> rowKeys(const KeymapKeys &keymap, int row, bool *withLessGreater)
|
||||||
{
|
{
|
||||||
|
*withLessGreater = false;
|
||||||
QSet<QString> elsewhere; // LSGT often repeats a pair that exists elsewhere (US: < >)
|
QSet<QString> elsewhere; // LSGT often repeats a pair that exists elsewhere (US: < >)
|
||||||
for (const auto &keys : keymap.rows) {
|
for (const auto &keys : keymap.rows) {
|
||||||
for (const KeymapKey &key : keys) {
|
for (const KeymapKey &key : keys) {
|
||||||
@@ -67,6 +71,7 @@ QList<KeyDef> rowKeys(const KeymapKeys &keymap, int row)
|
|||||||
for (const KeymapKey &source : keymap.rows.value(row)) {
|
for (const KeymapKey &source : keymap.rows.value(row)) {
|
||||||
if (source.position == KeymapKey::Position::LessGreater && elsewhere.contains(source.lower))
|
if (source.position == KeymapKey::Position::LessGreater && elsewhere.contains(source.lower))
|
||||||
continue;
|
continue;
|
||||||
|
*withLessGreater |= source.position == KeymapKey::Position::LessGreater;
|
||||||
KeyDef key = characterKey(source);
|
KeyDef key = characterKey(source);
|
||||||
// Show (and flick for) a shifted level that isn't just the capital letter: ! on 1, " on sk ô.
|
// 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())
|
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) {
|
for (const KeyDef &key : row) {
|
||||||
if (key.type == KeyType::Letters)
|
if (key.type == KeyType::Letters)
|
||||||
result += letterKeys(keymap, key.lettersRow, key.flicks);
|
result += letterKeys(keymap, key.lettersRow, key.flicks);
|
||||||
else if (key.type == KeyType::Keys)
|
else if (key.type == KeyType::Keys) {
|
||||||
result += rowKeys(keymap, key.lettersRow);
|
bool withLessGreater = false;
|
||||||
|
const QList<KeyDef> 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
|
else
|
||||||
result.append(key);
|
result.append(key);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -110,6 +110,20 @@ private Q_SLOTS:
|
|||||||
QCOMPARE(letterKey(us, u"1"_s).shifted, 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<Row> &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()
|
void fullModeKeepsDeadKeysAndKeymapShift()
|
||||||
{
|
{
|
||||||
const Layout sk = TestLayouts::build("sk", KeyboardMode::Full);
|
const Layout sk = TestLayouts::build("sk", KeyboardMode::Full);
|
||||||
|
|||||||
Reference in New Issue
Block a user