#include "layout/KeyGeometry.h" #include using namespace Qt::StringLiterals; namespace { KeyDef key(qreal width = 1.0, KeyType type = KeyType::Character) { KeyDef k; k.type = type; k.label = u"x"_s; k.width = width; return k; } } // namespace class TestKeyGeometry : public QObject { Q_OBJECT private Q_SLOTS: void fillsWidthAndHeight() { const Layer layer{u"l"_s, {{key(), key()}, {key(2)}}}; const KeyboardMetrics metrics{.padding = 10, .gap = 10}; const auto rects = computeKeyRects(layer, {210, 110}, metrics); QCOMPARE(rects.size(), 3); QCOMPARE(rects[0], QRectF(10, 10, 90, 40)); QCOMPARE(rects[1], QRectF(110, 10, 90, 40)); QCOMPARE(rects[2], QRectF(10, 60, 190, 40)); // a 2-unit key spans the gap } void spacersShiftFollowingKeys() { const Layer layer{u"l"_s, {{key(), key(), key()}, {key(0.5, KeyType::Spacer), key(), key(1.5)}}}; const auto rects = computeKeyRects(layer, {300, 100}, {.padding = 0, .gap = 0}); QCOMPARE(rects[4].left(), 50.0); QCOMPARE(rects[5].right(), 300.0); } void shorterRowsAreCentered() { const Layer layer{u"l"_s, {{key(), key(), key(), key()}, {key(), key()}}}; const auto rects = computeKeyRects(layer, {400, 100}, {.padding = 0, .gap = 0}); QCOMPARE(rects[4].left(), 100.0); QCOMPARE(rects[5].right(), 300.0); } void stretchKeysFillTheRow() { KeyDef wide = key(); wide.stretch = true; const Layer layer{u"l"_s, {{key(), key(), key(), key()}, {key(), wide}}}; const auto rects = computeKeyRects(layer, {400, 100}, {.padding = 0, .gap = 0}); QCOMPARE(rects[4].left(), 0.0); QCOMPARE(rects[5].width(), 300.0); } void blocksShareUnitAndSitAtTheBottom() { const Block tall{{{key(), key()}, {key(), key()}}}; const Block shortBlock{{{key()}}}; const auto rects = computeKeyRects({tall, shortBlock}, {400, 100}, {.padding = 0, .gap = 0, .blockGap = 100}); // 3 units in 300 px: 100 each. QCOMPARE(rects[1].right(), 200.0); QCOMPARE(rects[4], QRectF(300, 50, 100, 50)); } void fillingBlockSpansTheFullHeight() { const Block tall{{{key()}, {key()}, {key()}, {key()}}}; const Block filling{{{key()}, {key()}}, true}; const auto rects = computeKeyRects({tall, filling}, {200, 100}, {.padding = 0, .gap = 0, .blockGap = 0}); QCOMPARE(rects[0].height(), 25.0); QCOMPARE(rects[4], QRectF(100, 0, 100, 50)); QCOMPARE(rects[5], QRectF(100, 50, 100, 50)); // A filling block taller than the rest doesn't shrink the shared rows. QCOMPARE(totalRows({tall, filling}), 4); QCOMPARE(totalRows({filling}), 2); } void reservedRoomStretchesTheRowsAfterTheFixedOnes() { Block reserved{{{key()}, {key()}, {key()}}}; reserved.minUnits = 2; reserved.minRows = 5; reserved.fixedRows = 1; const Block side{{{key()}}}; const auto rects = computeKeyRects({reserved, side}, {300, 100}, {.padding = 0, .gap = 0, .blockGap = 0}); QCOMPARE(totalRows({reserved, side}), 5); QCOMPARE(rects[0], QRectF(50, 0, 100, 20)); // fixed row keeps the shared height, centered in 2 units QCOMPARE(rects[1], QRectF(50, 20, 100, 40)); QCOMPARE(rects[2], QRectF(50, 60, 100, 40)); QCOMPARE(rects[3], QRectF(200, 80, 100, 20)); // the side block doesn't move } }; QTEST_GUILESS_MAIN(TestKeyGeometry) #include "tst_keygeometry.moc"