Cancel keys still down when hold-keys mode flips
The surface cancels its fingers under the old rules before the switch, so a release no longer reaches the other mode (a stuck repeater or held modifier one way, a second copy of the character the other). Sticky modifiers, shift and dead keys start over. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -200,8 +200,15 @@ void KeyboardController::setContext(const TextContext &context)
|
|||||||
|
|
||||||
void KeyboardController::setOptions(const TypingOptions &options)
|
void KeyboardController::setOptions(const TypingOptions &options)
|
||||||
{
|
{
|
||||||
if (m_options.holdKeys && !options.holdKeys)
|
if (options.holdKeys != m_options.holdKeys) {
|
||||||
|
Q_EMIT holdKeysAboutToChange();
|
||||||
m_hardware.releaseAll();
|
m_hardware.releaseAll();
|
||||||
|
m_backspaceRepeater.stop();
|
||||||
|
m_keysymRepeater.stop();
|
||||||
|
m_deadKeys.cancel();
|
||||||
|
m_modifiers.clear();
|
||||||
|
m_shift = {};
|
||||||
|
}
|
||||||
m_options = options;
|
m_options = options;
|
||||||
m_model.setShiftLevel(shiftLevel());
|
m_model.setShiftLevel(shiftLevel());
|
||||||
Q_EMIT shiftChanged();
|
Q_EMIT shiftChanged();
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ Q_SIGNALS:
|
|||||||
void modifiersChanged();
|
void modifiersChanged();
|
||||||
void dismissRequested();
|
void dismissRequested();
|
||||||
void nextLayoutRequested(); // the globe key: switching is the system's job
|
void nextLayoutRequested(); // the globe key: switching is the system's job
|
||||||
|
// Hold-keys mode is about to flip: keys still down must be cancelled now,
|
||||||
|
// under the rules they were pressed with.
|
||||||
|
void holdKeysAboutToChange();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void typeCharacter(const KeyDef &key, KeyOutput output, const QString &alternate);
|
void typeCharacter(const KeyDef &key, KeyOutput output, const QString &alternate);
|
||||||
|
|||||||
@@ -44,7 +44,11 @@ void KeyboardSurface::setController(KeyboardController *controller)
|
|||||||
if (controller == m_controller)
|
if (controller == m_controller)
|
||||||
return;
|
return;
|
||||||
cancelAll();
|
cancelAll();
|
||||||
|
if (m_controller)
|
||||||
|
disconnect(m_controller, nullptr, this, nullptr);
|
||||||
m_controller = controller;
|
m_controller = controller;
|
||||||
|
if (m_controller)
|
||||||
|
connect(m_controller, &KeyboardController::holdKeysAboutToChange, this, &KeyboardSurface::cancelAll);
|
||||||
Q_EMIT controllerChanged();
|
Q_EMIT controllerChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,6 +169,22 @@ private Q_SLOTS:
|
|||||||
controller->setOptions({});
|
controller->setOptions({});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void switchingHoldKeysMidPressCancelsTheKey()
|
||||||
|
{
|
||||||
|
const QPoint a = keyCenter(u"a"_s);
|
||||||
|
QTest::touchEvent(&window, touchscreen).press(0, a);
|
||||||
|
controller->setOptions({.holdKeys = true});
|
||||||
|
QTest::touchEvent(&window, touchscreen).release(0, a);
|
||||||
|
QVERIFY(engine.output.isEmpty());
|
||||||
|
QVERIFY(engine.keyEvents.isEmpty());
|
||||||
|
|
||||||
|
QTest::touchEvent(&window, touchscreen).press(0, a);
|
||||||
|
controller->setOptions({});
|
||||||
|
QTest::touchEvent(&window, touchscreen).release(0, a);
|
||||||
|
QVERIFY(engine.held.isEmpty());
|
||||||
|
QVERIFY(engine.output.isEmpty()); // not typed a second time as a tap
|
||||||
|
}
|
||||||
|
|
||||||
void slideFromNumbersKeyTypesAndReturns()
|
void slideFromNumbersKeyTypesAndReturns()
|
||||||
{
|
{
|
||||||
const QPoint layerKey = keyCenter(u".?123"_s, u"layer"_s);
|
const QPoint layerKey = keyCenter(u".?123"_s, u"layer"_s);
|
||||||
|
|||||||
Reference in New Issue
Block a user