- A tapped shift (on or off) survives the field re-reporting its context: it lasts until a character is typed, the hint changes or a field is focused - An input-method reset forgets the guessed text and pending dead key, so double-space can't delete a character the keyboard never saw - Fields that state typing preferences only get capitals if they ask - Trackpad moves in fields without surrounding text make the guess unknown; Backspace removes a whole grapheme cluster from it Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
158 lines
3.8 KiB
C++
158 lines
3.8 KiB
C++
#include "input/ShiftState.h"
|
|
|
|
#include <QTest>
|
|
|
|
using Mode = ShiftState::Mode;
|
|
|
|
class TestShiftState : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private Q_SLOTS:
|
|
void tapShiftsOneCharacter()
|
|
{
|
|
ShiftState shift;
|
|
shift.press(0);
|
|
shift.release();
|
|
QCOMPARE(shift.mode(), Mode::Once);
|
|
shift.characterTyped();
|
|
QCOMPARE(shift.mode(), Mode::Off);
|
|
}
|
|
|
|
void doubleTapLocks()
|
|
{
|
|
ShiftState shift;
|
|
shift.press(0);
|
|
shift.release();
|
|
shift.press(200);
|
|
shift.release();
|
|
QCOMPARE(shift.mode(), Mode::Locked);
|
|
shift.characterTyped();
|
|
shift.characterTyped();
|
|
QCOMPARE(shift.mode(), Mode::Locked);
|
|
}
|
|
|
|
void doubleTapLocksAfterAutomaticShift()
|
|
{
|
|
ShiftState shift;
|
|
shift.setAutomatic(true);
|
|
shift.press(0); // turns auto-shift off...
|
|
shift.release();
|
|
shift.press(200); // ...and the second tap locks
|
|
shift.release();
|
|
QCOMPARE(shift.mode(), Mode::Locked);
|
|
}
|
|
|
|
void tapAfterUnlockIsNotDoubleTap()
|
|
{
|
|
ShiftState shift;
|
|
shift.press(0);
|
|
shift.press(100); // locked
|
|
shift.press(1000); // unlocks
|
|
shift.press(1100);
|
|
QCOMPARE(shift.mode(), Mode::Once);
|
|
}
|
|
|
|
void typingBetweenTapsIsNotDoubleTap()
|
|
{
|
|
ShiftState shift;
|
|
shift.press(0);
|
|
shift.release();
|
|
shift.characterTyped();
|
|
shift.press(200);
|
|
QCOMPARE(shift.mode(), Mode::Once);
|
|
}
|
|
|
|
void tapUnlocks()
|
|
{
|
|
ShiftState shift;
|
|
shift.press(0);
|
|
shift.press(100);
|
|
shift.press(1000);
|
|
QCOMPARE(shift.mode(), Mode::Off);
|
|
}
|
|
|
|
void slowSecondTapTurnsOff()
|
|
{
|
|
ShiftState shift;
|
|
shift.press(0);
|
|
shift.release();
|
|
shift.press(ShiftState::DoubleTapMs + 1);
|
|
shift.release();
|
|
QCOMPARE(shift.mode(), Mode::Off);
|
|
}
|
|
|
|
void holdShiftsEveryCharacterUntilRelease()
|
|
{
|
|
ShiftState shift;
|
|
shift.press(0);
|
|
shift.characterTyped();
|
|
shift.characterTyped();
|
|
QCOMPARE(shift.mode(), Mode::Once);
|
|
shift.release();
|
|
QCOMPARE(shift.mode(), Mode::Off);
|
|
}
|
|
|
|
void automaticIgnoredWhileLocked()
|
|
{
|
|
ShiftState shift;
|
|
shift.press(0);
|
|
shift.press(100);
|
|
shift.release();
|
|
shift.setAutomatic(false);
|
|
QCOMPARE(shift.mode(), Mode::Locked);
|
|
}
|
|
|
|
void automaticCapitalizes()
|
|
{
|
|
ShiftState shift;
|
|
shift.setAutomatic(true);
|
|
QCOMPARE(shift.mode(), Mode::Once);
|
|
shift.characterTyped();
|
|
QCOMPARE(shift.mode(), Mode::Off);
|
|
}
|
|
|
|
void repeatedHintKeepsUserShift()
|
|
{
|
|
ShiftState shift;
|
|
shift.setAutomatic(false);
|
|
shift.press(0);
|
|
shift.release();
|
|
shift.setAutomatic(false); // the field re-reported
|
|
QCOMPARE(shift.mode(), Mode::Once);
|
|
}
|
|
|
|
void repeatedHintKeepsUserUnshift()
|
|
{
|
|
ShiftState shift;
|
|
shift.setAutomatic(true);
|
|
shift.press(0); // off at a sentence start
|
|
shift.release();
|
|
shift.setAutomatic(true);
|
|
QCOMPARE(shift.mode(), Mode::Off);
|
|
}
|
|
|
|
void changedHintOverridesUserShift()
|
|
{
|
|
ShiftState shift;
|
|
shift.setAutomatic(true);
|
|
shift.press(0);
|
|
shift.release();
|
|
shift.setAutomatic(false);
|
|
shift.setAutomatic(true); // e.g. backspaced to a sentence start
|
|
QCOMPARE(shift.mode(), Mode::Once);
|
|
}
|
|
|
|
void hintAppliesAgainAfterTyping()
|
|
{
|
|
ShiftState shift;
|
|
shift.setAutomatic(true);
|
|
shift.characterTyped(); // e.g. a space at a sentence start
|
|
shift.setAutomatic(true);
|
|
QCOMPARE(shift.mode(), Mode::Once);
|
|
}
|
|
};
|
|
|
|
QTEST_GUILESS_MAIN(TestShiftState)
|
|
#include "tst_shiftstate.moc"
|