Keep the user's shift; trust the text guess less

- 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>
This commit is contained in:
2026-10-15 10:13:27 +02:00
co-authored by Claude Opus 5.5
parent 076bc14e2f
commit d44aab7772
9 changed files with 130 additions and 10 deletions
+40
View File
@@ -150,6 +150,46 @@ private Q_SLOTS:
QCOMPARE(controller->shiftMode(), KeyboardController::ShiftMode::Once);
}
void fieldHintsCanOptOutOfCapitalization()
{
TextContext context = Field;
context.hints = TextContext::AutoCompletion; // states preferences, no capitals among them
controller->setContext(context);
QCOMPARE(controller->shiftMode(), KeyboardController::ShiftMode::Off);
context.hints |= TextContext::AutoCapitalization;
controller->setContext(context);
QCOMPARE(controller->shiftMode(), KeyboardController::ShiftMode::Once);
}
void cursorMovesForgetTheGuessedText()
{
controller->resetContext(Field); // reports no text: we only know what we typed
for (const char *c : {"h", "i", "."})
tap(makeKey(KeyType::Character, QString::fromLatin1(c)));
controller->moveCursor({-2, 0}); // now somewhere inside "Hi."
tap(makeKey(KeyType::Space));
QCOMPARE(controller->shiftMode(), KeyboardController::ShiftMode::Off);
}
void contextReportKeepsTappedShift()
{
tap(makeKey(KeyType::Shift));
controller->setContext(MidSentence); // unchanged text, re-reported
tap(makeKey(KeyType::Character, u"a"_s));
QCOMPARE(engine.output, u"A");
}
void resetForgetsTextBefore()
{
TextContext context = MidSentence;
context.textBeforeCursor = u"word "_s;
controller->setContext(context);
controller->setContext(Field); // input-method reset: no surrounding text
tap(makeKey(KeyType::Space));
QCOMPARE(engine.output, u" ");
QCOMPARE(engine.mismatchedReplacements, 0);
}
void doubleSpacePeriodCanBeTurnedOff()
{
controller->setOptions({.doubleSpacePeriod = false});