Fix reentrancy regression in QShortcutMap after c7e5e1d9e
When closing a popup dialog using a shortcut, when the popup was originally opened using a shortcut, the closing-shortcut would interfere with the state of the first shortcut, and we ended up sending a key event for the original shortcut. Task-number: QTBUG-50360 Change-Id: I62e5ddb9ca43b28519ede629775bc0d7598dccc4 Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
This commit is contained in:
parent
70092c9a47
commit
af45b352d7
@ -336,12 +336,16 @@ bool QShortcutMap::tryShortcut(QKeyEvent *e)
|
|||||||
// For a partial match we don't know yet if we will handle the shortcut
|
// For a partial match we don't know yet if we will handle the shortcut
|
||||||
// but we need to say we did, so that we get the follow-up key-presses.
|
// but we need to say we did, so that we get the follow-up key-presses.
|
||||||
return true;
|
return true;
|
||||||
case QKeySequence::ExactMatch:
|
case QKeySequence::ExactMatch: {
|
||||||
|
// Save number of identical matches before dispatching
|
||||||
|
// to keep QShortcutMap and tryShortcut reentrant.
|
||||||
|
const int identicalMatches = d->identicals.count();
|
||||||
resetState();
|
resetState();
|
||||||
dispatchEvent(e);
|
dispatchEvent(e);
|
||||||
// If there are no identicals we've only found disabled shortcuts, and
|
// If there are no identicals we've only found disabled shortcuts, and
|
||||||
// shouldn't say that we handled the event.
|
// shouldn't say that we handled the event.
|
||||||
return d->identicals.count() > 0;
|
return identicalMatches > 0;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,8 @@ public:
|
|||||||
TriggerSlot4,
|
TriggerSlot4,
|
||||||
TriggerSlot5,
|
TriggerSlot5,
|
||||||
TriggerSlot6,
|
TriggerSlot6,
|
||||||
TriggerSlot7
|
TriggerSlot7,
|
||||||
|
SendKeyEvent
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Result {
|
enum Result {
|
||||||
@ -84,6 +85,7 @@ public:
|
|||||||
Slot5Triggered,
|
Slot5Triggered,
|
||||||
Slot6Triggered,
|
Slot6Triggered,
|
||||||
Slot7Triggered,
|
Slot7Triggered,
|
||||||
|
SentKeyEvent,
|
||||||
Ambiguous
|
Ambiguous
|
||||||
} currentResult;
|
} currentResult;
|
||||||
|
|
||||||
@ -104,6 +106,7 @@ public slots:
|
|||||||
void ambigSlot7() { currentResult = Ambiguous; ambigResult = Slot7Triggered; }
|
void ambigSlot7() { currentResult = Ambiguous; ambigResult = Slot7Triggered; }
|
||||||
void statusMessage( const QString& message ) { sbText = message; }
|
void statusMessage( const QString& message ) { sbText = message; }
|
||||||
void shortcutDestroyed(QObject* obj);
|
void shortcutDestroyed(QObject* obj);
|
||||||
|
void sendKeyEvent() { sendKeyEvents(edit, Qt::CTRL + Qt::Key_B, 0); currentResult = SentKeyEvent; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
@ -981,6 +984,19 @@ void tst_QShortcut::keypressConsumption()
|
|||||||
QVERIFY(edit->toPlainText().endsWith("<Ctrl+I>a"));
|
QVERIFY(edit->toPlainText().endsWith("<Ctrl+I>a"));
|
||||||
|
|
||||||
clearAllShortcuts();
|
clearAllShortcuts();
|
||||||
|
edit->clear();
|
||||||
|
QCOMPARE(edit->toPlainText().size(), 0);
|
||||||
|
|
||||||
|
setupShortcut(edit, "first", SendKeyEvent, "Ctrl+A");
|
||||||
|
|
||||||
|
// Verify reentrancy when a non-shortcut is triggered as part
|
||||||
|
// of shortcut processing.
|
||||||
|
currentResult = NoResult;
|
||||||
|
ambigResult = NoResult;
|
||||||
|
sendKeyEvents(edit, Qt::CTRL + Qt::Key_A, 0);
|
||||||
|
QCOMPARE(currentResult, SentKeyEvent);
|
||||||
|
QCOMPARE(ambigResult, NoResult);
|
||||||
|
QCOMPARE(edit->toPlainText(), QString(QString("<Ctrl+B>")));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------
|
// ------------------------------------------------------------------
|
||||||
@ -1182,9 +1198,12 @@ QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int t
|
|||||||
normal = SLOT(slotTrig7());
|
normal = SLOT(slotTrig7());
|
||||||
ambig = SLOT(ambigSlot7());
|
ambig = SLOT(ambigSlot7());
|
||||||
break;
|
break;
|
||||||
|
case SendKeyEvent:
|
||||||
|
normal = SLOT(sendKeyEvent());
|
||||||
}
|
}
|
||||||
connect(cut, SIGNAL(activated()), this, normal);
|
connect(cut, SIGNAL(activated()), this, normal);
|
||||||
connect(cut, SIGNAL(activatedAmbiguously()), this, ambig);
|
if (ambig)
|
||||||
|
connect(cut, SIGNAL(activatedAmbiguously()), this, ambig);
|
||||||
connect(cut, SIGNAL(destroyed(QObject*)), this, SLOT(shortcutDestroyed(QObject*)));
|
connect(cut, SIGNAL(destroyed(QObject*)), this, SLOT(shortcutDestroyed(QObject*)));
|
||||||
shortcuts.append(cut);
|
shortcuts.append(cut);
|
||||||
return cut;
|
return cut;
|
||||||
|
Loading…
Reference in New Issue
Block a user