Unverified Commit efe76a53 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Update key examples to use `Focus` widgets instead of `RawKeyboardListener` (#101537)

This updates the examples for PhysicalKeyboardKey and LogicalKeyboardKey to use Focus widgets that handle the keys instead of using RawKeyboardListener, since that usually leads people down the wrong path. Updated the See Also and added tests as well. Also exposed the `physicalKey` attribute for `tester.sendKeyEvent`.
parent cae740b9
...@@ -8,61 +8,59 @@ import 'package:flutter/foundation.dart'; ...@@ -8,61 +8,59 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
void main() => runApp(const MyApp()); void main() => runApp(const KeyExampleApp());
class MyApp extends StatelessWidget { class KeyExampleApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key); const KeyExampleApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
title: _title,
home: Scaffold( home: Scaffold(
appBar: AppBar(title: const Text(_title)), appBar: AppBar(title: const Text('Key Handling Example')),
body: const MyStatefulWidget(), body: const MyKeyExample(),
), ),
); );
} }
} }
class MyStatefulWidget extends StatefulWidget { class MyKeyExample extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key); const MyKeyExample({Key? key}) : super(key: key);
@override @override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState(); State<MyKeyExample> createState() => _MyKeyExampleState();
} }
class _MyStatefulWidgetState extends State<MyStatefulWidget> { class _MyKeyExampleState extends State<MyKeyExample> {
// The node used to request the keyboard focus. // The node used to request the keyboard focus.
final FocusNode _focusNode = FocusNode(); final FocusNode _focusNode = FocusNode();
// The message to display. // The message to display.
String? _message; String? _message;
// Focus nodes need to be disposed. // Focus nodes need to be disposed.
@override @override
void dispose() { void dispose() {
_focusNode.dispose(); _focusNode.dispose();
super.dispose(); super.dispose();
} }
// Handles the key events from the RawKeyboardListener and update the // Handles the key events from the Focus widget and updates the
// _message. // _message.
void _handleKeyEvent(RawKeyEvent event) { KeyEventResult _handleKeyEvent(FocusNode node, RawKeyEvent event) {
setState(() { setState(() {
if (event.logicalKey == LogicalKeyboardKey.keyQ) { if (event.logicalKey == LogicalKeyboardKey.keyQ) {
_message = 'Pressed the "Q" key!'; _message = 'Pressed the "Q" key!';
} else { } else {
if (kReleaseMode) { if (kReleaseMode) {
_message = _message = 'Not a Q: Pressed 0x${event.logicalKey.keyId.toRadixString(16)}';
'Not a Q: Pressed 0x${event.logicalKey.keyId.toRadixString(16)}';
} else { } else {
// The debugName will only print useful information in debug mode. // As the name implies, the debugName will only print useful
// information in debug mode.
_message = 'Not a Q: Pressed ${event.logicalKey.debugName}'; _message = 'Not a Q: Pressed ${event.logicalKey.debugName}';
} }
} }
}); });
return event.logicalKey == LogicalKeyboardKey.keyQ ? KeyEventResult.handled : KeyEventResult.ignored;
} }
@override @override
...@@ -73,7 +71,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> { ...@@ -73,7 +71,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
alignment: Alignment.center, alignment: Alignment.center,
child: DefaultTextStyle( child: DefaultTextStyle(
style: textTheme.headline4!, style: textTheme.headline4!,
child: RawKeyboardListener( child: Focus(
focusNode: _focusNode, focusNode: _focusNode,
onKey: _handleKeyEvent, onKey: _handleKeyEvent,
child: AnimatedBuilder( child: AnimatedBuilder(
...@@ -84,7 +82,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> { ...@@ -84,7 +82,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
onTap: () { onTap: () {
FocusScope.of(context).requestFocus(_focusNode); FocusScope.of(context).requestFocus(_focusNode);
}, },
child: const Text('Tap to focus'), child: const Text('Click to focus'),
); );
} }
return Text(_message ?? 'Press a key'); return Text(_message ?? 'Press a key');
......
...@@ -4,36 +4,34 @@ ...@@ -4,36 +4,34 @@
// Flutter code sample for PhysicalKeyboardKey // Flutter code sample for PhysicalKeyboardKey
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
void main() => runApp(const MyApp()); void main() => runApp(const KeyExampleApp());
class MyApp extends StatelessWidget { class KeyExampleApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key); const KeyExampleApp({Key? key}) : super(key: key);
static const String _title = 'Flutter Code Sample';
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MaterialApp( return MaterialApp(
title: _title,
home: Scaffold( home: Scaffold(
appBar: AppBar(title: const Text(_title)), appBar: AppBar(title: const Text('PhysicalKeyboardKey Example')),
body: const MyStatefulWidget(), body: const MyPhysicalKeyExample(),
), ),
); );
} }
} }
class MyStatefulWidget extends StatefulWidget { class MyPhysicalKeyExample extends StatefulWidget {
const MyStatefulWidget({Key? key}) : super(key: key); const MyPhysicalKeyExample({Key? key}) : super(key: key);
@override @override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState(); State<MyPhysicalKeyExample> createState() => _MyPhysicalKeyExampleState();
} }
class _MyStatefulWidgetState extends State<MyStatefulWidget> { class _MyPhysicalKeyExampleState extends State<MyPhysicalKeyExample> {
// The node used to request the keyboard focus. // The node used to request the keyboard focus.
final FocusNode _focusNode = FocusNode(); final FocusNode _focusNode = FocusNode();
// The message to display. // The message to display.
...@@ -48,14 +46,21 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> { ...@@ -48,14 +46,21 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
// Handles the key events from the RawKeyboardListener and update the // Handles the key events from the RawKeyboardListener and update the
// _message. // _message.
void _handleKeyEvent(RawKeyEvent event) { KeyEventResult _handleKeyEvent(FocusNode node, RawKeyEvent event) {
setState(() { setState(() {
if (event.physicalKey == PhysicalKeyboardKey.keyA) { if (event.physicalKey == PhysicalKeyboardKey.keyA) {
_message = 'Pressed the key next to CAPS LOCK!'; _message = 'Pressed the key next to CAPS LOCK!';
} else { } else {
_message = 'Wrong key.'; if (kReleaseMode) {
_message = 'Not the key next to CAPS LOCK: Pressed 0x${event.physicalKey.usbHidUsage.toRadixString(16)}';
} else {
// As the name implies, the debugName will only print useful
// information in debug mode.
_message = 'Not the key next to CAPS LOCK: Pressed ${event.physicalKey.debugName}';
}
} }
}); });
return event.physicalKey == PhysicalKeyboardKey.keyA ? KeyEventResult.handled : KeyEventResult.ignored;
} }
@override @override
...@@ -66,7 +71,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> { ...@@ -66,7 +71,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
alignment: Alignment.center, alignment: Alignment.center,
child: DefaultTextStyle( child: DefaultTextStyle(
style: textTheme.headline4!, style: textTheme.headline4!,
child: RawKeyboardListener( child: Focus(
focusNode: _focusNode, focusNode: _focusNode,
onKey: _handleKeyEvent, onKey: _handleKeyEvent,
child: AnimatedBuilder( child: AnimatedBuilder(
...@@ -77,7 +82,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> { ...@@ -77,7 +82,7 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
onTap: () { onTap: () {
FocusScope.of(context).requestFocus(_focusNode); FocusScope.of(context).requestFocus(_focusNode);
}, },
child: const Text('Tap to focus'), child: const Text('Click to focus'),
); );
} }
return Text(_message ?? 'Press a key'); return Text(_message ?? 'Press a key');
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/services.dart';
import 'package:flutter_api_samples/services/keyboard_key/logical_keyboard_key.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Responds to key', (WidgetTester tester) async {
await tester.pumpWidget(
const example.KeyExampleApp(),
);
await tester.tap(find.text('Click to focus'));
await tester.pumpAndSettle();
expect(find.text('Press a key'), findsOneWidget);
await tester.sendKeyEvent(LogicalKeyboardKey.keyQ);
await tester.pumpAndSettle();
expect(find.text('Pressed the "Q" key!'), findsOneWidget);
await tester.sendKeyEvent(LogicalKeyboardKey.keyB);
await tester.pumpAndSettle();
expect(find.text('Not a Q: Pressed Key B'), findsOneWidget);
});
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/services.dart';
import 'package:flutter_api_samples/services/keyboard_key/physical_keyboard_key.0.dart' as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Responds to key', (WidgetTester tester) async {
await tester.pumpWidget(
const example.KeyExampleApp(),
);
await tester.tap(find.text('Click to focus'));
await tester.pumpAndSettle();
expect(find.text('Press a key'), findsOneWidget);
await tester.sendKeyEvent(LogicalKeyboardKey.keyQ, physicalKey: PhysicalKeyboardKey.keyA);
await tester.pumpAndSettle();
expect(find.text('Pressed the key next to CAPS LOCK!'), findsOneWidget);
await tester.sendKeyEvent(LogicalKeyboardKey.keyB, physicalKey: PhysicalKeyboardKey.keyB);
await tester.pumpAndSettle();
expect(find.text('Not the key next to CAPS LOCK: Pressed Key B'), findsOneWidget);
});
}
...@@ -48,7 +48,7 @@ abstract class KeyboardKey with Diagnosticable { ...@@ -48,7 +48,7 @@ abstract class KeyboardKey with Diagnosticable {
/// ///
/// {@tool dartpad} /// {@tool dartpad}
/// This example shows how to detect if the user has selected the logical "Q" /// This example shows how to detect if the user has selected the logical "Q"
/// key. /// key and handle the key if they have.
/// ///
/// ** See code in examples/api/lib/services/keyboard_key/logical_keyboard_key.0.dart ** /// ** See code in examples/api/lib/services/keyboard_key/logical_keyboard_key.0.dart **
/// {@end-tool} /// {@end-tool}
...@@ -56,8 +56,9 @@ abstract class KeyboardKey with Diagnosticable { ...@@ -56,8 +56,9 @@ abstract class KeyboardKey with Diagnosticable {
/// ///
/// * [RawKeyEvent], the keyboard event object received by widgets that listen /// * [RawKeyEvent], the keyboard event object received by widgets that listen
/// to keyboard events. /// to keyboard events.
/// * [RawKeyboardListener], a widget used to listen to and supply handlers for /// * [Focus.onKey], the handler on a widget that lets you handle key events.
/// keyboard events. /// * [RawKeyboardListener], a widget used to listen to keyboard events (but
/// not handle them).
@immutable @immutable
class LogicalKeyboardKey extends KeyboardKey { class LogicalKeyboardKey extends KeyboardKey {
/// Creates a new LogicalKeyboardKey object for a key ID. /// Creates a new LogicalKeyboardKey object for a key ID.
...@@ -3503,8 +3504,9 @@ class LogicalKeyboardKey extends KeyboardKey { ...@@ -3503,8 +3504,9 @@ class LogicalKeyboardKey extends KeyboardKey {
/// ///
/// * [RawKeyEvent], the keyboard event object received by widgets that listen /// * [RawKeyEvent], the keyboard event object received by widgets that listen
/// to keyboard events. /// to keyboard events.
/// * [RawKeyboardListener], a widget used to listen to and supply handlers for /// * [Focus.onKey], the handler on a widget that lets you handle key events.
/// keyboard events. /// * [RawKeyboardListener], a widget used to listen to keyboard events (but
/// not handle them).
@immutable @immutable
class PhysicalKeyboardKey extends KeyboardKey { class PhysicalKeyboardKey extends KeyboardKey {
/// Creates a new PhysicalKeyboardKey object for a USB HID usage. /// Creates a new PhysicalKeyboardKey object for a USB HID usage.
......
...@@ -982,6 +982,14 @@ abstract class WidgetController { ...@@ -982,6 +982,14 @@ abstract class WidgetController {
/// else. Must not be null. Some platforms (e.g. Windows, iOS) are not yet /// else. Must not be null. Some platforms (e.g. Windows, iOS) are not yet
/// supported. /// supported.
/// ///
/// Specify the `physicalKey` for the event to override what is included in
/// the simulated event. If not specified, it uses a default from the US
/// keyboard layout for the corresponding logical `key`.
///
/// Specify the `character` for the event to override what is included in the
/// simulated event. If not specified, it uses a default derived from the
/// logical `key`.
///
/// Whether the event is sent through [RawKeyEvent] or [KeyEvent] is /// Whether the event is sent through [RawKeyEvent] or [KeyEvent] is
/// controlled by [debugKeyEventSimulatorTransitModeOverride]. /// controlled by [debugKeyEventSimulatorTransitModeOverride].
/// ///
...@@ -997,11 +1005,16 @@ abstract class WidgetController { ...@@ -997,11 +1005,16 @@ abstract class WidgetController {
/// ///
/// - [sendKeyDownEvent] to simulate only a key down event. /// - [sendKeyDownEvent] to simulate only a key down event.
/// - [sendKeyUpEvent] to simulate only a key up event. /// - [sendKeyUpEvent] to simulate only a key up event.
Future<bool> sendKeyEvent(LogicalKeyboardKey key, { String platform = _defaultPlatform }) async { Future<bool> sendKeyEvent(
LogicalKeyboardKey key, {
String platform = _defaultPlatform,
String? character,
PhysicalKeyboardKey? physicalKey
}) async {
assert(platform != null); assert(platform != null);
final bool handled = await simulateKeyDownEvent(key, platform: platform); final bool handled = await simulateKeyDownEvent(key, platform: platform, character: character, physicalKey: physicalKey);
// Internally wrapped in async guard. // Internally wrapped in async guard.
await simulateKeyUpEvent(key, platform: platform); await simulateKeyUpEvent(key, platform: platform, physicalKey: physicalKey);
return handled; return handled;
} }
...@@ -1016,6 +1029,14 @@ abstract class WidgetController { ...@@ -1016,6 +1029,14 @@ abstract class WidgetController {
/// else. Must not be null. Some platforms (e.g. Windows, iOS) are not yet /// else. Must not be null. Some platforms (e.g. Windows, iOS) are not yet
/// supported. /// supported.
/// ///
/// Specify the `physicalKey` for the event to override what is included in
/// the simulated event. If not specified, it uses a default from the US
/// keyboard layout for the corresponding logical `key`.
///
/// Specify the `character` for the event to override what is included in the
/// simulated event. If not specified, it uses a default derived from the
/// logical `key`.
///
/// Whether the event is sent through [RawKeyEvent] or [KeyEvent] is /// Whether the event is sent through [RawKeyEvent] or [KeyEvent] is
/// controlled by [debugKeyEventSimulatorTransitModeOverride]. /// controlled by [debugKeyEventSimulatorTransitModeOverride].
/// ///
...@@ -1028,10 +1049,15 @@ abstract class WidgetController { ...@@ -1028,10 +1049,15 @@ abstract class WidgetController {
/// - [sendKeyUpEvent] and [sendKeyRepeatEvent] to simulate the corresponding /// - [sendKeyUpEvent] and [sendKeyRepeatEvent] to simulate the corresponding
/// key up and repeat event. /// key up and repeat event.
/// - [sendKeyEvent] to simulate both the key up and key down in the same call. /// - [sendKeyEvent] to simulate both the key up and key down in the same call.
Future<bool> sendKeyDownEvent(LogicalKeyboardKey key, { String? character, String platform = _defaultPlatform }) async { Future<bool> sendKeyDownEvent(
LogicalKeyboardKey key, {
String platform = _defaultPlatform,
String? character,
PhysicalKeyboardKey? physicalKey
}) async {
assert(platform != null); assert(platform != null);
// Internally wrapped in async guard. // Internally wrapped in async guard.
return simulateKeyDownEvent(key, character: character, platform: platform); return simulateKeyDownEvent(key, platform: platform, character: character, physicalKey: physicalKey);
} }
/// Simulates sending a physical key up event through the system channel. /// Simulates sending a physical key up event through the system channel.
...@@ -1044,6 +1070,10 @@ abstract class WidgetController { ...@@ -1044,6 +1070,10 @@ abstract class WidgetController {
/// that type of system. Defaults to "web" on web, and "android" everywhere /// that type of system. Defaults to "web" on web, and "android" everywhere
/// else. May not be null. /// else. May not be null.
/// ///
/// Specify the `physicalKey` for the event to override what is included in
/// the simulated event. If not specified, it uses a default from the US
/// keyboard layout for the corresponding logical `key`.
///
/// Whether the event is sent through [RawKeyEvent] or [KeyEvent] is /// Whether the event is sent through [RawKeyEvent] or [KeyEvent] is
/// controlled by [debugKeyEventSimulatorTransitModeOverride]. /// controlled by [debugKeyEventSimulatorTransitModeOverride].
/// ///
...@@ -1054,13 +1084,17 @@ abstract class WidgetController { ...@@ -1054,13 +1084,17 @@ abstract class WidgetController {
/// - [sendKeyDownEvent] and [sendKeyRepeatEvent] to simulate the /// - [sendKeyDownEvent] and [sendKeyRepeatEvent] to simulate the
/// corresponding key down and repeat event. /// corresponding key down and repeat event.
/// - [sendKeyEvent] to simulate both the key up and key down in the same call. /// - [sendKeyEvent] to simulate both the key up and key down in the same call.
Future<bool> sendKeyUpEvent(LogicalKeyboardKey key, { String platform = _defaultPlatform }) async { Future<bool> sendKeyUpEvent(
LogicalKeyboardKey key, {
String platform = _defaultPlatform,
PhysicalKeyboardKey? physicalKey
}) async {
assert(platform != null); assert(platform != null);
// Internally wrapped in async guard. // Internally wrapped in async guard.
return simulateKeyUpEvent(key, platform: platform); return simulateKeyUpEvent(key, platform: platform, physicalKey: physicalKey);
} }
/// Simulates sending a physical key repeat event. /// Simulates sending a key repeat event from a physical keyboard.
/// ///
/// This only simulates key repeat events coming from a physical keyboard, not /// This only simulates key repeat events coming from a physical keyboard, not
/// from a soft keyboard. /// from a soft keyboard.
...@@ -1070,6 +1104,14 @@ abstract class WidgetController { ...@@ -1070,6 +1104,14 @@ abstract class WidgetController {
/// of system. Defaults to "web" on web, and "android" everywhere else. Must not be /// of system. Defaults to "web" on web, and "android" everywhere else. Must not be
/// null. Some platforms (e.g. Windows, iOS) are not yet supported. /// null. Some platforms (e.g. Windows, iOS) are not yet supported.
/// ///
/// Specify the `physicalKey` for the event to override what is included in
/// the simulated event. If not specified, it uses a default from the US
/// keyboard layout for the corresponding logical `key`.
///
/// Specify the `character` for the event to override what is included in the
/// simulated event. If not specified, it uses a default derived from the
/// logical `key`.
///
/// Whether the event is sent through [RawKeyEvent] or [KeyEvent] is /// Whether the event is sent through [RawKeyEvent] or [KeyEvent] is
/// controlled by [debugKeyEventSimulatorTransitModeOverride]. If through [RawKeyEvent], /// controlled by [debugKeyEventSimulatorTransitModeOverride]. If through [RawKeyEvent],
/// this method is equivalent to [sendKeyDownEvent]. /// this method is equivalent to [sendKeyDownEvent].
...@@ -1083,10 +1125,15 @@ abstract class WidgetController { ...@@ -1083,10 +1125,15 @@ abstract class WidgetController {
/// - [sendKeyDownEvent] and [sendKeyUpEvent] to simulate the corresponding /// - [sendKeyDownEvent] and [sendKeyUpEvent] to simulate the corresponding
/// key down and up event. /// key down and up event.
/// - [sendKeyEvent] to simulate both the key up and key down in the same call. /// - [sendKeyEvent] to simulate both the key up and key down in the same call.
Future<bool> sendKeyRepeatEvent(LogicalKeyboardKey key, { String? character, String platform = _defaultPlatform }) async { Future<bool> sendKeyRepeatEvent(
LogicalKeyboardKey key, {
String platform = _defaultPlatform,
String? character,
PhysicalKeyboardKey? physicalKey
}) async {
assert(platform != null); assert(platform != null);
// Internally wrapped in async guard. // Internally wrapped in async guard.
return simulateKeyRepeatEvent(key, character: character, platform: platform); return simulateKeyRepeatEvent(key, platform: platform, character: character, physicalKey: physicalKey);
} }
/// Returns the rect of the given widget. This is only valid once /// Returns the rect of the given widget. This is only valid once
......
...@@ -151,6 +151,29 @@ void main() { ...@@ -151,6 +151,29 @@ void main() {
expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty); expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
events.clear(); events.clear();
// Key press keyA with physical keyQ
await tester.sendKeyDownEvent(LogicalKeyboardKey.keyA, physicalKey: PhysicalKeyboardKey.keyQ);
expect(events.length, 1);
_verifyKeyEvent<KeyDownEvent>(events[0], PhysicalKeyboardKey.keyQ, LogicalKeyboardKey.keyA, 'a');
expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.keyQ}));
expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.keyA}));
expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
events.clear();
await tester.sendKeyRepeatEvent(LogicalKeyboardKey.keyA, physicalKey: PhysicalKeyboardKey.keyQ);
_verifyKeyEvent<KeyRepeatEvent>(events[0], PhysicalKeyboardKey.keyQ, LogicalKeyboardKey.keyA, 'a');
expect(HardwareKeyboard.instance.physicalKeysPressed, equals(<PhysicalKeyboardKey>{PhysicalKeyboardKey.keyQ}));
expect(HardwareKeyboard.instance.logicalKeysPressed, equals(<LogicalKeyboardKey>{LogicalKeyboardKey.keyA}));
expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
events.clear();
await tester.sendKeyUpEvent(LogicalKeyboardKey.keyA, physicalKey: PhysicalKeyboardKey.keyQ);
_verifyKeyEvent<KeyUpEvent>(events[0], PhysicalKeyboardKey.keyQ, LogicalKeyboardKey.keyA, null);
expect(HardwareKeyboard.instance.physicalKeysPressed, isEmpty);
expect(HardwareKeyboard.instance.logicalKeysPressed, isEmpty);
expect(HardwareKeyboard.instance.lockModesEnabled, isEmpty);
events.clear();
// Key press numpad1 // Key press numpad1
await tester.sendKeyDownEvent(LogicalKeyboardKey.numpad1); await tester.sendKeyDownEvent(LogicalKeyboardKey.numpad1);
_verifyKeyEvent<KeyDownEvent>(events[0], PhysicalKeyboardKey.numpad1, LogicalKeyboardKey.numpad1, null); _verifyKeyEvent<KeyDownEvent>(events[0], PhysicalKeyboardKey.numpad1, LogicalKeyboardKey.numpad1, null);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment