require a clean release for double-tap modifier detection (T-409)
Typing Shift+; opened quick-open instead of a colon. Two flaws in the T-341 detector: it counted a tap on the Shift keydown (so a chorded press could complete the gesture before the chord key arrived), and it relied on the chorded key bubbling to the root KeyboardListener to break the gesture — but a focused editor or text field consumes that event, so the tracker never saw it. The tracker now models press/release: a tap is a press with no other key going down while the modifier is held, and the gesture fires on the second clean release. The root shell feeds it from a HardwareKeyboard handler, which observes every event before focus dispatch regardless of who consumes it, and treats a modifier pressed while a non-modifier is already held as a chord. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -354,6 +354,44 @@ void main() {
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('double-tapped bare Shift opens quick-open (T-341)', (tester) async {
|
||||
await pumpApp(tester);
|
||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.shiftLeft);
|
||||
await tester.sendKeyUpEvent(LogicalKeyboardKey.shiftLeft);
|
||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.shiftLeft);
|
||||
await tester.sendKeyUpEvent(LogicalKeyboardKey.shiftLeft);
|
||||
await tester.pump();
|
||||
expect(f.services.quickOpen.isOpen, isTrue);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('typing colons (Shift+;) never triggers quick-open (T-409)', (tester) async {
|
||||
await pumpApp(tester);
|
||||
// Two rapid `:` keystrokes — the chorded `;` dirties each Shift press.
|
||||
for (var i = 0; i < 2; i++) {
|
||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.shiftLeft);
|
||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.semicolon);
|
||||
await tester.sendKeyUpEvent(LogicalKeyboardKey.semicolon);
|
||||
await tester.sendKeyUpEvent(LogicalKeyboardKey.shiftLeft);
|
||||
}
|
||||
await tester.pump();
|
||||
expect(f.services.quickOpen.isOpen, isFalse);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('a bare Shift tap followed by a Shift chord does not fire (T-409)', (tester) async {
|
||||
await pumpApp(tester);
|
||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.shiftLeft);
|
||||
await tester.sendKeyUpEvent(LogicalKeyboardKey.shiftLeft); // clean tap arms
|
||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.shiftLeft);
|
||||
await tester.sendKeyDownEvent(LogicalKeyboardKey.semicolon); // chord — old code fired on the down
|
||||
await tester.sendKeyUpEvent(LogicalKeyboardKey.semicolon);
|
||||
await tester.sendKeyUpEvent(LogicalKeyboardKey.shiftLeft);
|
||||
await tester.pump();
|
||||
expect(f.services.quickOpen.isOpen, isFalse);
|
||||
expect(tester.takeException(), isNull);
|
||||
});
|
||||
|
||||
testWidgets('file.closeWorkspace command closes the active project', (tester) async {
|
||||
final repo = Directory.current.path;
|
||||
await tester.runAsync(() async => f.services.project.open(repo));
|
||||
|
||||
Reference in New Issue
Block a user