Skip to content

Commit

Permalink
ui.KeyData.toString (#28007)
Browse files Browse the repository at this point in the history
Enhances ui.KeyData.toString by:
- Fixing the character interpretation;
- Adding hex representation to characters;
- Applying the code to the web engine which is currently missing.
  • Loading branch information
dkwingsmt committed Aug 11, 2021
1 parent 05c819f commit 833b4f1
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 17 deletions.
55 changes: 39 additions & 16 deletions lib/ui/key.dart
Original file line number Diff line number Diff line change
Expand Up @@ -112,21 +112,36 @@ class KeyData {
}

String _logicalToString() {
String result = '0x${logical.toRadixString(16)}';
final int nonValueBits = _nonValueBits(logical);
if (nonValueBits & 0x0FF == 0x000) {
result += '(Unicode)';
}
if (nonValueBits & 0x0FF == 0x001) {
result += '(HID)';
}
if (nonValueBits & 0x100 != 0x000) {
result += '(auto)';
}
if (nonValueBits & 0x200 != 0x000) {
result += '(synonym)';
}
return result;
final String result = '0x${logical.toRadixString(16)}';
final int planeNum = _nonValueBits(logical) & 0x0FF;
final String planeDescription = (() {
switch (planeNum) {
case 0x000:
return ' (Unicode)';
case 0x001:
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 '';
})();
return '$result$planeDescription';
}

String? _escapeCharacter() {
Expand All @@ -149,9 +164,17 @@ class KeyData {
}
}

String? _quotedCharCode() {
if (character == null)
return '';
final Iterable<String> hexChars = character!.codeUnits
.map((int code) => code.toRadixString(16).padLeft(2, '0'));
return ' (0x${hexChars.join(' ')})';
}

@override
String toString() => 'KeyData(key ${_typeToString(type)}, physical: 0x${physical.toRadixString(16)}, '
'logical: ${_logicalToString()}, character: ${_escapeCharacter()})';
'logical: ${_logicalToString()}, character: ${_escapeCharacter()}${_quotedCharCode()}${synthesized ? ', synthesized' : ''})';

/// Returns a complete textual description of the information in this object.
String toStringFull() {
Expand Down
55 changes: 54 additions & 1 deletion lib/web_ui/lib/src/ui/key.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,62 @@ class KeyData {
/// [KeyRepeatEvent] is never synthesized.
final bool synthesized;

String _logicalToString() {
final String result = '0x${logical.toRadixString(16)}';
// Find the bits that are not included in `valueMask`, shifted to the right.
// For example, if [logical] is 0x12abcdabcd, then the result is 0x12.
//
// This is mostly equivalent to a right shift, resolving the problem that
// JavaScript only support 32-bit bitwise operations and needs to use
// division instead.
final int planeNum = (logical / 0x100000000).floor();
final String planeDescription = (() {
switch (planeNum) {
case 0x000:
return ' (Unicode)';
case 0x001:
return ' (Unprintable)';
case 0x002:
return ' (Flutter)';
case 0x017:
return ' (Web)';
}
return '';
})();
return '$result$planeDescription';
}

String? _escapeCharacter() {
if (character == null) {
return character ?? '<none>';
}
switch (character!) {
case '\n':
return r'"\n"';
case '\t':
return r'"\t"';
case '\r':
return r'"\r"';
case '\b':
return r'"\b"';
case '\f':
return r'"\f"';
default:
return '"$character"';
}
}

String? _quotedCharCode() {
if (character == null)
return '';
final Iterable<String> hexChars = character!.codeUnits
.map((int code) => code.toRadixString(16).padLeft(2, '0'));
return ' (0x${hexChars.join(' ')})';
}

@override
String toString() => 'KeyData(type: ${_typeToString(type)}, physical: 0x${physical.toRadixString(16)}, '
'logical: 0x${logical.toRadixString(16)}, character: $character)';
'logical: ${_logicalToString()}, character: ${_escapeCharacter()}${_quotedCharCode()}${synthesized ? ', synthesized' : ''})';

/// Returns a complete textual description of the information in this object.
String toStringFull() {
Expand Down
29 changes: 29 additions & 0 deletions lib/web_ui/test/keyboard_converter_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,35 @@ void main() {
}

void testMain() {
test('KeyData.toString', () {
expect(const ui.KeyData(
type: ui.KeyEventType.down,
physical: 0x700e5,
logical: 0x61,
character: 'A',
timeStamp: Duration.zero,
synthesized: false,
).toString(), 'KeyData(type: down, physical: 0x700e5, logical: 0x61 (Unicode), character: "A" (0x41))');

expect(const ui.KeyData(
type: ui.KeyEventType.up,
physical: 0x700e6,
logical: 0x100000061,
character: '\n',
timeStamp: Duration.zero,
synthesized: true,
).toString(), r'KeyData(type: up, physical: 0x700e6, logical: 0x100000061 (Unprintable), character: "\n" (0x0a), synthesized)');

expect(const ui.KeyData(
type: ui.KeyEventType.repeat,
physical: 0x700e7,
logical: 0x9900000071,
character: null,
timeStamp: Duration.zero,
synthesized: false,
).toString(), 'KeyData(type: repeat, physical: 0x700e7, logical: 0x9900000071, character: <none>)');
});

test('Single key press, repeat, and release', () {
final List<ui.KeyData> keyDataList = <ui.KeyData>[];
final KeyboardConverter converter = KeyboardConverter((ui.KeyData key) {
Expand Down

0 comments on commit 833b4f1

Please sign in to comment.