diff --git a/lib/ui/key.dart b/lib/ui/key.dart index ed58e56cdba39..25eab4ac94754 100644 --- a/lib/ui/key.dart +++ b/lib/ui/key.dart @@ -14,7 +14,47 @@ enum KeyEventType { up, /// The key is held, causing a repeated key input. - repeat, + repeat; + + String get label { + return switch (this) { + down => 'Key Down', + up => 'Key Up', + repeat => 'Key Repeat', + }; + } +} + +/// The source device for the key event. +/// +/// Not all platforms supply an accurate type. +// Must match the KeyEventDeviceType enum in ui/window/key_data.h. +enum KeyEventDeviceType { + /// The device is a keyboard. + keyboard, + + /// The device is a directional pad on something like a television remote + /// control or similar. + directionalPad, + + /// The device is a gamepad button + gamepad, + + /// The device is a joystick button + joystick, + + /// The device is a device connected to an HDMI bus. + hdmi; + + String get label { + return switch (this) { + keyboard => 'Keyboard', + directionalPad => 'Directional Pad', + gamepad => 'Gamepad', + joystick => 'Joystick', + hdmi => 'HDMI', + }; + } } /// Information about a key event. @@ -27,6 +67,7 @@ class KeyData { required this.logical, required this.character, required this.synthesized, + this.deviceType = KeyEventDeviceType.keyboard, }); /// Time of event dispatch, relative to an arbitrary timeline. @@ -38,6 +79,10 @@ class KeyData { /// The type of the event. final KeyEventType type; + /// Describes what type of device (keyboard, directional pad, etc.) this event + /// originated from. + final KeyEventDeviceType deviceType; + /// The key code for the physical key that has changed. final int physical; @@ -49,30 +94,31 @@ class KeyData { /// Ignored for up events. final String? character; - /// If [synthesized] is true, this event does not correspond to a native event. + /// If [synthesized] is true, this event does not correspond to a native + /// event. /// /// Although most of Flutter's keyboard events are transformed from native /// events, some events are not based on native events, and are synthesized - /// only to conform Flutter's key event model (as documented in - /// the `HardwareKeyboard` class in the framework). + /// only to conform Flutter's key event model (as documented in the + /// `HardwareKeyboard` class in the framework). /// /// For example, some key downs or ups might be lost when the window loses - /// focus. Some platforms provides ways to query whether a key is being held. + /// focus. Some platforms provide ways to query whether a key is being held. /// If the embedder detects an inconsistency between its internal record and /// the state returned by the system, the embedder will synthesize a /// corresponding event to synchronize the state without breaking the event /// model. /// - /// As another example, macOS treats CapsLock in a special way by sending - /// down and up events at the down of alterate presses to indicate the - /// direction in which the lock is toggled instead of that the physical key is - /// going. A macOS embedder should normalize the behavior by converting a - /// native down event into a down event followed immediately by a synthesized - /// up event, and the native up event also into a down event followed - /// immediately by a synthesized up event. + /// As another example, macOS treats CapsLock in a special way by sending down + /// and up events at the down of alternate presses to indicate the direction + /// in which the lock is toggled instead of that the physical key is going. A + /// macOS embedder should normalize the behavior by converting a native down + /// event into a down event followed immediately by a synthesized up event, + /// and the native up event also into a down event followed immediately by a + /// synthesized up event. /// - /// Synthesized events do not have a trustworthy [timeStamp], and should not be - /// processed as if the key actually went down or up at the time of the + /// Synthesized events do not have a trustworthy [timeStamp], and should not + /// be processed as if the key actually went down or up at the time of the /// callback. /// /// [KeyRepeatEvent] is never synthesized. @@ -172,29 +218,23 @@ class KeyData { } @override - String toString() => 'KeyData(key ${_typeToString(type)}, physical: 0x${physical.toRadixString(16)}, ' - 'logical: ${_logicalToString()}, character: ${_escapeCharacter()}${_quotedCharCode()}${synthesized ? ', synthesized' : ''})'; + String toString() { + return 'KeyData(${type.label}, ' + 'physical: 0x${physical.toRadixString(16)}, ' + 'logical: ${_logicalToString()}, ' + 'character: ${_escapeCharacter()}${_quotedCharCode()}' + '${synthesized ? ', synthesized' : ''}'; + } /// Returns a complete textual description of the information in this object. String toStringFull() { - return '$runtimeType(' - 'type: ${_typeToString(type)}, ' - 'timeStamp: $timeStamp, ' - 'physical: 0x${physical.toRadixString(16)}, ' - 'logical: 0x${logical.toRadixString(16)}, ' - 'character: ${_escapeCharacter()}, ' - 'synthesized: $synthesized' + return '$runtimeType(type: ${type.label}, ' + 'deviceType: ${deviceType.label}, ' + 'timeStamp: $timeStamp, ' + 'physical: 0x${physical.toRadixString(16)}, ' + 'logical: 0x${logical.toRadixString(16)}, ' + 'character: ${_escapeCharacter()}, ' + 'synthesized: $synthesized' ')'; } - - static String _typeToString(KeyEventType type) { - switch (type) { - case KeyEventType.up: - return 'up'; - case KeyEventType.down: - return 'down'; - case KeyEventType.repeat: - return 'repeat'; - } - } } diff --git a/lib/ui/platform_dispatcher.dart b/lib/ui/platform_dispatcher.dart index e8f7d83805baf..60f6783f6a58c 100644 --- a/lib/ui/platform_dispatcher.dart +++ b/lib/ui/platform_dispatcher.dart @@ -506,11 +506,9 @@ class PlatformDispatcher { // If this value changes, update the encoding code in the following files: // - // * key_data.h - // * key.dart (ui) - // * key.dart (web_ui) - // * HardwareKeyboard.java - static const int _kKeyDataFieldCount = 5; + // * key_data.h (kKeyDataFieldCount) + // * KeyData.java (KeyData.FIELD_COUNT) + static const int _kKeyDataFieldCount = 6; // The packet structure is described in `key_data_packet.h`. static KeyData _unpackKeyData(ByteData packet) { diff --git a/lib/ui/window/key_data.h b/lib/ui/window/key_data.h index e3b3ea5d6459d..6ce44667743b9 100644 --- a/lib/ui/window/key_data.h +++ b/lib/ui/window/key_data.h @@ -9,8 +9,11 @@ namespace flutter { -// If this value changes, update the key data unpacking code in hooks.dart. -static constexpr int kKeyDataFieldCount = 5; +// If this value changes, update the encoding code in the following files: +// +// * KeyData.java (KeyData.FIELD_COUNT) +// * platform_dispatcher.dart (_kKeyDataFieldCount) +static constexpr int kKeyDataFieldCount = 6; static constexpr int kBytesPerKeyField = sizeof(int64_t); // The change of the key event, used by KeyData. @@ -22,6 +25,30 @@ enum class KeyEventType : int64_t { kRepeat, }; +// The source device for the key event. +// +// Not all platforms supply an accurate source. +// +// Defaults to [keyboard]. +// Must match the KeyEventDeviceType enum in ui/key.dart. +enum class KeyEventDeviceType : int64_t { + // The source is a keyboard. + kKeyboard = 0, + + // The source is a directional pad on something like a television remote + // control or similar. + kDirectionalPad, + + // The source is a gamepad button. + kGamepad, + + // The source is a joystick button. + kJoystick, + + // The source is a device connected to an HDMI bus. + kHdmi, +}; + // The fixed-length sections of a KeyDataPacket. // // KeyData does not contain `character`, for variable-length data are stored in @@ -41,6 +68,7 @@ struct alignas(8) KeyData { // // The value is 1 for true, and 0 for false. uint64_t synthesized; + KeyEventDeviceType device_type; // Sets all contents of `Keydata` to 0. void Clear(); diff --git a/lib/ui/window/key_data_packet.cc b/lib/ui/window/key_data_packet.cc index fe24af210cd67..15c213cb20876 100644 --- a/lib/ui/window/key_data_packet.cc +++ b/lib/ui/window/key_data_packet.cc @@ -5,6 +5,7 @@ #include "flutter/lib/ui/window/key_data_packet.h" #include +#include #include "flutter/fml/logging.h" @@ -13,8 +14,8 @@ namespace flutter { KeyDataPacket::KeyDataPacket(const KeyData& event, const char* character) { size_t char_size = character == nullptr ? 0 : strlen(character); uint64_t char_size_64 = char_size; - data_.resize(sizeof(uint64_t) + sizeof(KeyData) + char_size); - memcpy(CharacterSizeStart(), &char_size_64, sizeof(char_size)); + data_.resize(sizeof(char_size_64) + sizeof(KeyData) + char_size); + memcpy(CharacterSizeStart(), &char_size_64, sizeof(char_size_64)); memcpy(KeyDataStart(), &event, sizeof(KeyData)); if (character != nullptr) { memcpy(CharacterStart(), character, char_size); diff --git a/lib/web_ui/lib/key.dart b/lib/web_ui/lib/key.dart index 64934d59b0989..35fbf42d9a5a0 100644 --- a/lib/web_ui/lib/key.dart +++ b/lib/web_ui/lib/key.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. - part of ui; /// The type of a key event. @@ -15,7 +14,47 @@ enum KeyEventType { up, /// The key is held, causing a repeated key input. - repeat, + repeat; + + String get label { + return switch (this) { + down => 'Key Down', + up => 'Key Up', + repeat => 'Key Repeat', + }; + } +} + +/// The source device for the key event. +/// +/// Not all platforms supply an accurate type. +// Must match the KeyEventDeviceType enum in ui/window/key_data.h. +enum KeyEventDeviceType { + /// The device is a keyboard. + keyboard, + + /// The device is a directional pad on something like a television remote + /// control or similar. + directionalPad, + + /// The device is a gamepad button + gamepad, + + /// The device is a joystick button + joystick, + + /// The device is a device connected to an HDMI bus. + hdmi; + + String get label { + return switch (this) { + keyboard => 'Keyboard', + directionalPad => 'Directional Pad', + gamepad => 'Gamepad', + joystick => 'Joystick', + hdmi => 'HDMI', + }; + } } /// Information about a key event. @@ -28,17 +67,22 @@ class KeyData { required this.logical, required this.character, required this.synthesized, + this.deviceType = KeyEventDeviceType.keyboard, }); /// Time of event dispatch, relative to an arbitrary timeline. /// - /// For [KeyEventType.synchronize] and [KeyEventType.cancel] events, the [timeStamp] - /// might not be the actual time that the key press or release happens. + /// For synthesized events, the [timeStamp] might not be the actual time that + /// the key press or release happens. final Duration timeStamp; /// The type of the event. final KeyEventType type; + /// Describes what type of device (keyboard, directional pad, etc.) this event + /// originated from. + final KeyEventDeviceType deviceType; + /// The key code for the physical key that has changed. final int physical; @@ -50,29 +94,31 @@ class KeyData { /// Ignored for up events. final String? character; - /// If [synthesized] is true, this event does not correspond to a native event. + /// If [synthesized] is true, this event does not correspond to a native + /// event. /// /// Although most of Flutter's keyboard events are transformed from native /// events, some events are not based on native events, and are synthesized - /// only to conform Flutter's key event model (as documented in - /// the `HardwareKeyboard` class in the framework). + /// only to conform Flutter's key event model (as documented in the + /// `HardwareKeyboard` class in the framework). /// /// For example, some key downs or ups might be lost when the window loses - /// focus. Some platforms provides ways to query whether a key is being held. - /// If Flutter detects an inconsistency between the state Flutter records and - /// the state returned by the system, Flutter will synthesize a corresponding - /// event to synchronize the state without breaking the event model. + /// focus. Some platforms provide ways to query whether a key is being held. + /// If the embedder detects an inconsistency between its internal record and + /// the state returned by the system, the embedder will synthesize a + /// corresponding event to synchronize the state without breaking the event + /// model. /// - /// As another example, macOS treats CapsLock in a special way by sending - /// down and up events at the down of alterate presses to indicate the - /// direction in which the lock is toggled instead of that the physical key is - /// going. Flutter normalizes the behavior by converting a native down event - /// into a down event followed immediately by a synthesized up event, and - /// the native up event also into a down event followed immediately by a + /// As another example, macOS treats CapsLock in a special way by sending down + /// and up events at the down of alternate presses to indicate the direction + /// in which the lock is toggled instead of that the physical key is going. A + /// macOS embedder should normalize the behavior by converting a native down + /// event into a down event followed immediately by a synthesized up event, + /// and the native up event also into a down event followed immediately by a /// synthesized up event. /// - /// Synthesized events do not have a trustworthy [timeStamp], and should not be - /// processed as if the key actually went down or up at the time of the + /// Synthesized events do not have a trustworthy [timeStamp], and should not + /// be processed as if the key actually went down or up at the time of the /// callback. /// /// [KeyRepeatEvent] is never synthesized. @@ -95,8 +141,22 @@ class KeyData { return ' (Unprintable)'; case 0x002: return ' (Flutter)'; + case 0x011: + return ' (Android)'; + case 0x012: + return ' (Fuchsia)'; + case 0x013: + return ' (iOS)'; + case 0x014: + return ' (macOS)'; + case 0x015: + return ' (GTK)'; + case 0x016: + return ' (Windows)'; case 0x017: return ' (Web)'; + case 0x018: + return ' (GLFW)'; } return ''; })(); @@ -105,7 +165,7 @@ class KeyData { String? _escapeCharacter() { if (character == null) { - return character ?? ''; + return ''; } switch (character!) { case '\n': @@ -133,29 +193,24 @@ class KeyData { } @override - String toString() => 'KeyData(type: ${_typeToString(type)}, physical: 0x${physical.toRadixString(16)}, ' - 'logical: ${_logicalToString()}, character: ${_escapeCharacter()}${_quotedCharCode()}${synthesized ? ', synthesized' : ''})'; + String toString() { + return 'KeyData(${type.label}, ' + 'physical: 0x${physical.toRadixString(16)}, ' + 'logical: ${_logicalToString()}, ' + 'character: ${_escapeCharacter()}${_quotedCharCode()}' + '${synthesized ? ', synthesized' : ''})'; + } /// Returns a complete textual description of the information in this object. String toStringFull() { return '$runtimeType(' - 'type: ${_typeToString(type)}, ' - 'timeStamp: $timeStamp, ' - 'physical: 0x${physical.toRadixString(16)}, ' - 'logical: 0x${logical.toRadixString(16)}, ' - 'character: $character, ' - 'synthesized: $synthesized' + 'type: ${type.label}, ' + 'deviceType: ${deviceType.label}, ' + 'timeStamp: $timeStamp, ' + 'physical: 0x${physical.toRadixString(16)}, ' + 'logical: 0x${logical.toRadixString(16)}, ' + 'character: ${_escapeCharacter()}, ' + 'synthesized: $synthesized' ')'; } - - static String _typeToString(KeyEventType type) { - switch (type) { - case KeyEventType.up: - return 'up'; - case KeyEventType.down: - return 'down'; - case KeyEventType.repeat: - return 'repeat'; - } - } } diff --git a/lib/web_ui/test/engine/keyboard_converter_test.dart b/lib/web_ui/test/engine/keyboard_converter_test.dart index 90922c5cbcf5e..74b2ee95db401 100644 --- a/lib/web_ui/test/engine/keyboard_converter_test.dart +++ b/lib/web_ui/test/engine/keyboard_converter_test.dart @@ -60,7 +60,7 @@ void testMain() { character: 'A', timeStamp: Duration.zero, synthesized: false, - ).toString(), 'KeyData(type: down, physical: 0x700e5, logical: 0x61 (Unicode), character: "A" (0x41))'); + ).toString(), 'KeyData(Key Down, physical: 0x700e5, logical: 0x61 (Unicode), character: "A" (0x41))'); expect(const ui.KeyData( type: ui.KeyEventType.up, @@ -69,7 +69,7 @@ void testMain() { character: '\n', timeStamp: Duration.zero, synthesized: true, - ).toString(), r'KeyData(type: up, physical: 0x700e6, logical: 0x100000061 (Unprintable), character: "\n" (0x0a), synthesized)'); + ).toString(), r'KeyData(Key Up, physical: 0x700e6, logical: 0x100000061 (Unprintable), character: "\n" (0x0a), synthesized)'); expect(const ui.KeyData( type: ui.KeyEventType.repeat, @@ -78,7 +78,7 @@ void testMain() { character: null, timeStamp: Duration.zero, synthesized: false, - ).toString(), 'KeyData(type: repeat, physical: 0x700e7, logical: 0x9900000071, character: )'); + ).toString(), 'KeyData(Key Repeat, physical: 0x700e7, logical: 0x9900000071, character: )'); }); test('Single key press, repeat, and release', () { @@ -93,6 +93,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 1), type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -103,6 +104,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 1, microseconds: 500), type: ui.KeyEventType.repeat, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -113,6 +115,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(seconds: 1, milliseconds: 500), type: ui.KeyEventType.repeat, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -123,6 +126,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(seconds: 2, microseconds: 500), type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: null, @@ -143,6 +147,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 1), type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyL, logical: kLogicalKeyL, character: 'l̥', @@ -160,6 +165,7 @@ void testMain() { converter.handleEvent(keyDownEvent('ShiftLeft', 'Shift', kShift, kLocationLeft)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -169,6 +175,7 @@ void testMain() { converter.handleEvent(keyDownEvent('KeyA', 'A', kShift)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'A', @@ -178,6 +185,7 @@ void testMain() { converter.handleEvent(keyRepeatedDownEvent('KeyA', 'A', kShift)); expectKeyData(keyDataList.last, type: ui.KeyEventType.repeat, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'A', @@ -187,6 +195,7 @@ void testMain() { converter.handleEvent(keyUpEvent('ShiftLeft', 'Shift', 0, kLocationLeft)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -196,6 +205,7 @@ void testMain() { converter.handleEvent(keyRepeatedDownEvent('KeyA', 'a')); expectKeyData(keyDataList.last, type: ui.KeyEventType.repeat, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -205,6 +215,7 @@ void testMain() { converter.handleEvent(keyRepeatedDownEvent('KeyA', 'a')); expectKeyData(keyDataList.last, type: ui.KeyEventType.repeat, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -214,6 +225,7 @@ void testMain() { converter.handleEvent(keyUpEvent('KeyA', 'a')); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: null, @@ -231,6 +243,7 @@ void testMain() { converter.handleEvent(keyDownEvent('ShiftLeft', 'Shift', kShift, kLocationLeft)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -239,6 +252,7 @@ void testMain() { converter.handleEvent(keyDownEvent('ShiftRight', 'Shift', kShift, kLocationRight)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftRight, logical: kLogicalShiftRight, character: null, @@ -247,6 +261,7 @@ void testMain() { converter.handleEvent(keyUpEvent('ShiftLeft', 'Shift', kShift, kLocationLeft)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -255,6 +270,7 @@ void testMain() { converter.handleEvent(keyUpEvent('ShiftRight', 'Shift', 0, kLocationRight)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftRight, logical: kLogicalShiftRight, character: null, @@ -271,6 +287,7 @@ void testMain() { converter.handleEvent(keyDownEvent('', 'Shift', kShift)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalEmptyCode, logical: kLogicalShiftLeft, character: null, @@ -279,6 +296,7 @@ void testMain() { converter.handleEvent(keyUpEvent('', 'Shift', kShift)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalEmptyCode, logical: kLogicalShiftLeft, character: null, @@ -287,6 +305,7 @@ void testMain() { converter.handleEvent(keyDownEvent('', 'Control', kCtrl)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalEmptyCode, logical: kLogicalCtrlLeft, character: null, @@ -295,6 +314,7 @@ void testMain() { converter.handleEvent(keyUpEvent('', 'Control', kCtrl)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalEmptyCode, logical: kLogicalCtrlLeft, character: null, @@ -303,6 +323,7 @@ void testMain() { converter.handleEvent(keyDownEvent('', 'Alt', kAlt)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalEmptyCode, logical: kLogicalAltLeft, character: null, @@ -311,6 +332,7 @@ void testMain() { converter.handleEvent(keyUpEvent('', 'Alt', kAlt)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalEmptyCode, logical: kLogicalAltLeft, character: null, @@ -319,6 +341,7 @@ void testMain() { converter.handleEvent(keyDownEvent('', 'Meta', kMeta)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalEmptyCode, logical: kLogicalMetaLeft, character: null, @@ -327,6 +350,7 @@ void testMain() { converter.handleEvent(keyUpEvent('', 'Meta', kMeta)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalEmptyCode, logical: kLogicalMetaLeft, character: null, @@ -343,6 +367,7 @@ void testMain() { converter.handleEvent(keyDownEvent('Digit1', '1')); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalDigit1, logical: kLogicalDigit1, character: '1', @@ -351,6 +376,7 @@ void testMain() { converter.handleEvent(keyDownEvent('Numpad1', '1', 0, kLocationNumpad)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalNumpad1, logical: kLogicalNumpad1, character: '1', @@ -359,6 +385,7 @@ void testMain() { converter.handleEvent(keyUpEvent('Digit1', '1')); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalDigit1, logical: kLogicalDigit1, character: null, @@ -367,6 +394,7 @@ void testMain() { converter.handleEvent(keyUpEvent('Numpad1', '1', 0, kLocationNumpad)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalNumpad1, logical: kLogicalNumpad1, character: null, @@ -393,6 +421,7 @@ void testMain() { converter.handleEvent(keyDownEvent('KeyE', 'Dead', kAlt)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyE, logical: kLogicalAltE, character: null, @@ -401,6 +430,7 @@ void testMain() { converter.handleEvent(keyUpEvent('KeyE', 'Dead', kAlt)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyE, logical: kLogicalAltE, character: null, @@ -409,6 +439,7 @@ void testMain() { converter.handleEvent(keyDownEvent('KeyU', 'Dead', kAlt)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyU, logical: kLogicalAltU, character: null, @@ -417,6 +448,7 @@ void testMain() { converter.handleEvent(keyUpEvent('KeyU', 'Dead', kAlt)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyU, logical: kLogicalAltU, character: null, @@ -429,6 +461,7 @@ void testMain() { converter.handleEvent(keyDownEvent('KeyE', 'Dead', kAlt | kShift)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyE, logical: kLogicalAltShiftE, character: null, @@ -439,6 +472,7 @@ void testMain() { converter.handleEvent(keyUpEvent('KeyE', 'e', kShift)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyE, logical: kLogicalAltShiftE, character: null, @@ -463,6 +497,7 @@ void testMain() { expect(keyDataList, hasLength(2)); expectKeyData(keyDataList.first, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -470,6 +505,7 @@ void testMain() { ); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -481,6 +517,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -527,6 +564,7 @@ void testMain() { converter.handleEvent(keyDownEvent('KeyA', 'a')); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -535,6 +573,7 @@ void testMain() { converter.handleEvent(keyDownEvent('KeyU', 'u')); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyU, logical: kLogicalKeyU, character: 'u', @@ -554,6 +593,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalCapsLock, logical: kLogicalCapsLock, character: null, @@ -565,6 +605,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalCapsLock, logical: kLogicalCapsLock, character: null, @@ -577,6 +618,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalCapsLock, logical: kLogicalCapsLock, character: null, @@ -588,6 +630,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalCapsLock, logical: kLogicalCapsLock, character: null, @@ -601,6 +644,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalCapsLock, logical: kLogicalCapsLock, character: null, @@ -626,6 +670,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalCapsLock, logical: kLogicalCapsLock, character: null, @@ -639,6 +684,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalCapsLock, logical: kLogicalCapsLock, character: null, @@ -651,6 +697,7 @@ void testMain() { converter.handleEvent(keyDownEvent('CapsLock', 'CapsLock')); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalCapsLock, logical: kLogicalCapsLock, character: null, @@ -659,6 +706,7 @@ void testMain() { converter.handleEvent(keyUpEvent('CapsLock', 'CapsLock')); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalCapsLock, logical: kLogicalCapsLock, character: null, @@ -680,18 +728,20 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 200), type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', ); keyDataList.clear(); - // Keyup of KeyA is omitted due to being a shortcut. + // Key Up of KeyA is omitted due to being a shortcut. async.elapse(const Duration(milliseconds: 2500)); expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 2200), type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: null, @@ -703,6 +753,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 2700), type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalMetaLeft, logical: kLogicalMetaLeft, character: null, @@ -714,6 +765,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 2800), type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -724,6 +776,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 2900), type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: null, @@ -750,12 +803,13 @@ void testMain() { async.elapse(const Duration(milliseconds: 50)); converter.handleEvent(keyRepeatedDownEvent('KeyA', 'a', kMeta)..timeStamp = 700); - // Keyup of KeyA is omitted due to being a shortcut. + // Key Up of KeyA is omitted due to being a shortcut. async.elapse(const Duration(milliseconds: 2000)); expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 2700), type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: null, @@ -767,6 +821,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 3200), type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalMetaLeft, logical: kLogicalMetaLeft, character: null, @@ -778,6 +833,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 3300), type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -788,6 +844,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 3400), type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: null, @@ -808,6 +865,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 200), type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -822,6 +880,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 800), type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: null, @@ -835,6 +894,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 2800), type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -845,6 +905,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 2900), type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: null, @@ -865,6 +926,7 @@ void testMain() { expectKeyData(keyDataList.last, timeStamp: const Duration(milliseconds: 200), type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -886,6 +948,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalScrollLock, logical: kLogicalScrollLock, character: null, @@ -899,6 +962,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalScrollLock, logical: kLogicalScrollLock, character: null, @@ -908,6 +972,7 @@ void testMain() { converter.handleEvent(keyDownEvent('ScrollLock', 'ScrollLock')); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalScrollLock, logical: kLogicalScrollLock, character: null, @@ -916,6 +981,7 @@ void testMain() { converter.handleEvent(keyUpEvent('ScrollLock', 'ScrollLock')); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalScrollLock, logical: kLogicalScrollLock, character: null, @@ -932,6 +998,7 @@ void testMain() { converter.handleEvent(keyDownEvent('ShiftRight', 'Shift', kShift, kLocationRight)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftRight, logical: kLogicalShiftRight, character: null, @@ -940,6 +1007,7 @@ void testMain() { converter.handleEvent(keyDownEvent('ShiftLeft', 'Shift', kShift, kLocationLeft)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -952,6 +1020,7 @@ void testMain() { expect(keyDataList, hasLength(3)); expectKeyData(keyDataList[0], type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -959,6 +1028,7 @@ void testMain() { ); expectKeyData(keyDataList[1], type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftRight, logical: kLogicalShiftRight, character: null, @@ -966,6 +1036,7 @@ void testMain() { ); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalKeyA, logical: kLogicalKeyA, character: 'a', @@ -988,6 +1059,7 @@ void testMain() { converter.handleEvent(keyDownEvent('ShiftLeft', 'Shift', kShift, kLocationLeft)); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -999,6 +1071,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.first, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalMetaLeft, logical: kLogicalMetaLeft, character: null, @@ -1010,6 +1083,7 @@ void testMain() { expect(keyDataList, hasLength(1)); expectKeyData(keyDataList.first, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalMetaLeft, logical: kLogicalMetaLeft, character: null, @@ -1019,6 +1093,7 @@ void testMain() { converter.handleEvent(keyUpEvent('ShiftLeft', 'Shift', 0, kLocationLeft)); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: kPhysicalShiftLeft, logical: kLogicalShiftLeft, character: null, @@ -1084,6 +1159,7 @@ const int kScrollLock = 0x4; void expectKeyData( ui.KeyData target, { required ui.KeyEventType type, + required ui.KeyEventDeviceType deviceType, required int physical, required int logical, required String? character, diff --git a/lib/web_ui/test/engine/pointer_binding_test.dart b/lib/web_ui/test/engine/pointer_binding_test.dart index f93d1a2e966a6..ddcc1c83f523d 100644 --- a/lib/web_ui/test/engine/pointer_binding_test.dart +++ b/lib/web_ui/test/engine/pointer_binding_test.dart @@ -592,6 +592,7 @@ void testMain() { expect(keyDataList.length, 1); expectKeyData(keyDataList.last, type: ui.KeyEventType.down, + deviceType: ui.KeyEventDeviceType.keyboard, physical: physicalLeft, logical: logicalLeft, character: null, @@ -714,6 +715,7 @@ void testMain() { expect(keyDataList.length, 1); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: physicalLeft, logical: logicalLeft, character: null, @@ -743,6 +745,7 @@ void testMain() { expect(keyDataList.length, 1); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: physicalRight, logical: logicalRight, character: null, @@ -832,6 +835,7 @@ void testMain() { expect(keyDataList.length, 1); expectKeyData(keyDataList.last, type: ui.KeyEventType.up, + deviceType: ui.KeyEventDeviceType.keyboard, physical: physicalAltRight, logical: logicalAltGraph, character: null, diff --git a/lib/web_ui/test/engine/window_test.dart b/lib/web_ui/test/engine/window_test.dart index ff93016a59056..5c5d1a242b54c 100644 --- a/lib/web_ui/test/engine/window_test.dart +++ b/lib/web_ui/test/engine/window_test.dart @@ -323,7 +323,7 @@ Future testMain() async { // Regression test for https://github.com/flutter/flutter/issues/88269 test('sets preferred screen orientation', () async { - final DomScreen original = domWindow.screen!; + final DomScreen? original = domWindow.screen; final List lockCalls = []; int unlockCount = 0; @@ -397,7 +397,7 @@ Future testMain() async { /// Regression test for https://github.com/flutter/flutter/issues/66128. test("setPreferredOrientation responds even if browser doesn't support api", () async { - final DomScreen original = domWindow.screen!; + final DomScreen? original = domWindow.screen; // The `orientation` property cannot be overridden, so this test overrides the entire `screen`. js_util.setProperty(domWindow, 'screen', js_util.jsify({ diff --git a/shell/platform/android/io/flutter/embedding/android/KeyData.java b/shell/platform/android/io/flutter/embedding/android/KeyData.java index eb8a41767c576..776372c801169 100644 --- a/shell/platform/android/io/flutter/embedding/android/KeyData.java +++ b/shell/platform/android/io/flutter/embedding/android/KeyData.java @@ -30,7 +30,11 @@ public class KeyData { public static final String CHANNEL = "flutter/keydata"; // The number of fields except for `character`. - private static final int FIELD_COUNT = 5; + // If this value changes, update the code in the following files: + // + // * key_data.h (kKeyDataFieldCount) + // * platform_dispatcher.dart (_kKeyDataFieldCount) + private static final int FIELD_COUNT = 6; private static final int BYTES_PER_FIELD = 8; /** The action type of the key data. */ @@ -63,6 +67,42 @@ static Type fromLong(long value) { } } + /** The device type of the key data. */ + public enum DeviceType { + kKeyboard(0), + kDirectionalPad(1), + kGamepad(2), + kJoystick(3), + kHdmi(4); + + private long value; + + private DeviceType(long value) { + this.value = value; + } + + public long getValue() { + return value; + } + + static DeviceType fromLong(long value) { + switch ((int) value) { + case 0: + return kKeyboard; + case 1: + return kDirectionalPad; + case 2: + return kGamepad; + case 3: + return kJoystick; + case 4: + return kHdmi; + default: + throw new AssertionError("Unexpected DeviceType value"); + } + } + } + /** Creates an empty {@link KeyData}. */ public KeyData() {} @@ -78,6 +118,7 @@ public KeyData(@NonNull ByteBuffer buffer) { this.physicalKey = buffer.getLong(); this.logicalKey = buffer.getLong(); this.synthesized = buffer.getLong() != 0; + this.deviceType = DeviceType.fromLong(buffer.getLong()); if (buffer.remaining() != charSize) { throw new AssertionError( @@ -102,6 +143,7 @@ public KeyData(@NonNull ByteBuffer buffer) { long physicalKey; long logicalKey; boolean synthesized; + DeviceType deviceType; /** The character of this key data encoded in UTF-8. */ @Nullable String character; @@ -131,6 +173,7 @@ ByteBuffer toBytes() { packet.putLong(physicalKey); packet.putLong(logicalKey); packet.putLong(synthesized ? 1L : 0L); + packet.putLong(deviceType.getValue()); if (charBytes != null) { packet.put(charBytes); } diff --git a/shell/platform/android/io/flutter/embedding/android/KeyEmbedderResponder.java b/shell/platform/android/io/flutter/embedding/android/KeyEmbedderResponder.java index aa1fdec32d514..ed23adac1d24f 100644 --- a/shell/platform/android/io/flutter/embedding/android/KeyEmbedderResponder.java +++ b/shell/platform/android/io/flutter/embedding/android/KeyEmbedderResponder.java @@ -4,6 +4,7 @@ package io.flutter.embedding.android; +import android.view.InputDevice; import android.view.KeyEvent; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -341,12 +342,33 @@ private boolean handleEventImpl( } final KeyData output = new KeyData(); + + switch (event.getSource()) { + default: + case InputDevice.SOURCE_KEYBOARD: + output.deviceType = KeyData.DeviceType.kKeyboard; + break; + case InputDevice.SOURCE_DPAD: + output.deviceType = KeyData.DeviceType.kDirectionalPad; + break; + case InputDevice.SOURCE_GAMEPAD: + output.deviceType = KeyData.DeviceType.kGamepad; + break; + case InputDevice.SOURCE_JOYSTICK: + output.deviceType = KeyData.DeviceType.kJoystick; + break; + case InputDevice.SOURCE_HDMI: + output.deviceType = KeyData.DeviceType.kHdmi; + break; + } + output.timestamp = event.getEventTime(); output.type = type; output.logicalKey = logicalKey; output.physicalKey = physicalKey; output.character = character; output.synthesized = false; + output.deviceType = KeyData.DeviceType.kKeyboard; sendKeyEvent(output, onKeyEventHandledCallback); for (final Runnable postSyncEvent : postSynchronizeEvents) { @@ -363,6 +385,7 @@ private void synthesizeEvent(boolean isDown, Long logicalKey, Long physicalKey, output.physicalKey = physicalKey; output.character = null; output.synthesized = true; + output.deviceType = KeyData.DeviceType.kKeyboard; if (physicalKey != 0 && logicalKey != 0) { updatePressingState(physicalKey, isDown ? logicalKey : null); } diff --git a/shell/platform/android/test/io/flutter/embedding/android/KeyboardManagerTest.java b/shell/platform/android/test/io/flutter/embedding/android/KeyboardManagerTest.java index 80aaf225edee5..1bf7cfe2a01a9 100644 --- a/shell/platform/android/test/io/flutter/embedding/android/KeyboardManagerTest.java +++ b/shell/platform/android/test/io/flutter/embedding/android/KeyboardManagerTest.java @@ -19,6 +19,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.test.ext.junit.runners.AndroidJUnit4; +import io.flutter.embedding.android.KeyData.DeviceType; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.JSONMessageCodec; import io.flutter.util.FakeKeyEvent; @@ -315,12 +316,14 @@ static void assertEmbedderEventEquals( long physicalKey, long logicalKey, String character, - boolean synthesized) { + boolean synthesized, + DeviceType deviceType) { assertEquals(type, data.type); assertEquals(physicalKey, data.physicalKey); assertEquals(logicalKey, data.logicalKey); assertEquals(character, data.character); assertEquals(synthesized, data.synthesized); + assertEquals(deviceType, data.deviceType); } static void verifyEmbedderEvents(List receivedCalls, KeyData[] expectedData) { @@ -333,7 +336,8 @@ static void verifyEmbedderEvents(List receivedCalls, KeyData[] expec data.physicalKey, data.logicalKey, data.character, - data.synthesized); + data.synthesized, + data.deviceType); } } @@ -342,7 +346,8 @@ static KeyData buildKeyData( long physicalKey, long logicalKey, @Nullable String characters, - boolean synthesized) { + boolean synthesized, + DeviceType deviceType) { final KeyData result = new KeyData(); result.physicalKey = physicalKey; result.logicalKey = logicalKey; @@ -350,6 +355,7 @@ static KeyData buildKeyData( result.type = type; result.character = characters; result.synthesized = synthesized; + result.deviceType = deviceType; return result; } @@ -405,6 +411,7 @@ public static KeyData buildShiftKeyData(boolean isLeft, boolean isDown, boolean data.physicalKey = isLeft ? PHYSICAL_SHIFT_LEFT : PHYSICAL_SHIFT_RIGHT; data.logicalKey = isLeft ? LOGICAL_SHIFT_LEFT : LOGICAL_SHIFT_RIGHT; data.synthesized = isSynthesized; + data.deviceType = KeyData.DeviceType.kKeyboard; return data; } @@ -439,6 +446,7 @@ public void serializeAndDeserializeKeyData() { data1.type = Type.kRepeat; data1.character = "A"; data1.synthesized = true; + data1.deviceType = DeviceType.kKeyboard; final ByteBuffer data1Buffer = data1.toBytes(); @@ -450,10 +458,11 @@ public void serializeAndDeserializeKeyData() { + "0a00000000000000" + "0b00000000000000" + "0100000000000000" + + "0000000000000000" + "41", printBufferBytes(data1Buffer)); // `position` is considered as the message size. - assertEquals(49, data1Buffer.position()); + assertEquals(57, data1Buffer.position()); data1Buffer.rewind(); final KeyData data1Loaded = new KeyData(data1Buffer); @@ -467,6 +476,7 @@ public void serializeAndDeserializeKeyData() { data2.type = Type.kUp; data2.character = null; data2.synthesized = false; + data2.deviceType = DeviceType.kDirectionalPad; final ByteBuffer data2Buffer = data2.toBytes(); @@ -477,7 +487,8 @@ public void serializeAndDeserializeKeyData() { + "0100000000000000" + "ccccbbbbaaaa0000" + "8888777766660000" - + "0000000000000000", + + "0000000000000000" + + "0100000000000000", printBufferBytes(data2Buffer)); data2Buffer.rewind(); @@ -568,7 +579,13 @@ public void embedderReponderHandlesEvents() { assertEquals(true, result); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "a", false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_KEY_A, + LOGICAL_KEY_A, + "a", + false, + DeviceType.kKeyboard); // Don't send the key event to the text plugin if the only primary responder // hasn't responded. @@ -598,7 +615,13 @@ public void bothRespondersHandlesEvents() { assertEquals(true, result); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "a", false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_KEY_A, + LOGICAL_KEY_A, + "a", + false, + DeviceType.kKeyboard); assertChannelEventEquals(calls.get(1).channelObject, "keydown", KEYCODE_A); verify(tester.mockView, times(0)).onTextInputKeyEvent(any(KeyEvent.class)); @@ -716,7 +739,7 @@ public void tapLowerA() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "a", false), + buildKeyData(Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "a", false, DeviceType.kKeyboard), }); calls.clear(); @@ -727,7 +750,8 @@ public void tapLowerA() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kRepeat, PHYSICAL_KEY_A, LOGICAL_KEY_A, "a", false), + buildKeyData( + Type.kRepeat, PHYSICAL_KEY_A, LOGICAL_KEY_A, "a", false, DeviceType.kKeyboard), }); calls.clear(); @@ -738,7 +762,7 @@ public void tapLowerA() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_KEY_A, LOGICAL_KEY_A, null, false), + buildKeyData(Type.kUp, PHYSICAL_KEY_A, LOGICAL_KEY_A, null, false, DeviceType.kKeyboard), }); calls.clear(); } @@ -759,7 +783,13 @@ public void tapUpperA() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false), + buildKeyData( + Type.kDown, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard), }); calls.clear(); @@ -770,7 +800,7 @@ public void tapUpperA() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "A", false), + buildKeyData(Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "A", false, DeviceType.kKeyboard), }); calls.clear(); @@ -781,7 +811,7 @@ public void tapUpperA() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_KEY_A, LOGICAL_KEY_A, null, false), + buildKeyData(Type.kUp, PHYSICAL_KEY_A, LOGICAL_KEY_A, null, false, DeviceType.kKeyboard), }); calls.clear(); @@ -793,7 +823,8 @@ public void tapUpperA() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false), + buildKeyData( + Type.kUp, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false, DeviceType.kKeyboard), }); calls.clear(); } @@ -814,7 +845,7 @@ public void eventsWithMintedCodes() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, 0x1100000042L, LOGICAL_ENTER, "\n", false), + buildKeyData(Type.kDown, 0x1100000042L, LOGICAL_ENTER, "\n", false, DeviceType.kKeyboard), }); calls.clear(); @@ -824,7 +855,7 @@ public void eventsWithMintedCodes() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, 0, 0, null, true), + buildKeyData(Type.kDown, 0, 0, null, true, DeviceType.kKeyboard), }); calls.clear(); @@ -836,7 +867,7 @@ public void eventsWithMintedCodes() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, 0x11DEADBEEFL, 0x1100000000L, null, false), + buildKeyData(Type.kDown, 0x11DEADBEEFL, 0x1100000000L, null, false, DeviceType.kKeyboard), }); calls.clear(); @@ -848,7 +879,8 @@ public void eventsWithMintedCodes() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_ARROW_LEFT, 0x1100000000L, null, false), + buildKeyData( + Type.kDown, PHYSICAL_ARROW_LEFT, 0x1100000000L, null, false, DeviceType.kKeyboard), }); calls.clear(); @@ -860,7 +892,8 @@ public void eventsWithMintedCodes() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_ARROW_RIGHT, 0x11DEADBEEFL, null, false), + buildKeyData( + Type.kDown, PHYSICAL_ARROW_RIGHT, 0x11DEADBEEFL, null, false, DeviceType.kKeyboard), }); calls.clear(); } @@ -880,7 +913,7 @@ public void duplicateDownEventsArePrecededBySynthesizedUpEvents() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "a", false), + buildKeyData(Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "a", false, DeviceType.kKeyboard), }); calls.clear(); @@ -890,9 +923,21 @@ public void duplicateDownEventsArePrecededBySynthesizedUpEvents() { new FakeKeyEvent(ACTION_DOWN, SCAN_KEY_A, KEYCODE_A, 0, 'a', 0))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_KEY_A, LOGICAL_KEY_A, null, true); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_KEY_A, + LOGICAL_KEY_A, + null, + true, + DeviceType.kKeyboard); assertEmbedderEventEquals( - calls.get(1).keyData, Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "a", false); + calls.get(1).keyData, + Type.kDown, + PHYSICAL_KEY_A, + LOGICAL_KEY_A, + "a", + false, + DeviceType.kKeyboard); calls.clear(); } @@ -911,7 +956,7 @@ public void abruptUpEventsAreIgnored() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, 0l, 0l, null, true), + buildKeyData(Type.kDown, 0l, 0l, null, true, DeviceType.kKeyboard), }); calls.clear(); } @@ -930,7 +975,13 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false), + buildKeyData( + Type.kDown, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard), }); calls.clear(); @@ -939,7 +990,8 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false), + buildKeyData( + Type.kUp, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false, DeviceType.kKeyboard), }); calls.clear(); @@ -949,7 +1001,13 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_SHIFT_RIGHT, LOGICAL_SHIFT_RIGHT, null, false), + buildKeyData( + Type.kDown, + PHYSICAL_SHIFT_RIGHT, + LOGICAL_SHIFT_RIGHT, + null, + false, + DeviceType.kKeyboard), }); calls.clear(); @@ -958,7 +1016,13 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_SHIFT_RIGHT, LOGICAL_SHIFT_RIGHT, null, false), + buildKeyData( + Type.kUp, + PHYSICAL_SHIFT_RIGHT, + LOGICAL_SHIFT_RIGHT, + null, + false, + DeviceType.kKeyboard), }); calls.clear(); @@ -968,7 +1032,13 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_CONTROL_LEFT, LOGICAL_CONTROL_LEFT, null, false), + buildKeyData( + Type.kDown, + PHYSICAL_CONTROL_LEFT, + LOGICAL_CONTROL_LEFT, + null, + false, + DeviceType.kKeyboard), }); calls.clear(); @@ -977,7 +1047,13 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_CONTROL_LEFT, LOGICAL_CONTROL_LEFT, null, false), + buildKeyData( + Type.kUp, + PHYSICAL_CONTROL_LEFT, + LOGICAL_CONTROL_LEFT, + null, + false, + DeviceType.kKeyboard), }); calls.clear(); @@ -987,7 +1063,13 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_CONTROL_RIGHT, LOGICAL_CONTROL_RIGHT, null, false), + buildKeyData( + Type.kDown, + PHYSICAL_CONTROL_RIGHT, + LOGICAL_CONTROL_RIGHT, + null, + false, + DeviceType.kKeyboard), }); calls.clear(); @@ -996,7 +1078,13 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_CONTROL_RIGHT, LOGICAL_CONTROL_RIGHT, null, false), + buildKeyData( + Type.kUp, + PHYSICAL_CONTROL_RIGHT, + LOGICAL_CONTROL_RIGHT, + null, + false, + DeviceType.kKeyboard), }); calls.clear(); @@ -1006,7 +1094,8 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_ALT_LEFT, LOGICAL_ALT_LEFT, null, false), + buildKeyData( + Type.kDown, PHYSICAL_ALT_LEFT, LOGICAL_ALT_LEFT, null, false, DeviceType.kKeyboard), }); calls.clear(); @@ -1015,7 +1104,8 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_ALT_LEFT, LOGICAL_ALT_LEFT, null, false), + buildKeyData( + Type.kUp, PHYSICAL_ALT_LEFT, LOGICAL_ALT_LEFT, null, false, DeviceType.kKeyboard), }); calls.clear(); @@ -1025,7 +1115,8 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_ALT_RIGHT, LOGICAL_ALT_RIGHT, null, false), + buildKeyData( + Type.kDown, PHYSICAL_ALT_RIGHT, LOGICAL_ALT_RIGHT, null, false, DeviceType.kKeyboard), }); calls.clear(); @@ -1034,7 +1125,8 @@ public void modifierKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_ALT_RIGHT, LOGICAL_ALT_RIGHT, null, false), + buildKeyData( + Type.kUp, PHYSICAL_ALT_RIGHT, LOGICAL_ALT_RIGHT, null, false, DeviceType.kKeyboard), }); calls.clear(); } @@ -1053,7 +1145,8 @@ public void nonUsKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_DIGIT1, LOGICAL_DIGIT1, "1", false), + buildKeyData( + Type.kDown, PHYSICAL_DIGIT1, LOGICAL_DIGIT1, "1", false, DeviceType.kKeyboard), }); calls.clear(); @@ -1062,7 +1155,8 @@ public void nonUsKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_DIGIT1, LOGICAL_DIGIT1, null, false), + buildKeyData( + Type.kUp, PHYSICAL_DIGIT1, LOGICAL_DIGIT1, null, false, DeviceType.kKeyboard), }); calls.clear(); @@ -1076,7 +1170,8 @@ public void nonUsKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_DIGIT1, LOGICAL_DIGIT1, "&", false), + buildKeyData( + Type.kDown, PHYSICAL_DIGIT1, LOGICAL_DIGIT1, "&", false, DeviceType.kKeyboard), }); calls.clear(); @@ -1085,7 +1180,8 @@ public void nonUsKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_DIGIT1, LOGICAL_DIGIT1, null, false), + buildKeyData( + Type.kUp, PHYSICAL_DIGIT1, LOGICAL_DIGIT1, null, false, DeviceType.kKeyboard), }); calls.clear(); @@ -1099,7 +1195,7 @@ public void nonUsKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "ф", false), + buildKeyData(Type.kDown, PHYSICAL_KEY_A, LOGICAL_KEY_A, "ф", false, DeviceType.kKeyboard), }); calls.clear(); @@ -1108,7 +1204,7 @@ public void nonUsKeys() { verifyEmbedderEvents( calls, new KeyData[] { - buildKeyData(Type.kUp, PHYSICAL_KEY_A, LOGICAL_KEY_A, null, false), + buildKeyData(Type.kUp, PHYSICAL_KEY_A, LOGICAL_KEY_A, null, false, DeviceType.kKeyboard), }); calls.clear(); } @@ -1131,7 +1227,13 @@ public void synchronizeShiftLeftDuringForeignKeyEvents() { ACTION_DOWN, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', SHIFT_LEFT_ON))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, true); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + true, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1140,7 +1242,13 @@ public void synchronizeShiftLeftDuringForeignKeyEvents() { new FakeKeyEvent(ACTION_UP, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', 0))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, true); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + true, + DeviceType.kKeyboard); calls.clear(); } @@ -1165,7 +1273,13 @@ public void synchronizeShiftLeftDuringSelfKeyEvents() { ACTION_DOWN, SCAN_SHIFT_LEFT, KEYCODE_SHIFT_LEFT, 1, '\0', SHIFT_LEFT_ON))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); // Down event when the current state is 1. @@ -1176,9 +1290,21 @@ public void synchronizeShiftLeftDuringSelfKeyEvents() { ACTION_DOWN, SCAN_SHIFT_LEFT, KEYCODE_SHIFT_LEFT, 0, '\0', SHIFT_LEFT_ON))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, true); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + true, + DeviceType.kKeyboard); assertEmbedderEventEquals( - calls.get(1).keyData, Type.kDown, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false); + calls.get(1).keyData, + Type.kDown, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); // Up event when the current state is 1. @@ -1188,7 +1314,13 @@ public void synchronizeShiftLeftDuringSelfKeyEvents() { new FakeKeyEvent(ACTION_UP, SCAN_SHIFT_LEFT, KEYCODE_SHIFT_LEFT, 0, '\0', 0))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); // Up event when the current state is 0. @@ -1197,7 +1329,8 @@ public void synchronizeShiftLeftDuringSelfKeyEvents() { tester.keyboardManager.handleEvent( new FakeKeyEvent(ACTION_UP, SCAN_SHIFT_LEFT, KEYCODE_SHIFT_LEFT, 0, '\0', 0))); assertEquals(calls.size(), 1); - assertEmbedderEventEquals(calls.get(0).keyData, Type.kDown, 0l, 0l, null, true); + assertEmbedderEventEquals( + calls.get(0).keyData, Type.kDown, 0l, 0l, null, true, DeviceType.kKeyboard); calls.clear(); // Down event when the current state is 0. @@ -1208,7 +1341,13 @@ public void synchronizeShiftLeftDuringSelfKeyEvents() { ACTION_DOWN, SCAN_SHIFT_LEFT, KEYCODE_SHIFT_LEFT, 0, '\0', SHIFT_LEFT_ON))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); // Repeat event when the current state is 1. @@ -1219,7 +1358,13 @@ public void synchronizeShiftLeftDuringSelfKeyEvents() { ACTION_DOWN, SCAN_SHIFT_LEFT, KEYCODE_SHIFT_LEFT, 1, '\0', SHIFT_LEFT_ON))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kRepeat, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false); + calls.get(0).keyData, + Type.kRepeat, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); } @@ -1314,7 +1459,13 @@ public void synchronizeOtherModifiers() { ACTION_DOWN, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', META_CTRL_ON))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_CONTROL_LEFT, LOGICAL_CONTROL_LEFT, null, true); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_CONTROL_LEFT, + LOGICAL_CONTROL_LEFT, + null, + true, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1323,7 +1474,13 @@ public void synchronizeOtherModifiers() { new FakeKeyEvent(ACTION_UP, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', 0))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_CONTROL_LEFT, LOGICAL_CONTROL_LEFT, null, true); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_CONTROL_LEFT, + LOGICAL_CONTROL_LEFT, + null, + true, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1333,7 +1490,13 @@ public void synchronizeOtherModifiers() { ACTION_DOWN, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', META_ALT_ON))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_ALT_LEFT, LOGICAL_ALT_LEFT, null, true); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_ALT_LEFT, + LOGICAL_ALT_LEFT, + null, + true, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1342,7 +1505,13 @@ public void synchronizeOtherModifiers() { new FakeKeyEvent(ACTION_UP, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', 0))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_ALT_LEFT, LOGICAL_ALT_LEFT, null, true); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_ALT_LEFT, + LOGICAL_ALT_LEFT, + null, + true, + DeviceType.kKeyboard); calls.clear(); } @@ -1367,9 +1536,21 @@ public void synchronizeModifiersForConflictingMetaState() { new FakeKeyEvent(ACTION_DOWN, SCAN_SHIFT_LEFT, KEYCODE_SHIFT_LEFT, 0, '\0', 0))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard); assertEmbedderEventEquals( - calls.get(1).keyData, Type.kUp, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, true); + calls.get(1).keyData, + Type.kUp, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + true, + DeviceType.kKeyboard); calls.clear(); // A normal down event. @@ -1380,7 +1561,13 @@ public void synchronizeModifiersForConflictingMetaState() { ACTION_DOWN, SCAN_SHIFT_LEFT, KEYCODE_SHIFT_LEFT, 0, '\0', SHIFT_LEFT_ON))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); // Test: Repeat event when the current state is 0. @@ -1390,9 +1577,21 @@ public void synchronizeModifiersForConflictingMetaState() { new FakeKeyEvent(ACTION_DOWN, SCAN_SHIFT_LEFT, KEYCODE_SHIFT_LEFT, 1, '\0', 0))); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kRepeat, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, false); + calls.get(0).keyData, + Type.kRepeat, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard); assertEmbedderEventEquals( - calls.get(1).keyData, Type.kUp, PHYSICAL_SHIFT_LEFT, LOGICAL_SHIFT_LEFT, null, true); + calls.get(1).keyData, + Type.kUp, + PHYSICAL_SHIFT_LEFT, + LOGICAL_SHIFT_LEFT, + null, + true, + DeviceType.kKeyboard); calls.clear(); } @@ -1415,9 +1614,21 @@ public void synchronizeModifiersForZeroedScanCode() { assertEquals(tester.keyboardManager.handleEvent(keyEvent), true); assertEquals(calls.size(), 2); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, physicalKey, LOGICAL_SHIFT_LEFT, null, false); + calls.get(0).keyData, + Type.kDown, + physicalKey, + LOGICAL_SHIFT_LEFT, + null, + false, + DeviceType.kKeyboard); assertEmbedderEventEquals( - calls.get(1).keyData, Type.kUp, physicalKey, LOGICAL_SHIFT_LEFT, null, true); + calls.get(1).keyData, + Type.kUp, + physicalKey, + LOGICAL_SHIFT_LEFT, + null, + true, + DeviceType.kKeyboard); calls.clear(); } @@ -1439,7 +1650,13 @@ public void normalCapsLockEvents() { ACTION_DOWN, SCAN_CAPS_LOCK, KEYCODE_CAPS_LOCK, 0, '\0', META_CAPS_LOCK_ON))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1448,7 +1665,13 @@ public void normalCapsLockEvents() { new FakeKeyEvent(ACTION_UP, SCAN_CAPS_LOCK, KEYCODE_CAPS_LOCK, 0, '\0', 0))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, false); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1458,7 +1681,13 @@ public void normalCapsLockEvents() { ACTION_DOWN, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', META_CAPS_LOCK_ON))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_ARROW_LEFT, LOGICAL_ARROW_LEFT, null, false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_ARROW_LEFT, + LOGICAL_ARROW_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1468,7 +1697,13 @@ public void normalCapsLockEvents() { ACTION_UP, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', META_CAPS_LOCK_ON))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_ARROW_LEFT, LOGICAL_ARROW_LEFT, null, false); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_ARROW_LEFT, + LOGICAL_ARROW_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1478,7 +1713,13 @@ public void normalCapsLockEvents() { ACTION_DOWN, SCAN_CAPS_LOCK, KEYCODE_CAPS_LOCK, 0, '\0', META_CAPS_LOCK_ON))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1487,7 +1728,13 @@ public void normalCapsLockEvents() { new FakeKeyEvent(ACTION_UP, SCAN_CAPS_LOCK, KEYCODE_CAPS_LOCK, 0, '\0', 0))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, false); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1496,7 +1743,13 @@ public void normalCapsLockEvents() { new FakeKeyEvent(ACTION_DOWN, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', 0))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_ARROW_LEFT, LOGICAL_ARROW_LEFT, null, false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_ARROW_LEFT, + LOGICAL_ARROW_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1505,7 +1758,13 @@ public void normalCapsLockEvents() { new FakeKeyEvent(ACTION_UP, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', 0))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_ARROW_LEFT, LOGICAL_ARROW_LEFT, null, false); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_ARROW_LEFT, + LOGICAL_ARROW_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); } @@ -1524,11 +1783,29 @@ public void synchronizeCapsLock() { ACTION_DOWN, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', META_CAPS_LOCK_ON))); assertEquals(calls.size(), 3); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, true); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + true, + DeviceType.kKeyboard); assertEmbedderEventEquals( - calls.get(1).keyData, Type.kUp, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, true); + calls.get(1).keyData, + Type.kUp, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + true, + DeviceType.kKeyboard); assertEmbedderEventEquals( - calls.get(2).keyData, Type.kDown, PHYSICAL_ARROW_LEFT, LOGICAL_ARROW_LEFT, null, false); + calls.get(2).keyData, + Type.kDown, + PHYSICAL_ARROW_LEFT, + LOGICAL_ARROW_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1538,7 +1815,13 @@ public void synchronizeCapsLock() { ACTION_DOWN, SCAN_CAPS_LOCK, KEYCODE_CAPS_LOCK, 0, '\0', META_CAPS_LOCK_ON))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kDown, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, false); + calls.get(0).keyData, + Type.kDown, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1548,11 +1831,29 @@ public void synchronizeCapsLock() { ACTION_UP, SCAN_ARROW_LEFT, KEYCODE_DPAD_LEFT, 0, '\0', META_CAPS_LOCK_ON))); assertEquals(calls.size(), 3); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, true); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + true, + DeviceType.kKeyboard); assertEmbedderEventEquals( - calls.get(1).keyData, Type.kDown, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, true); + calls.get(1).keyData, + Type.kDown, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + true, + DeviceType.kKeyboard); assertEmbedderEventEquals( - calls.get(2).keyData, Type.kUp, PHYSICAL_ARROW_LEFT, LOGICAL_ARROW_LEFT, null, false); + calls.get(2).keyData, + Type.kUp, + PHYSICAL_ARROW_LEFT, + LOGICAL_ARROW_LEFT, + null, + false, + DeviceType.kKeyboard); calls.clear(); assertEquals( @@ -1561,7 +1862,13 @@ public void synchronizeCapsLock() { new FakeKeyEvent(ACTION_UP, SCAN_CAPS_LOCK, KEYCODE_CAPS_LOCK, 0, '\0', 0))); assertEquals(calls.size(), 1); assertEmbedderEventEquals( - calls.get(0).keyData, Type.kUp, PHYSICAL_CAPS_LOCK, LOGICAL_CAPS_LOCK, null, false); + calls.get(0).keyData, + Type.kUp, + PHYSICAL_CAPS_LOCK, + LOGICAL_CAPS_LOCK, + null, + false, + DeviceType.kKeyboard); calls.clear(); } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm b/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm index ef488f3384a79..f385c23b59c62 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponder.mm @@ -611,6 +611,7 @@ - (void)synthesizeCapsLockTapWithTimestamp:(NSTimeInterval)timestamp { .logical = kCapsLockLogicalKey, .character = nil, .synthesized = true, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; _sendEvent(flutterEvent, nullptr, nullptr); @@ -645,6 +646,7 @@ - (void)sendEmptyEvent { .logical = 0, .character = nil, .synthesized = false, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; _sendEvent(event, nil, nil); } @@ -665,6 +667,7 @@ - (void)synthesizeModifierEventOfType:(BOOL)isDownEvent .logical = logicalKey, .character = nil, .synthesized = true, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; [self updateKey:physicalKey asPressed:isDownEvent ? logicalKey : 0]; _sendEvent(flutterEvent, nullptr, nullptr); @@ -711,6 +714,7 @@ - (void)handlePressBegin:(nonnull FlutterUIPressProxy*)press .character = specialKey != nil ? nil : getEventCharacters(press.key.characters, press.key.keyCode), .synthesized = false, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; [self sendPrimaryFlutterEvent:flutterEvent callback:callback]; } @@ -744,6 +748,7 @@ - (void)handlePressEnd:(nonnull FlutterUIPressProxy*)press .logical = [pressedLogicalKey unsignedLongLongValue], .character = nil, .synthesized = false, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; [self sendPrimaryFlutterEvent:flutterEvent callback:callback]; } diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponderTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponderTest.mm index 0aac9fdaf3926..5e0ebab0ca624 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponderTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEmbedderKeyResponderTest.mm @@ -147,6 +147,7 @@ - (void)testBasicKeyEvent API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->timestamp, 123000000.0f); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); @@ -169,6 +170,7 @@ - (void)testBasicKeyEvent API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->timestamp, 123000000.0f); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); @@ -207,6 +209,7 @@ - (void)testIosKeyPlane API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kKeyCodeEject | kIosPlane); XCTAssertEqual(event->logical, kKeyCodeEject | kIosPlane); XCTAssertEqual(event->character, nullptr); @@ -228,6 +231,7 @@ - (void)testIosKeyPlane API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kKeyCodeEject | kIosPlane); XCTAssertEqual(event->logical, kKeyCodeEject | kIosPlane); XCTAssertEqual(event->character, nullptr); @@ -262,6 +266,7 @@ - (void)testOutOfOrderModifiers API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalAltRight); XCTAssertEqual(event->logical, kLogicalAltRight); XCTAssertEqual(event->character, nullptr); @@ -277,6 +282,7 @@ - (void)testOutOfOrderModifiers API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyW); XCTAssertEqual(event->logical, kLogicalKeyW); XCTAssertStrEqual(event->character, "∑"); @@ -293,6 +299,7 @@ - (void)testOutOfOrderModifiers API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalAltRight); XCTAssertEqual(event->logical, kLogicalAltRight); XCTAssertEqual(event->character, nullptr); @@ -312,6 +319,7 @@ - (void)testOutOfOrderModifiers API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyW); XCTAssertEqual(event->logical, kLogicalKeyW); XCTAssertEqual(event->character, nullptr); @@ -328,6 +336,7 @@ - (void)testOutOfOrderModifiers API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertStrEqual(event->character, "å"); @@ -356,6 +365,7 @@ - (void)testIgnoreDuplicateDownEvent API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertStrEqual(event->character, "a"); @@ -391,6 +401,7 @@ - (void)testIgnoreDuplicateDownEvent API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertEqual(event->character, nullptr); @@ -456,6 +467,7 @@ - (void)testToggleModifiersDuringKeyTap API_AVAILABLE(ios(13.4)) { event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->timestamp, 123000000.0f); XCTAssertEqual(event->physical, kPhysicalShiftRight); XCTAssertEqual(event->logical, kLogicalShiftRight); @@ -472,6 +484,7 @@ - (void)testToggleModifiersDuringKeyTap API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertStrEqual(event->character, "A"); @@ -487,6 +500,7 @@ - (void)testToggleModifiersDuringKeyTap API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalShiftRight); XCTAssertEqual(event->logical, kLogicalShiftRight); XCTAssertEqual(event->character, nullptr); @@ -502,6 +516,7 @@ - (void)testToggleModifiersDuringKeyTap API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertEqual(event->character, nullptr); @@ -543,6 +558,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalNumpad1); XCTAssertEqual(event->logical, kLogicalNumpad1); XCTAssertStrEqual(event->character, "1"); @@ -559,6 +575,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyUndefined); XCTAssertEqual(event->logical, kLogicalKeyUndefined); XCTAssertEqual(event->character, nullptr); @@ -575,6 +592,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalF1); XCTAssertEqual(event->logical, kLogicalF1); XCTAssertEqual(event->character, nullptr); @@ -591,6 +609,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertStrEqual(event->character, "a"); @@ -607,6 +626,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalShiftLeft); XCTAssertEqual(event->logical, kLogicalShiftLeft); XCTAssertEqual(event->character, nullptr); @@ -625,6 +645,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { // have to simulate a keyup. event = [events firstObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalShiftLeft); XCTAssertEqual(event->logical, kLogicalShiftLeft); XCTAssertEqual(event->character, nullptr); @@ -632,6 +653,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalNumpad1); XCTAssertEqual(event->logical, kLogicalNumpad1); XCTAssertEqual(event->character, nullptr); @@ -648,6 +670,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalF1); XCTAssertEqual(event->logical, kLogicalF1); XCTAssertEqual(event->character, nullptr); @@ -664,6 +687,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyUndefined); XCTAssertEqual(event->logical, kLogicalKeyUndefined); XCTAssertEqual(event->synthesized, false); @@ -679,6 +703,7 @@ - (void)testSpecialModiferFlags API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertEqual(event->character, nullptr); @@ -722,6 +747,7 @@ - (void)testIdentifyLeftAndRightModifiers API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalShiftLeft); XCTAssertEqual(event->logical, kLogicalShiftLeft); XCTAssertEqual(event->character, nullptr); @@ -737,6 +763,7 @@ - (void)testIdentifyLeftAndRightModifiers API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalShiftRight); XCTAssertEqual(event->logical, kLogicalShiftRight); XCTAssertEqual(event->character, nullptr); @@ -752,6 +779,7 @@ - (void)testIdentifyLeftAndRightModifiers API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalShiftLeft); XCTAssertEqual(event->logical, kLogicalShiftLeft); XCTAssertEqual(event->character, nullptr); @@ -767,6 +795,7 @@ - (void)testIdentifyLeftAndRightModifiers API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalShiftRight); XCTAssertEqual(event->logical, kLogicalShiftRight); XCTAssertEqual(event->character, nullptr); @@ -801,6 +830,7 @@ - (void)testSynchronizeCapsLockStateOnCapsLock API_AVAILABLE(ios(13.4)) { event = events[0].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalCapsLock); XCTAssertEqual(event->logical, kLogicalCapsLock); XCTAssertEqual(event->character, nullptr); @@ -809,6 +839,7 @@ - (void)testSynchronizeCapsLockStateOnCapsLock API_AVAILABLE(ios(13.4)) { event = events[1].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalCapsLock); XCTAssertEqual(event->logical, kLogicalCapsLock); XCTAssertEqual(event->character, nullptr); @@ -817,6 +848,7 @@ - (void)testSynchronizeCapsLockStateOnCapsLock API_AVAILABLE(ios(13.4)) { event = events[2].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertStrEqual(event->character, "A"); @@ -835,6 +867,7 @@ - (void)testSynchronizeCapsLockStateOnCapsLock API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertEqual(event->synthesized, false); @@ -850,6 +883,7 @@ - (void)testSynchronizeCapsLockStateOnCapsLock API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events firstObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalCapsLock); XCTAssertEqual(event->logical, kLogicalCapsLock); XCTAssertEqual(event->character, nullptr); @@ -869,6 +903,7 @@ - (void)testSynchronizeCapsLockStateOnCapsLock API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events firstObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalCapsLock); XCTAssertEqual(event->logical, kLogicalCapsLock); XCTAssertEqual(event->character, nullptr); @@ -886,6 +921,7 @@ - (void)testSynchronizeCapsLockStateOnCapsLock API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = [events lastObject].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertStrEqual(event->character, "a"); @@ -918,6 +954,7 @@ - (void)testSynchronizeCapsLockStateOnNormalKey API_AVAILABLE(ios(13.4)) { event = events[0].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalCapsLock); XCTAssertEqual(event->logical, kLogicalCapsLock); XCTAssertEqual(event->character, nullptr); @@ -926,6 +963,7 @@ - (void)testSynchronizeCapsLockStateOnNormalKey API_AVAILABLE(ios(13.4)) { event = events[1].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalCapsLock); XCTAssertEqual(event->logical, kLogicalCapsLock); XCTAssertEqual(event->character, nullptr); @@ -934,6 +972,7 @@ - (void)testSynchronizeCapsLockStateOnNormalKey API_AVAILABLE(ios(13.4)) { event = events[2].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalKeyA); XCTAssertEqual(event->logical, kLogicalKeyA); XCTAssertStrEqual(event->character, "A"); @@ -967,6 +1006,7 @@ - (void)testCommandPeriodKey API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = events[0].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalMetaLeft); XCTAssertEqual(event->logical, kLogicalMetaLeft); XCTAssertEqual(event->character, nullptr); @@ -980,6 +1020,7 @@ - (void)testCommandPeriodKey API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = events[0].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeDown); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalPeriod); XCTAssertEqual(event->logical, kLogicalEscape); XCTAssertEqual(event->character, nullptr); @@ -993,6 +1034,7 @@ - (void)testCommandPeriodKey API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = events[0].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalPeriod); XCTAssertEqual(event->logical, kLogicalEscape); XCTAssertEqual(event->character, nullptr); @@ -1005,6 +1047,7 @@ - (void)testCommandPeriodKey API_AVAILABLE(ios(13.4)) { XCTAssertEqual([events count], 1u); event = events[0].data; XCTAssertEqual(event->type, kFlutterKeyEventTypeUp); + XCTAssertEqual(event->device_type, kFlutterKeyEventDeviceTypeKeyboard); XCTAssertEqual(event->physical, kPhysicalMetaLeft); XCTAssertEqual(event->logical, kLogicalMetaLeft); XCTAssertEqual(event->character, nullptr); diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 24fbb0b92afe9..174fa8a47ef6e 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -2352,6 +2352,23 @@ static inline flutter::KeyEventType MapKeyEventType( return flutter::KeyEventType::kUp; } +static inline flutter::KeyEventDeviceType MapKeyEventDeviceType( + FlutterKeyEventDeviceType event_kind) { + switch (event_kind) { + case kFlutterKeyEventDeviceTypeKeyboard: + return flutter::KeyEventDeviceType::kKeyboard; + case kFlutterKeyEventDeviceTypeDirectionalPad: + return flutter::KeyEventDeviceType::kDirectionalPad; + case kFlutterKeyEventDeviceTypeGamepad: + return flutter::KeyEventDeviceType::kGamepad; + case kFlutterKeyEventDeviceTypeJoystick: + return flutter::KeyEventDeviceType::kJoystick; + case kFlutterKeyEventDeviceTypeHdmi: + return flutter::KeyEventDeviceType::kHdmi; + } + return flutter::KeyEventDeviceType::kKeyboard; +} + // Send a platform message to the framework. // // The `data_callback` will be invoked with `user_data`, and must not be empty. @@ -2414,6 +2431,9 @@ FlutterEngineResult FlutterEngineSendKeyEvent(FLUTTER_API_SYMBOL(FlutterEngine) key_data.physical = SAFE_ACCESS(event, physical, 0); key_data.logical = SAFE_ACCESS(event, logical, 0); key_data.synthesized = SAFE_ACCESS(event, synthesized, false); + key_data.device_type = MapKeyEventDeviceType(SAFE_ACCESS( + event, device_type, + FlutterKeyEventDeviceType::kFlutterKeyEventDeviceTypeKeyboard)); auto packet = std::make_unique(key_data, character); diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index cfef518dcf6fe..1d9bb0a98f340 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -969,6 +969,14 @@ typedef enum { kFlutterKeyEventTypeRepeat, } FlutterKeyEventType; +typedef enum { + kFlutterKeyEventDeviceTypeKeyboard = 1, + kFlutterKeyEventDeviceTypeDirectionalPad, + kFlutterKeyEventDeviceTypeGamepad, + kFlutterKeyEventDeviceTypeJoystick, + kFlutterKeyEventDeviceTypeHdmi, +} FlutterKeyEventDeviceType; + /// A structure to represent a key event. /// /// Sending `FlutterKeyEvent` via `FlutterEngineSendKeyEvent` results in a @@ -1032,6 +1040,8 @@ typedef struct { /// An event being synthesized means that the `timestamp` might greatly /// deviate from the actual time when the event occurs physically. bool synthesized; + /// The source device for the key event. + FlutterKeyEventDeviceType device_type; } FlutterKeyEvent; typedef void (*FlutterKeyEventCallback)(bool /* handled */, diff --git a/shell/platform/embedder/fixtures/main.dart b/shell/platform/embedder/fixtures/main.dart index 81cc224868c11..7687dca71437f 100644 --- a/shell/platform/embedder/fixtures/main.dart +++ b/shell/platform/embedder/fixtures/main.dart @@ -116,7 +116,7 @@ Future get semanticsActionEvent { } @pragma('vm:entry-point') -void a11y_main() async { +Future a11y_main() async { // 1: Return initial state (semantics disabled). notifySemanticsEnabled(PlatformDispatcher.instance.semanticsEnabled); @@ -291,7 +291,7 @@ void a11y_main() async { } @pragma('vm:entry-point') -void a11y_string_attributes() async { +Future a11y_string_attributes() async { // 1: Wait until semantics are enabled. if (!PlatformDispatcher.instance.semanticsEnabled) { await semanticsChanged; @@ -379,7 +379,7 @@ void platform_messages_response() { void platform_messages_no_response() { PlatformDispatcher.instance.onPlatformMessage = (String name, ByteData? data, PlatformMessageResponseCallback? callback) { - var list = data!.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); + final Uint8List list = data!.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes); signalNativeMessage(utf8.decode(list)); // This does nothing because no one is listening on the other side. But complete the loop anyway // to make sure all null checking on response handles in the engine is in place. @@ -400,10 +400,10 @@ void null_platform_messages() { } Picture CreateSimplePicture() { - Paint blackPaint = Paint(); - Paint whitePaint = Paint()..color = Color.fromARGB(255, 255, 255, 255); - PictureRecorder baseRecorder = PictureRecorder(); - Canvas canvas = Canvas(baseRecorder); + final Paint blackPaint = Paint(); + final Paint whitePaint = Paint()..color = Color.fromARGB(255, 255, 255, 255); + final PictureRecorder baseRecorder = PictureRecorder(); + final Canvas canvas = Canvas(baseRecorder); canvas.drawRect(Rect.fromLTRB(0.0, 0.0, 1000.0, 1000.0), blackPaint); canvas.drawRect(Rect.fromLTRB(10.0, 10.0, 990.0, 990.0), whitePaint); return baseRecorder.endRecording(); @@ -412,7 +412,7 @@ Picture CreateSimplePicture() { @pragma('vm:entry-point') void can_composite_platform_views() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.addPicture(Offset(1.0, 1.0), CreateSimplePicture()); builder.pushOffset(1.0, 2.0); builder.addPlatformView(42, width: 123.0, height: 456.0); @@ -428,7 +428,7 @@ void can_composite_platform_views() { @pragma('vm:entry-point') void can_composite_platform_views_with_opacity() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); // Root node builder.pushOffset(1.0, 2.0); @@ -458,7 +458,7 @@ void can_composite_platform_views_with_opacity() { @pragma('vm:entry-point') void can_composite_with_opacity() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOpacity(127); builder.addPicture(Offset(1.0, 1.0), CreateSimplePicture()); builder.pop(); // offset @@ -470,10 +470,10 @@ void can_composite_with_opacity() { } Picture CreateColoredBox(Color color, Size size) { - Paint paint = Paint(); + final Paint paint = Paint(); paint.color = color; - PictureRecorder baseRecorder = PictureRecorder(); - Canvas canvas = Canvas(baseRecorder); + final PictureRecorder baseRecorder = PictureRecorder(); + final Canvas canvas = Canvas(baseRecorder); canvas.drawRect(Rect.fromLTRB(0.0, 0.0, size.width, size.height), paint); return baseRecorder.endRecording(); } @@ -481,13 +481,13 @@ Picture CreateColoredBox(Color color, Size size) { @pragma('vm:entry-point') void can_composite_platform_views_with_known_scene() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Color red = Color.fromARGB(127, 255, 0, 0); - Color blue = Color.fromARGB(127, 0, 0, 255); - Color gray = Color.fromARGB(127, 127, 127, 127); + final Color red = Color.fromARGB(127, 255, 0, 0); + final Color blue = Color.fromARGB(127, 0, 0, 255); + final Color gray = Color.fromARGB(127, 127, 127, 127); - Size size = Size(50.0, 150.0); + final Size size = Size(50.0, 150.0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); // 10 (Index 0) @@ -527,13 +527,13 @@ void can_composite_platform_views_with_known_scene() { @pragma('vm:entry-point') void can_composite_platform_views_transparent_overlay() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Color red = Color.fromARGB(127, 255, 0, 0); - Color blue = Color.fromARGB(127, 0, 0, 255); - Color transparent = Color(0xFFFFFF); + final Color red = Color.fromARGB(127, 255, 0, 0); + final Color blue = Color.fromARGB(127, 0, 0, 255); + final Color transparent = Color(0xFFFFFF); - Size size = Size(50.0, 150.0); + final Size size = Size(50.0, 150.0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); // 10 (Index 0) @@ -563,12 +563,12 @@ void can_composite_platform_views_transparent_overlay() { @pragma('vm:entry-point') void can_composite_platform_views_no_overlay() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Color red = Color.fromARGB(127, 255, 0, 0); - Color blue = Color.fromARGB(127, 0, 0, 255); + final Color red = Color.fromARGB(127, 255, 0, 0); + final Color blue = Color.fromARGB(127, 0, 0, 255); - Size size = Size(50.0, 150.0); + final Size size = Size(50.0, 150.0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); // 10 (Index 0) @@ -594,10 +594,10 @@ void can_composite_platform_views_no_overlay() { @pragma('vm:entry-point') void can_composite_platform_views_with_root_layer_only() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Color red = Color.fromARGB(127, 255, 0, 0); - Size size = Size(50.0, 150.0); + final Color red = Color.fromARGB(127, 255, 0, 0); + final Size size = Size(50.0, 150.0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); // 10 (Index 0) @@ -616,10 +616,10 @@ void can_composite_platform_views_with_root_layer_only() { @pragma('vm:entry-point') void can_composite_platform_views_with_platform_layer_on_bottom() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Color red = Color.fromARGB(127, 255, 0, 0); - Size size = Size(50.0, 150.0); + final Color red = Color.fromARGB(127, 255, 0, 0); + final Size size = Size(50.0, 150.0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); // 10 (Index 0) @@ -645,11 +645,11 @@ void can_composite_platform_views_with_platform_layer_on_bottom() { external void signalBeginFrame(); @pragma('vm:entry-point') -void texture_destruction_callback_called_without_custom_compositor() async { +Future texture_destruction_callback_called_without_custom_compositor() async { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Color red = Color.fromARGB(127, 255, 0, 0); - Size size = Size(50.0, 150.0); - SceneBuilder builder = SceneBuilder(); + final Color red = Color.fromARGB(127, 255, 0, 0); + final Size size = Size(50.0, 150.0); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); builder.addPicture( Offset(10.0, 10.0), CreateColoredBox(red, size)); // red - flutter @@ -663,15 +663,15 @@ void texture_destruction_callback_called_without_custom_compositor() async { @pragma('vm:entry-point') void can_render_scene_without_custom_compositor() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Color red = Color.fromARGB(127, 255, 0, 0); - Color green = Color.fromARGB(127, 0, 255, 0); - Color blue = Color.fromARGB(127, 0, 0, 255); - Color magenta = Color.fromARGB(127, 255, 0, 255); - Color gray = Color.fromARGB(127, 127, 127, 127); + final Color red = Color.fromARGB(127, 255, 0, 0); + final Color green = Color.fromARGB(127, 0, 255, 0); + final Color blue = Color.fromARGB(127, 0, 0, 255); + final Color magenta = Color.fromARGB(127, 255, 0, 255); + final Color gray = Color.fromARGB(127, 127, 127, 127); - Size size = Size(50.0, 150.0); + final Size size = Size(50.0, 150.0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); @@ -698,8 +698,8 @@ void can_render_scene_without_custom_compositor() { } Picture CreateGradientBox(Size size) { - Paint paint = Paint(); - List rainbow = [ + final Paint paint = Paint(); + final List rainbow = [ Color.fromARGB(255, 255, 0, 0), // red Color.fromARGB(255, 255, 165, 0), // orange Color.fromARGB(255, 255, 255, 0), // yellow @@ -708,7 +708,7 @@ Picture CreateGradientBox(Size size) { Color.fromARGB(255, 75, 0, 130), // indigo Color.fromARGB(255, 238, 130, 238), // violet ]; - List stops = [ + final List stops = [ (1.0 / 7.0), (2.0 / 7.0), (3.0 / 7.0), @@ -719,19 +719,19 @@ Picture CreateGradientBox(Size size) { ]; paint.shader = Gradient.linear( Offset(0.0, 0.0), Offset(size.width, size.height), rainbow, stops); - PictureRecorder baseRecorder = PictureRecorder(); - Canvas canvas = Canvas(baseRecorder); + final PictureRecorder baseRecorder = PictureRecorder(); + final Canvas canvas = Canvas(baseRecorder); canvas.drawRect(Rect.fromLTRB(0.0, 0.0, size.width, size.height), paint); return baseRecorder.endRecording(); } @pragma('vm:external-name', 'EchoKeyEvent') external void _echoKeyEvent(int change, int timestamp, int physical, - int logical, int charCode, bool synthesized); + int logical, int charCode, bool synthesized, int deviceType); // Convert `kind` in enum form to its integer form. // -// It performs a reversed mapping from `unserializeKeyEventKind` +// It performs a reversed mapping from `UnserializeKeyEventType` // in shell/platform/embedder/tests/embedder_unittests.cc. int _serializeKeyEventType(KeyEventType change) { switch (change) { @@ -744,9 +744,28 @@ int _serializeKeyEventType(KeyEventType change) { } } +// Convert `deviceType` in enum form to its integer form. +// +// It performs a reversed mapping from `UnserializeKeyEventDeviceType` +// in shell/platform/embedder/tests/embedder_unittests.cc. +int _serializeKeyEventDeviceType(KeyEventDeviceType deviceType) { + switch (deviceType) { + case KeyEventDeviceType.keyboard: + return 1; + case KeyEventDeviceType.directionalPad: + return 2; + case KeyEventDeviceType.gamepad: + return 3; + case KeyEventDeviceType.joystick: + return 4; + case KeyEventDeviceType.hdmi: + return 5; + } +} + // Echo the event data with `_echoKeyEvent`, and returns synthesized as handled. @pragma('vm:entry-point') -void key_data_echo() async { +Future key_data_echo() async { PlatformDispatcher.instance.onKeyData = (KeyData data) { _echoKeyEvent( _serializeKeyEventType(data.type), @@ -755,6 +774,7 @@ void key_data_echo() async { data.logical, data.character == null ? 0 : data.character!.codeUnitAt(0), data.synthesized, + _serializeKeyEventDeviceType(data.deviceType), ); return data.synthesized; }; @@ -764,7 +784,7 @@ void key_data_echo() async { // After platform channel 'test/starts_echo' receives a message, starts echoing // the event data with `_echoKeyEvent`, and returns synthesized as handled. @pragma('vm:entry-point') -void key_data_late_echo() async { +Future key_data_late_echo() async { channelBuffers.setListener('test/starts_echo', (ByteData? data, PlatformMessageResponseCallback callback) { PlatformDispatcher.instance.onKeyData = (KeyData data) { @@ -775,6 +795,7 @@ void key_data_late_echo() async { data.logical, data.character == null ? 0 : data.character!.codeUnitAt(0), data.synthesized, + _serializeKeyEventDeviceType(data.deviceType), ); return data.synthesized; }; @@ -786,9 +807,9 @@ void key_data_late_echo() async { @pragma('vm:entry-point') void render_gradient() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Size size = Size(800.0, 600.0); + final Size size = Size(800.0, 600.0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); @@ -805,9 +826,9 @@ void render_gradient() { @pragma('vm:entry-point') void render_texture() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Size size = Size(800.0, 600.0); + final Size size = Size(800.0, 600.0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); @@ -823,10 +844,10 @@ void render_texture() { @pragma('vm:entry-point') void render_gradient_on_non_root_backing_store() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Size size = Size(800.0, 600.0); - Color red = Color.fromARGB(127, 255, 0, 0); + final Size size = Size(800.0, 600.0); + final Color red = Color.fromARGB(127, 255, 0, 0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); @@ -851,20 +872,20 @@ void verify_b141980393() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { // The platform view in the test case is screen sized but with margins of 31 // and 37 points from the top and bottom. - double top_margin = 31.0; - double bottom_margin = 37.0; - Size platform_view_size = Size(800.0, 600.0 - top_margin - bottom_margin); + const double topMargin = 31.0; + const double bottomMargin = 37.0; + final Size platformViewSize = Size(800.0, 600.0 - topMargin - bottomMargin); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset( 0.0, // x - top_margin // y + topMargin // y ); // The web view in example. builder.addPlatformView(1337, - width: platform_view_size.width, height: platform_view_size.height); + width: platformViewSize.width, height: platformViewSize.height); builder.pop(); @@ -876,8 +897,8 @@ void verify_b141980393() { @pragma('vm:entry-point') void can_display_platform_view_with_pixel_ratio() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); - builder.pushTransform(Float64List.fromList([ + final SceneBuilder builder = SceneBuilder(); + builder.pushTransform(Float64List.fromList([ 2.0, 0.0, 0.0, @@ -919,7 +940,7 @@ void can_receive_locale_updates() { @pragma('vm:entry-point') void verify_b143464703() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); // base // Background @@ -957,7 +978,7 @@ void verify_b143464703() { @pragma('vm:entry-point') void push_frames_over_and_over() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); builder.addPicture( Offset(0.0, 0.0), @@ -977,7 +998,7 @@ void push_frames_over_and_over() { @pragma('vm:entry-point') void platform_view_mutators() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); // base builder.addPicture(Offset(0.0, 0.0), CreateGradientBox(Size(800.0, 600.0))); @@ -999,7 +1020,7 @@ void platform_view_mutators() { @pragma('vm:entry-point') void platform_view_mutators_with_pixel_ratio() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); // base builder.addPicture(Offset(0.0, 0.0), CreateGradientBox(Size(400.0, 300.0))); @@ -1030,7 +1051,7 @@ void empty_scene() { @pragma('vm:entry-point') void scene_with_no_container() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.addPicture(Offset(0.0, 0.0), CreateGradientBox(Size(400.0, 300.0))); PlatformDispatcher.instance.views.first.render(builder.build()); signalNativeTest(); @@ -1039,10 +1060,10 @@ void scene_with_no_container() { } Picture CreateArcEndCapsPicture() { - PictureRecorder baseRecorder = PictureRecorder(); - Canvas canvas = Canvas(baseRecorder); + final PictureRecorder baseRecorder = PictureRecorder(); + final Canvas canvas = Canvas(baseRecorder); - var style = Paint() + final style = Paint() ..strokeWidth = 12.0 ..style = PaintingStyle.stroke ..strokeCap = StrokeCap.round @@ -1058,7 +1079,7 @@ Picture CreateArcEndCapsPicture() { @pragma('vm:entry-point') void arc_end_caps_correct() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.addPicture(Offset(0.0, 0.0), CreateArcEndCapsPicture()); PlatformDispatcher.instance.views.first.render(builder.build()); }; @@ -1068,7 +1089,7 @@ void arc_end_caps_correct() { @pragma('vm:entry-point') void scene_builder_with_clips() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushClipRect(Rect.fromLTRB(10.0, 10.0, 390.0, 290.0)); builder.addPlatformView(42, width: 400.0, height: 300.0); builder.addPicture(Offset(0.0, 0.0), CreateGradientBox(Size(400.0, 300.0))); @@ -1080,7 +1101,7 @@ void scene_builder_with_clips() { @pragma('vm:entry-point') void scene_builder_with_complex_clips() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.pushClipRect(Rect.fromLTRB(0.0, 0.0, 1024.0, 600.0)); builder.pushOffset(512.0, 0.0); @@ -1101,7 +1122,7 @@ external void sendObjectToNativeCode(dynamic object); @pragma('vm:entry-point') void objects_can_be_posted() { - ReceivePort port = ReceivePort(); + final ReceivePort port = ReceivePort(); port.listen((dynamic message) { sendObjectToNativeCode(message); }); @@ -1111,7 +1132,7 @@ void objects_can_be_posted() { @pragma('vm:entry-point') void empty_scene_posts_zero_layers_to_compositor() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); // Should not render anything. builder.pushClipRect(Rect.fromLTRB(0.0, 0.0, 300.0, 200.0)); PlatformDispatcher.instance.views.first.render(builder.build()); @@ -1122,7 +1143,7 @@ void empty_scene_posts_zero_layers_to_compositor() { @pragma('vm:entry-point') void compositor_can_post_only_platform_views() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); builder.addPlatformView(42, width: 300.0, height: 200.0); builder.addPlatformView(24, width: 300.0, height: 200.0); PlatformDispatcher.instance.views.first.render(builder.build()); @@ -1132,16 +1153,16 @@ void compositor_can_post_only_platform_views() { @pragma('vm:entry-point') void render_targets_are_recycled() { - int frame_count = 0; + int frameCount = 0; PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); for (int i = 0; i < 10; i++) { builder.addPicture(Offset(0.0, 0.0), CreateGradientBox(Size(30.0, 20.0))); builder.addPlatformView(42 + i, width: 30.0, height: 20.0); } PlatformDispatcher.instance.views.first.render(builder.build()); - frame_count++; - if (frame_count == 8) { + frameCount++; + if (frameCount == 8) { signalNativeTest(); } else { PlatformDispatcher.instance.scheduleFrame(); @@ -1152,17 +1173,17 @@ void render_targets_are_recycled() { @pragma('vm:entry-point') void render_targets_are_in_stable_order() { - int frame_count = 0; + int frameCount = 0; PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); for (int i = 0; i < 10; i++) { builder.addPicture(Offset(0.0, 0.0), CreateGradientBox(Size(30.0, 20.0))); builder.addPlatformView(42 + i, width: 30.0, height: 20.0); } PlatformDispatcher.instance.views.first.render(builder.build()); PlatformDispatcher.instance.scheduleFrame(); - frame_count++; - if (frame_count == 8) { + frameCount++; + if (frameCount == 8) { signalNativeTest(); } }; @@ -1174,7 +1195,7 @@ external void nativeArgumentsCallback(List args); @pragma('vm:entry-point') void custom_logger(List args) { - print("hello world"); + print('hello world'); } @pragma('vm:entry-point') @@ -1183,17 +1204,17 @@ void dart_entrypoint_args(List args) { } @pragma('vm:external-name', 'SnapshotsCallback') -external void snapshotsCallback(Image big_image, Image small_image); +external void snapshotsCallback(Image bigImage, Image smallImage); @pragma('vm:entry-point') -void snapshot_large_scene(int max_size) async { +Future snapshot_large_scene(int maxSize) async { // Set width to double the max size, which will result in height being half the max size after scaling. - double width = max_size * 2.0, height = max_size.toDouble(); + double width = maxSize * 2.0, height = maxSize.toDouble(); PictureRecorder recorder = PictureRecorder(); { - Canvas canvas = Canvas(recorder, Rect.fromLTWH(0, 0, width, height)); - Paint paint = Paint(); + final Canvas canvas = Canvas(recorder, Rect.fromLTWH(0, 0, width, height)); + final Paint paint = Paint(); // Bottom left paint.color = Color.fromARGB(255, 100, 255, 100); canvas.drawRect(Rect.fromLTWH(0, height / 2, width / 2, height / 2), paint); @@ -1202,31 +1223,31 @@ void snapshot_large_scene(int max_size) async { canvas.drawRect(Rect.fromLTWH(width / 2, 0, width / 2, height / 2), paint); } Picture picture = recorder.endRecording(); - Image big_image = await picture.toImage(width.toInt(), height.toInt()); + final Image bigImage = await picture.toImage(width.toInt(), height.toInt()); // The max size varies across hardware/drivers, so normalize the result to a smaller target size in // order to reliably test against an image fixture. - double small_width = 128, small_height = 64; + double smallWidth = 128, smallHeight = 64; recorder = PictureRecorder(); { - Canvas canvas = - Canvas(recorder, Rect.fromLTWH(0, 0, small_width, small_height)); - canvas.scale(small_width / big_image.width); - canvas.drawImage(big_image, Offset.zero, Paint()); + final Canvas canvas = + Canvas(recorder, Rect.fromLTWH(0, 0, smallWidth, smallHeight)); + canvas.scale(smallWidth / bigImage.width); + canvas.drawImage(bigImage, Offset.zero, Paint()); } picture = recorder.endRecording(); - Image small_image = - await picture.toImage(small_width.toInt(), small_height.toInt()); + final Image smallImage = + await picture.toImage(smallWidth.toInt(), smallHeight.toInt()); - snapshotsCallback(big_image, small_image); + snapshotsCallback(bigImage, smallImage); } @pragma('vm:entry-point') void invalid_backingstore() { PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Color red = Color.fromARGB(127, 255, 0, 0); - Size size = Size(50.0, 150.0); - SceneBuilder builder = SceneBuilder(); + final Color red = Color.fromARGB(127, 255, 0, 0); + final Size size = Size(50.0, 150.0); + final SceneBuilder builder = SceneBuilder(); builder.pushOffset(0.0, 0.0); builder.addPicture( Offset(10.0, 10.0), CreateColoredBox(red, size)); // red - flutter @@ -1291,7 +1312,7 @@ void pointer_data_packet() { } @pragma('vm:entry-point') -void channel_listener_response() async { +Future channel_listener_response() async { channelBuffers.setListener('test/listen', (ByteData? data, PlatformMessageResponseCallback callback) { callback(null); @@ -1303,9 +1324,9 @@ void channel_listener_response() async { void render_gradient_retained() { OffsetEngineLayer? offsetLayer; // Retain the offset layer. PlatformDispatcher.instance.onBeginFrame = (Duration duration) { - Size size = Size(800.0, 600.0); + final Size size = Size(800.0, 600.0); - SceneBuilder builder = SceneBuilder(); + final SceneBuilder builder = SceneBuilder(); offsetLayer = builder.pushOffset(0.0, 0.0, oldLayer: offsetLayer); diff --git a/shell/platform/embedder/tests/embedder_unittests.cc b/shell/platform/embedder/tests/embedder_unittests.cc index f872ccc1962ec..377ea7dced8ec 100644 --- a/shell/platform/embedder/tests/embedder_unittests.cc +++ b/shell/platform/embedder/tests/embedder_unittests.cc @@ -2082,7 +2082,7 @@ typedef struct { // // It performs a revesed mapping from `_serializeKeyEventType` // in shell/platform/embedder/fixtures/main.dart. -FlutterKeyEventType UnserializeKeyEventKind(uint64_t kind) { +FlutterKeyEventType UnserializeKeyEventType(uint64_t kind) { switch (kind) { case 1: return kFlutterKeyEventTypeUp; @@ -2096,6 +2096,28 @@ FlutterKeyEventType UnserializeKeyEventKind(uint64_t kind) { } } +// Convert `source` in integer form to its enum form. +// +// It performs a revesed mapping from `_serializeKeyEventDeviceType` +// in shell/platform/embedder/fixtures/main.dart. +FlutterKeyEventDeviceType UnserializeKeyEventDeviceType(uint64_t source) { + switch (source) { + case 1: + return kFlutterKeyEventDeviceTypeKeyboard; + case 2: + return kFlutterKeyEventDeviceTypeDirectionalPad; + case 3: + return kFlutterKeyEventDeviceTypeGamepad; + case 4: + return kFlutterKeyEventDeviceTypeJoystick; + case 5: + return kFlutterKeyEventDeviceTypeHdmi; + default: + FML_UNREACHABLE(); + return kFlutterKeyEventDeviceTypeKeyboard; + } +} + // Checks the equality of two `FlutterKeyEvent` by each of their members except // for `character`. The `character` must be checked separately. void ExpectKeyEventEq(const FlutterKeyEvent& subject, @@ -2105,16 +2127,18 @@ void ExpectKeyEventEq(const FlutterKeyEvent& subject, EXPECT_EQ(subject.physical, baseline.physical); EXPECT_EQ(subject.logical, baseline.logical); EXPECT_EQ(subject.synthesized, baseline.synthesized); + EXPECT_EQ(subject.device_type, baseline.device_type); } TEST_F(EmbedderTest, KeyDataIsCorrectlySerialized) { auto message_latch = std::make_shared(); uint64_t echoed_char; FlutterKeyEvent echoed_event; + echoed_event.struct_size = sizeof(FlutterKeyEvent); auto native_echo_event = [&](Dart_NativeArguments args) { echoed_event.type = - UnserializeKeyEventKind(tonic::DartConverter::FromDart( + UnserializeKeyEventType(tonic::DartConverter::FromDart( Dart_GetNativeArgument(args, 0))); echoed_event.timestamp = static_cast(tonic::DartConverter::FromDart( @@ -2127,6 +2151,9 @@ TEST_F(EmbedderTest, KeyDataIsCorrectlySerialized) { Dart_GetNativeArgument(args, 4)); echoed_event.synthesized = tonic::DartConverter::FromDart(Dart_GetNativeArgument(args, 5)); + echoed_event.device_type = + UnserializeKeyEventDeviceType(tonic::DartConverter::FromDart( + Dart_GetNativeArgument(args, 6))); message_latch->Signal(); }; @@ -2157,6 +2184,7 @@ TEST_F(EmbedderTest, KeyDataIsCorrectlySerialized) { .logical = 0x00000000061, .character = "A", .synthesized = false, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; FlutterEngineSendKeyEvent(engine.get(), &down_event_upper_a, nullptr, nullptr); @@ -2174,6 +2202,7 @@ TEST_F(EmbedderTest, KeyDataIsCorrectlySerialized) { .logical = 0x00000000062, .character = "∆", .synthesized = false, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; FlutterEngineSendKeyEvent(engine.get(), &repeat_event_wide_char, nullptr, nullptr); @@ -2191,6 +2220,7 @@ TEST_F(EmbedderTest, KeyDataIsCorrectlySerialized) { .logical = 0x00000000063, .character = nullptr, .synthesized = true, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; FlutterEngineSendKeyEvent(engine.get(), &up_event, nullptr, nullptr); message_latch->Wait(); @@ -2209,7 +2239,7 @@ TEST_F(EmbedderTest, KeyDataAreBuffered) { static_cast(tonic::DartConverter::FromDart( Dart_GetNativeArgument(args, 1))), .type = - UnserializeKeyEventKind(tonic::DartConverter::FromDart( + UnserializeKeyEventType(tonic::DartConverter::FromDart( Dart_GetNativeArgument(args, 0))), .physical = tonic::DartConverter::FromDart( Dart_GetNativeArgument(args, 2)), @@ -2217,6 +2247,9 @@ TEST_F(EmbedderTest, KeyDataAreBuffered) { Dart_GetNativeArgument(args, 3)), .synthesized = tonic::DartConverter::FromDart( Dart_GetNativeArgument(args, 5)), + .device_type = UnserializeKeyEventDeviceType( + tonic::DartConverter::FromDart( + Dart_GetNativeArgument(args, 6))), }); message_latch->Signal(); @@ -2246,6 +2279,7 @@ TEST_F(EmbedderTest, KeyDataAreBuffered) { .logical = 0x00000000061, .character = "A", .synthesized = false, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; // Send an event. @@ -2329,6 +2363,7 @@ TEST_F(EmbedderTest, KeyDataResponseIsCorrectlyInvoked) { .physical = 0x00070005, .logical = 0x00000000062, .character = nullptr, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; KeyEventUserData user_data1{ @@ -2405,6 +2440,7 @@ TEST_F(EmbedderTest, BackToBackKeyEventResponsesCorrectlyInvoked) { .logical = 0x00000000062, .character = nullptr, .synthesized = false, + .device_type = kFlutterKeyEventDeviceTypeKeyboard, }; // Dispatch two events back to back, using the same callback on different