Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
a7899c19
Unverified
Commit
a7899c19
authored
Jul 29, 2021
by
Tong Mu
Committed by
GitHub
Jul 29, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[gen_keycodes] Remove nonexistent Web keys and improve their emulation (#87098)
parent
c451b6b0
Changes
8
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
175 additions
and
738 deletions
+175
-738
logical_key_data.json
dev/tools/gen_keycodes/data/logical_key_data.json
+21
-506
logical_key_data.dart
dev/tools/gen_keycodes/lib/logical_key_data.dart
+31
-27
gen_keycodes_test.dart
dev/tools/gen_keycodes/test/gen_keycodes_test.dart
+25
-50
keyboard_maps.dart
packages/flutter/lib/src/services/keyboard_maps.dart
+0
-144
raw_keyboard.dart
packages/flutter/lib/src/services/raw_keyboard.dart
+3
-3
raw_keyboard_web.dart
packages/flutter/lib/src/services/raw_keyboard_web.dart
+15
-3
raw_keyboard_test.dart
packages/flutter/test/services/raw_keyboard_test.dart
+26
-0
event_simulation.dart
packages/flutter_test/lib/src/event_simulation.dart
+54
-5
No files found.
dev/tools/gen_keycodes/data/logical_key_data.json
View file @
a7899c19
This diff is collapsed.
Click to expand it.
dev/tools/gen_keycodes/lib/logical_key_data.dart
View file @
a7899c19
...
@@ -11,11 +11,7 @@ import 'package:path/path.dart' as path;
...
@@ -11,11 +11,7 @@ import 'package:path/path.dart' as path;
import
'constants.dart'
;
import
'constants.dart'
;
import
'physical_key_data.dart'
;
import
'physical_key_data.dart'
;
bool
_isControlCharacter
(
String
label
)
{
bool
_isControlCharacter
(
int
codeUnit
)
{
if
(
label
.
length
!=
1
)
{
return
false
;
}
final
int
codeUnit
=
label
.
codeUnitAt
(
0
);
return
(
codeUnit
<=
0x1f
&&
codeUnit
>=
0x00
)
||
(
codeUnit
>=
0x7f
&&
codeUnit
<=
0x9f
);
return
(
codeUnit
<=
0x1f
&&
codeUnit
>=
0x00
)
||
(
codeUnit
>=
0x7f
&&
codeUnit
<=
0x9f
);
}
}
...
@@ -27,8 +23,11 @@ class _ModifierPair {
...
@@ -27,8 +23,11 @@ class _ModifierPair {
final
String
right
;
final
String
right
;
}
}
List
<
T
>
_toNonEmptyArray
<
T
>(
dynamic
source
)
{
// Return map[key1][key2] as a non-nullable List<T>, where both map[key1] or
final
List
<
dynamic
>?
dynamicNullableList
=
source
as
List
<
dynamic
>?;
// map[key1][key2] might be null.
List
<
T
>
_getGrandchildList
<
T
>(
Map
<
String
,
dynamic
>
map
,
String
key1
,
String
key2
)
{
final
dynamic
value
=
(
map
[
key1
]
as
Map
<
String
,
dynamic
>?)?[
key2
];
final
List
<
dynamic
>?
dynamicNullableList
=
value
as
List
<
dynamic
>?;
final
List
<
dynamic
>
dynamicList
=
dynamicNullableList
??
<
dynamic
>[];
final
List
<
dynamic
>
dynamicList
=
dynamicNullableList
??
<
dynamic
>[];
return
dynamicList
.
cast
<
T
>();
return
dynamicList
.
cast
<
T
>();
}
}
...
@@ -155,20 +154,23 @@ class LogicalKeyData {
...
@@ -155,20 +154,23 @@ class LogicalKeyData {
final
int
value
=
match
.
namedGroup
(
'unicode'
)
!=
null
?
final
int
value
=
match
.
namedGroup
(
'unicode'
)
!=
null
?
getHex
(
match
.
namedGroup
(
'unicode'
)!)
:
getHex
(
match
.
namedGroup
(
'unicode'
)!)
:
match
.
namedGroup
(
'char'
)!.
codeUnitAt
(
0
);
match
.
namedGroup
(
'char'
)!.
codeUnitAt
(
0
);
final
String
?
keyLabel
=
match
.
namedGroup
(
'kind'
)!
==
'UNI'
?
String
.
fromCharCode
(
value
)
:
null
;
final
String
?
keyLabel
=
(
match
.
namedGroup
(
'kind'
)!
==
'UNI'
&&
!
_isControlCharacter
(
value
))
?
String
.
fromCharCode
(
value
)
:
null
;
// Skip modifier keys from DOM. They will be added with supplemental data.
// Skip modifier keys from DOM. They will be added with supplemental data.
if
(
_chromeModifiers
.
containsKey
(
name
)
&&
source
==
'DOM'
)
{
if
(
_chromeModifiers
.
containsKey
(
name
)
&&
source
==
'DOM'
)
{
continue
;
continue
;
}
}
final
bool
isPrintable
=
(
keyLabel
!=
null
&&
!
_isControlCharacter
(
keyLabel
))
final
bool
isPrintable
=
keyLabel
!=
null
;
||
printable
.
containsKey
(
name
);
data
.
putIfAbsent
(
name
,
()
{
data
.
putIfAbsent
(
name
,
()
{
return
LogicalKeyEntry
.
fromName
(
final
LogicalKeyEntry
entry
=
LogicalKeyEntry
.
fromName
(
value:
toPlane
(
value
,
_sourceToPlane
(
source
,
isPrintable
)),
value:
toPlane
(
value
,
_sourceToPlane
(
source
,
isPrintable
)),
name:
name
,
name:
name
,
keyLabel:
keyLabel
,
keyLabel:
keyLabel
,
)..
webNames
.
add
(
webName
);
);
if
(
source
==
'DOM'
&&
!
isPrintable
)
entry
.
webNames
.
add
(
webName
);
return
entry
;
});
});
}
}
}
}
...
@@ -418,9 +420,11 @@ class LogicalKeyData {
...
@@ -418,9 +420,11 @@ class LogicalKeyData {
})();
})();
static
int
_sourceToPlane
(
String
source
,
bool
isPrintable
)
{
static
int
_sourceToPlane
(
String
source
,
bool
isPrintable
)
{
if
(
isPrintable
)
return
kUnicodePlane
.
value
;
switch
(
source
)
{
switch
(
source
)
{
case
'DOM'
:
case
'DOM'
:
return
isPrintable
?
kUnicodePlane
.
value
:
kUnprintablePlane
.
value
;
return
kUnprintablePlane
.
value
;
case
'FLUTTER'
:
case
'FLUTTER'
:
return
kFlutterPlane
.
value
;
return
kFlutterPlane
.
value
;
default
:
default
:
...
@@ -470,20 +474,20 @@ class LogicalKeyEntry {
...
@@ -470,20 +474,20 @@ class LogicalKeyEntry {
LogicalKeyEntry
.
fromJsonMapEntry
(
Map
<
String
,
dynamic
>
map
)
LogicalKeyEntry
.
fromJsonMapEntry
(
Map
<
String
,
dynamic
>
map
)
:
value
=
map
[
'value'
]
as
int
,
:
value
=
map
[
'value'
]
as
int
,
name
=
map
[
'name'
]
as
String
,
name
=
map
[
'name'
]
as
String
,
webNames
=
_
toNonEmptyArray
<
String
>((
map
[
'names'
]
as
Map
<
String
,
dynamic
>)[
'web'
]
),
webNames
=
_
getGrandchildList
<
String
>(
map
,
'names'
,
'web'
),
macOSKeyCodeNames
=
_
toNonEmptyArray
<
String
>((
map
[
'names'
]
as
Map
<
String
,
dynamic
>)[
'macos'
]
),
macOSKeyCodeNames
=
_
getGrandchildList
<
String
>(
map
,
'names'
,
'macos'
),
macOSKeyCodeValues
=
_
toNonEmptyArray
<
int
>((
map
[
'values'
]
as
Map
<
String
,
dynamic
>?)?[
'macos'
]
),
macOSKeyCodeValues
=
_
getGrandchildList
<
int
>(
map
,
'values'
,
'macos'
),
iOSKeyCodeNames
=
_
toNonEmptyArray
<
String
>((
map
[
'names'
]
as
Map
<
String
,
dynamic
>)[
'ios'
]
),
iOSKeyCodeNames
=
_
getGrandchildList
<
String
>(
map
,
'names'
,
'ios'
),
iOSKeyCodeValues
=
_
toNonEmptyArray
<
int
>((
map
[
'values'
]
as
Map
<
String
,
dynamic
>?)?[
'ios'
]
),
iOSKeyCodeValues
=
_
getGrandchildList
<
int
>(
map
,
'values'
,
'ios'
),
gtkNames
=
_
toNonEmptyArray
<
String
>((
map
[
'names'
]
as
Map
<
String
,
dynamic
>)[
'gtk'
]
),
gtkNames
=
_
getGrandchildList
<
String
>(
map
,
'names'
,
'gtk'
),
gtkValues
=
_
toNonEmptyArray
<
int
>((
map
[
'values'
]
as
Map
<
String
,
dynamic
>?)?[
'gtk'
]
),
gtkValues
=
_
getGrandchildList
<
int
>(
map
,
'values'
,
'gtk'
),
windowsNames
=
_
toNonEmptyArray
<
String
>((
map
[
'names'
]
as
Map
<
String
,
dynamic
>)[
'windows'
]
),
windowsNames
=
_
getGrandchildList
<
String
>(
map
,
'names'
,
'windows'
),
windowsValues
=
_
toNonEmptyArray
<
int
>((
map
[
'values'
]
as
Map
<
String
,
dynamic
>?)?[
'windows'
]
),
windowsValues
=
_
getGrandchildList
<
int
>(
map
,
'values'
,
'windows'
),
androidNames
=
_
toNonEmptyArray
<
String
>((
map
[
'names'
]
as
Map
<
String
,
dynamic
>)[
'android'
]
),
androidNames
=
_
getGrandchildList
<
String
>(
map
,
'names'
,
'android'
),
androidValues
=
_
toNonEmptyArray
<
int
>((
map
[
'values'
]
as
Map
<
String
,
dynamic
>?)?[
'android'
]
),
androidValues
=
_
getGrandchildList
<
int
>(
map
,
'values'
,
'android'
),
fuchsiaValues
=
_
toNonEmptyArray
<
int
>((
map
[
'values'
]
as
Map
<
String
,
dynamic
>?)?[
'fuchsia'
]
),
fuchsiaValues
=
_
getGrandchildList
<
int
>(
map
,
'values'
,
'fuchsia'
),
glfwNames
=
_
toNonEmptyArray
<
String
>((
map
[
'names'
]
as
Map
<
String
,
dynamic
>)[
'glfw'
]
),
glfwNames
=
_
getGrandchildList
<
String
>(
map
,
'names'
,
'glfw'
),
glfwValues
=
_
toNonEmptyArray
<
int
>((
map
[
'values'
]
as
Map
<
String
,
dynamic
>?)?[
'glfw'
]
),
glfwValues
=
_
getGrandchildList
<
int
>(
map
,
'values'
,
'glfw'
),
keyLabel
=
map
[
'keyLabel'
]
as
String
?;
keyLabel
=
map
[
'keyLabel'
]
as
String
?;
final
int
value
;
final
int
value
;
...
...
dev/tools/gen_keycodes/test/gen_keycodes_test.dart
View file @
a7899c19
...
@@ -22,8 +22,10 @@ String readDataFile(String fileName) {
...
@@ -22,8 +22,10 @@ String readDataFile(String fileName) {
return
File
(
path
.
join
(
dataRoot
,
fileName
)).
readAsStringSync
();
return
File
(
path
.
join
(
dataRoot
,
fileName
)).
readAsStringSync
();
}
}
final
String
testPhysicalData
=
path
.
join
(
dataRoot
,
'physical_key_data.json'
);
final
PhysicalKeyData
physicalData
=
PhysicalKeyData
.
fromJson
(
final
String
testLogicalData
=
path
.
join
(
dataRoot
,
'logical_key_data.json'
);
json
.
decode
(
readDataFile
(
'physical_key_data.json'
))
as
Map
<
String
,
dynamic
>);
final
LogicalKeyData
logicalData
=
LogicalKeyData
.
fromJson
(
json
.
decode
(
readDataFile
(
'logical_key_data.json'
))
as
Map
<
String
,
dynamic
>);
void
main
(
)
{
void
main
(
)
{
setUp
(()
{
setUp
(()
{
...
@@ -45,14 +47,6 @@ void main() {
...
@@ -45,14 +47,6 @@ void main() {
}
}
test
(
'Generate Keycodes for Android'
,
()
{
test
(
'Generate Keycodes for Android'
,
()
{
PhysicalKeyData
physicalData
;
LogicalKeyData
logicalData
;
physicalData
=
PhysicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testPhysicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
logicalData
=
LogicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testLogicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
const
String
platform
=
'android'
;
const
String
platform
=
'android'
;
final
PlatformCodeGenerator
codeGenerator
=
AndroidCodeGenerator
(
final
PlatformCodeGenerator
codeGenerator
=
AndroidCodeGenerator
(
physicalData
,
physicalData
,
...
@@ -67,14 +61,6 @@ void main() {
...
@@ -67,14 +61,6 @@ void main() {
checkCommonOutput
(
output
);
checkCommonOutput
(
output
);
});
});
test
(
'Generate Keycodes for macOS'
,
()
{
test
(
'Generate Keycodes for macOS'
,
()
{
PhysicalKeyData
physicalData
;
LogicalKeyData
logicalData
;
physicalData
=
PhysicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testPhysicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
logicalData
=
LogicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testLogicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
const
String
platform
=
'macos'
;
const
String
platform
=
'macos'
;
final
PlatformCodeGenerator
codeGenerator
=
MacOSCodeGenerator
(
final
PlatformCodeGenerator
codeGenerator
=
MacOSCodeGenerator
(
physicalData
,
physicalData
,
...
@@ -93,14 +79,6 @@ void main() {
...
@@ -93,14 +79,6 @@ void main() {
checkCommonOutput
(
output
);
checkCommonOutput
(
output
);
});
});
test
(
'Generate Keycodes for iOS'
,
()
{
test
(
'Generate Keycodes for iOS'
,
()
{
PhysicalKeyData
physicalData
;
LogicalKeyData
logicalData
;
physicalData
=
PhysicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testPhysicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
logicalData
=
LogicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testLogicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
const
String
platform
=
'ios'
;
const
String
platform
=
'ios'
;
final
PlatformCodeGenerator
codeGenerator
=
IOSCodeGenerator
(
final
PlatformCodeGenerator
codeGenerator
=
IOSCodeGenerator
(
physicalData
,
physicalData
,
...
@@ -120,14 +98,6 @@ void main() {
...
@@ -120,14 +98,6 @@ void main() {
checkCommonOutput
(
output
);
checkCommonOutput
(
output
);
});
});
test
(
'Generate Keycodes for Windows'
,
()
{
test
(
'Generate Keycodes for Windows'
,
()
{
PhysicalKeyData
physicalData
;
LogicalKeyData
logicalData
;
physicalData
=
PhysicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testPhysicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
logicalData
=
LogicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testLogicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
const
String
platform
=
'windows'
;
const
String
platform
=
'windows'
;
final
PlatformCodeGenerator
codeGenerator
=
WindowsCodeGenerator
(
final
PlatformCodeGenerator
codeGenerator
=
WindowsCodeGenerator
(
physicalData
,
physicalData
,
...
@@ -143,14 +113,6 @@ void main() {
...
@@ -143,14 +113,6 @@ void main() {
checkCommonOutput
(
output
);
checkCommonOutput
(
output
);
});
});
test
(
'Generate Keycodes for Linux'
,
()
{
test
(
'Generate Keycodes for Linux'
,
()
{
PhysicalKeyData
physicalData
;
LogicalKeyData
logicalData
;
physicalData
=
PhysicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testPhysicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
logicalData
=
LogicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testLogicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
const
String
platform
=
'gtk'
;
const
String
platform
=
'gtk'
;
final
PlatformCodeGenerator
codeGenerator
=
GtkCodeGenerator
(
final
PlatformCodeGenerator
codeGenerator
=
GtkCodeGenerator
(
physicalData
,
physicalData
,
...
@@ -166,14 +128,6 @@ void main() {
...
@@ -166,14 +128,6 @@ void main() {
checkCommonOutput
(
output
);
checkCommonOutput
(
output
);
});
});
test
(
'Generate Keycodes for Web'
,
()
{
test
(
'Generate Keycodes for Web'
,
()
{
PhysicalKeyData
physicalData
;
LogicalKeyData
logicalData
;
physicalData
=
PhysicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testPhysicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
logicalData
=
LogicalKeyData
.
fromJson
(
json
.
decode
(
File
(
testLogicalData
).
readAsStringSync
())
as
Map
<
String
,
dynamic
>);
const
String
platform
=
'web'
;
const
String
platform
=
'web'
;
final
PlatformCodeGenerator
codeGenerator
=
WebCodeGenerator
(
final
PlatformCodeGenerator
codeGenerator
=
WebCodeGenerator
(
physicalData
,
physicalData
,
...
@@ -188,4 +142,25 @@ void main() {
...
@@ -188,4 +142,25 @@ void main() {
expect
(
output
,
contains
(
'kWebLogicalLocationMap'
));
expect
(
output
,
contains
(
'kWebLogicalLocationMap'
));
checkCommonOutput
(
output
);
checkCommonOutput
(
output
);
});
});
test
(
'LogicalKeyData'
,
()
async
{
final
List
<
LogicalKeyEntry
>
entries
=
logicalData
.
entries
.
toList
();
// Regression tests for https://github.com/flutter/flutter/pull/87098
expect
(
entries
.
indexWhere
((
LogicalKeyEntry
entry
)
=>
entry
.
name
==
'ShiftLeft'
),
isNot
(-
1
));
expect
(
entries
.
indexWhere
((
LogicalKeyEntry
entry
)
=>
entry
.
webNames
.
contains
(
'ShiftLeft'
)),
-
1
);
// 'Shift' maps to both 'ShiftLeft' and 'ShiftRight', and should be resolved
// by other ways.
expect
(
entries
.
indexWhere
((
LogicalKeyEntry
entry
)
=>
entry
.
webNames
.
contains
(
'Shift'
)),
-
1
);
// Printable keys must not be added with Web key of their names.
expect
(
entries
.
indexWhere
((
LogicalKeyEntry
entry
)
=>
entry
.
webNames
.
contains
(
'Slash'
)),
-
1
);
});
}
}
packages/flutter/lib/src/services/keyboard_maps.dart
View file @
a7899c19
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/services/raw_keyboard.dart
View file @
a7899c19
...
@@ -285,12 +285,10 @@ abstract class RawKeyEvent with Diagnosticable {
...
@@ -285,12 +285,10 @@ abstract class RawKeyEvent with Diagnosticable {
/// Creates a concrete [RawKeyEvent] class from a message in the form received
/// Creates a concrete [RawKeyEvent] class from a message in the form received
/// on the [SystemChannels.keyEvent] channel.
/// on the [SystemChannels.keyEvent] channel.
factory
RawKeyEvent
.
fromMessage
(
Map
<
String
,
dynamic
>
message
)
{
factory
RawKeyEvent
.
fromMessage
(
Map
<
String
,
dynamic
>
message
)
{
final
RawKeyEventData
data
;
String
?
character
;
String
?
character
;
RawKeyEventData
_dataFromWeb
()
{
RawKeyEventData
_dataFromWeb
()
{
final
String
?
key
=
message
[
'key'
]
as
String
?;
final
String
?
key
=
message
[
'key'
]
as
String
?;
if
(
key
!=
null
&&
key
.
isNotEmpty
)
{
if
(
key
!=
null
&&
key
.
isNotEmpty
&&
key
.
length
==
1
)
{
character
=
key
;
character
=
key
;
}
}
return
RawKeyEventDataWeb
(
return
RawKeyEventDataWeb
(
...
@@ -300,6 +298,8 @@ abstract class RawKeyEvent with Diagnosticable {
...
@@ -300,6 +298,8 @@ abstract class RawKeyEvent with Diagnosticable {
metaState:
message
[
'metaState'
]
as
int
?
??
0
,
metaState:
message
[
'metaState'
]
as
int
?
??
0
,
);
);
}
}
final
RawKeyEventData
data
;
if
(
kIsWeb
)
{
if
(
kIsWeb
)
{
data
=
_dataFromWeb
();
data
=
_dataFromWeb
();
}
else
{
}
else
{
...
...
packages/flutter/lib/src/services/raw_keyboard_web.dart
View file @
a7899c19
...
@@ -10,6 +10,13 @@ import 'keyboard_key.dart';
...
@@ -10,6 +10,13 @@ import 'keyboard_key.dart';
import
'keyboard_maps.dart'
;
import
'keyboard_maps.dart'
;
import
'raw_keyboard.dart'
;
import
'raw_keyboard.dart'
;
String
?
_unicodeChar
(
String
key
)
{
if
(
key
.
length
==
1
)
{
return
key
.
substring
(
0
,
1
);
}
return
null
;
}
/// Platform-specific key event data for Web.
/// Platform-specific key event data for Web.
///
///
/// See also:
/// See also:
...
@@ -74,7 +81,7 @@ class RawKeyEventDataWeb extends RawKeyEventData {
...
@@ -74,7 +81,7 @@ class RawKeyEventDataWeb extends RawKeyEventData {
final
int
metaState
;
final
int
metaState
;
@override
@override
String
get
keyLabel
=>
key
==
'Unidentified'
?
''
:
key
;
String
get
keyLabel
=>
key
==
'Unidentified'
?
''
:
_unicodeChar
(
key
)
??
''
;
@override
@override
PhysicalKeyboardKey
get
physicalKey
{
PhysicalKeyboardKey
get
physicalKey
{
...
@@ -95,9 +102,14 @@ class RawKeyEventDataWeb extends RawKeyEventData {
...
@@ -95,9 +102,14 @@ class RawKeyEventDataWeb extends RawKeyEventData {
return
newKey
;
return
newKey
;
}
}
final
bool
isPrintable
=
key
.
length
==
1
;
if
(
isPrintable
)
return
LogicalKeyboardKey
(
key
.
codeUnitAt
(
0
));
// This is a non-printable key that we don't know about, so we mint a new
// This is a non-printable key that we don't know about, so we mint a new
// code.
// key from `code`. Don't mint with `key`, because the `key` will always be
return
LogicalKeyboardKey
(
code
.
hashCode
|
LogicalKeyboardKey
.
webPlane
);
// "Unidentified" .
return
LogicalKeyboardKey
(
code
.
hashCode
+
LogicalKeyboardKey
.
webPlane
);
}
}
@override
@override
...
...
packages/flutter/test/services/raw_keyboard_test.dart
View file @
a7899c19
...
@@ -2400,6 +2400,7 @@ void main() {
...
@@ -2400,6 +2400,7 @@ void main() {
'keymap'
:
'web'
,
'keymap'
:
'web'
,
'code'
:
'KeyA'
,
'code'
:
'KeyA'
,
'key'
:
'a'
,
'key'
:
'a'
,
'location'
:
0
,
'metaState'
:
0x0
,
'metaState'
:
0x0
,
});
});
final
RawKeyEventDataWeb
data
=
keyAEvent
.
data
as
RawKeyEventDataWeb
;
final
RawKeyEventDataWeb
data
=
keyAEvent
.
data
as
RawKeyEventDataWeb
;
...
@@ -2413,6 +2414,8 @@ void main() {
...
@@ -2413,6 +2414,8 @@ void main() {
'type'
:
'keydown'
,
'type'
:
'keydown'
,
'keymap'
:
'web'
,
'keymap'
:
'web'
,
'code'
:
'Escape'
,
'code'
:
'Escape'
,
'key'
:
'Escape'
,
'location'
:
0
,
'metaState'
:
0x0
,
'metaState'
:
0x0
,
});
});
final
RawKeyEventDataWeb
data
=
escapeKeyEvent
.
data
as
RawKeyEventDataWeb
;
final
RawKeyEventDataWeb
data
=
escapeKeyEvent
.
data
as
RawKeyEventDataWeb
;
...
@@ -2426,6 +2429,8 @@ void main() {
...
@@ -2426,6 +2429,8 @@ void main() {
'type'
:
'keydown'
,
'type'
:
'keydown'
,
'keymap'
:
'web'
,
'keymap'
:
'web'
,
'code'
:
'ShiftLeft'
,
'code'
:
'ShiftLeft'
,
'key'
:
'Shift'
,
'location'
:
1
,
'metaState'
:
RawKeyEventDataWeb
.
modifierShift
,
'metaState'
:
RawKeyEventDataWeb
.
modifierShift
,
});
});
final
RawKeyEventDataWeb
data
=
shiftKeyEvent
.
data
as
RawKeyEventDataWeb
;
final
RawKeyEventDataWeb
data
=
shiftKeyEvent
.
data
as
RawKeyEventDataWeb
;
...
@@ -2439,6 +2444,8 @@ void main() {
...
@@ -2439,6 +2444,8 @@ void main() {
'type'
:
'keydown'
,
'type'
:
'keydown'
,
'keymap'
:
'web'
,
'keymap'
:
'web'
,
'code'
:
'ArrowDown'
,
'code'
:
'ArrowDown'
,
'key'
:
'ArrowDown'
,
'location'
:
0
,
'metaState'
:
0x0
,
'metaState'
:
0x0
,
});
});
final
RawKeyEventDataWeb
data
=
arrowKeyDown
.
data
as
RawKeyEventDataWeb
;
final
RawKeyEventDataWeb
data
=
arrowKeyDown
.
data
as
RawKeyEventDataWeb
;
...
@@ -2447,6 +2454,25 @@ void main() {
...
@@ -2447,6 +2454,25 @@ void main() {
expect
(
data
.
keyLabel
,
isEmpty
);
expect
(
data
.
keyLabel
,
isEmpty
);
});
});
test
(
'Unrecognized keys are mapped to Web plane'
,
()
{
final
RawKeyEvent
arrowKeyDown
=
RawKeyEvent
.
fromMessage
(
const
<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'web'
,
'code'
:
'Unrecog1'
,
'key'
:
'Unrecog2'
,
'location'
:
0
,
'metaState'
:
0x0
,
});
final
RawKeyEventDataWeb
data
=
arrowKeyDown
.
data
as
RawKeyEventDataWeb
;
// This might be easily broken on Web if the code fails to acknowledge
// that JavaScript doesn't handle 64-bit bit-wise operation.
expect
(
data
.
physicalKey
.
usbHidUsage
,
greaterThan
(
0x01700000000
));
expect
(
data
.
physicalKey
.
usbHidUsage
,
lessThan
(
0x01800000000
));
expect
(
data
.
logicalKey
.
keyId
,
greaterThan
(
0x01700000000
));
expect
(
data
.
logicalKey
.
keyId
,
lessThan
(
0x01800000000
));
expect
(
data
.
keyLabel
,
isEmpty
);
});
test
(
'data.toString'
,
()
{
test
(
'data.toString'
,
()
{
expect
(
RawKeyEvent
.
fromMessage
(
const
<
String
,
dynamic
>{
expect
(
RawKeyEvent
.
fromMessage
(
const
<
String
,
dynamic
>{
'type'
:
'keydown'
,
'type'
:
'keydown'
,
...
...
packages/flutter_test/lib/src/event_simulation.dart
View file @
a7899c19
...
@@ -14,6 +14,16 @@ import 'package:flutter_test/flutter_test.dart';
...
@@ -14,6 +14,16 @@ import 'package:flutter_test/flutter_test.dart';
import
'binding.dart'
;
import
'binding.dart'
;
import
'test_async_utils.dart'
;
import
'test_async_utils.dart'
;
// A tuple of `key` and `location` from Web's `KeyboardEvent` class.
//
// See [RawKeyEventDataWeb]'s `key` and `location` fields for details.
@immutable
class
_WebKeyLocationPair
{
const
_WebKeyLocationPair
(
this
.
key
,
this
.
location
);
final
String
key
;
final
int
location
;
}
// TODO(gspencergoog): Replace this with more robust key simulation code once
// TODO(gspencergoog): Replace this with more robust key simulation code once
// the new key event code is in.
// the new key event code is in.
// https://github.com/flutter/flutter/issues/33521
// https://github.com/flutter/flutter/issues/33521
...
@@ -145,8 +155,32 @@ class KeyEventSimulator {
...
@@ -145,8 +155,32 @@ class KeyEventSimulator {
}
}
}
}
static
String
_getWebKeyCode
(
LogicalKeyboardKey
key
)
{
static
PhysicalKeyboardKey
_inferPhysicalKey
(
LogicalKeyboardKey
key
)
{
PhysicalKeyboardKey
?
result
;
for
(
final
PhysicalKeyboardKey
physicalKey
in
PhysicalKeyboardKey
.
knownPhysicalKeys
)
{
if
(
physicalKey
.
debugName
==
key
.
debugName
)
{
result
=
physicalKey
;
break
;
}
}
assert
(
result
!=
null
,
'Unable to infer physical key for
$key
'
);
return
result
!;
}
static
_WebKeyLocationPair
_getWebKeyLocation
(
LogicalKeyboardKey
key
,
String
keyLabel
)
{
String
?
result
;
String
?
result
;
for
(
final
MapEntry
<
String
,
List
<
LogicalKeyboardKey
?>>
entry
in
kWebLocationMap
.
entries
)
{
final
int
foundIndex
=
entry
.
value
.
indexOf
(
key
);
// If foundIndex is -1, then the key is not defined in kWebLocationMap.
// If foundIndex is 0, then the key is in the standard part of the keyboard,
// but we have to check `keyLabel` to see if it's remapped or modified.
if
(
foundIndex
!=
-
1
&&
foundIndex
!=
0
)
{
return
_WebKeyLocationPair
(
entry
.
key
,
foundIndex
);
}
}
if
(
keyLabel
.
isNotEmpty
)
{
return
_WebKeyLocationPair
(
keyLabel
,
0
);
}
for
(
final
String
code
in
kWebToLogicalKey
.
keys
)
{
for
(
final
String
code
in
kWebToLogicalKey
.
keys
)
{
if
(
key
.
keyId
==
kWebToLogicalKey
[
code
]!.
keyId
)
{
if
(
key
.
keyId
==
kWebToLogicalKey
[
code
]!.
keyId
)
{
result
=
code
;
result
=
code
;
...
@@ -154,6 +188,18 @@ class KeyEventSimulator {
...
@@ -154,6 +188,18 @@ class KeyEventSimulator {
}
}
}
}
assert
(
result
!=
null
,
'Key
$key
not found in web keyCode map'
);
assert
(
result
!=
null
,
'Key
$key
not found in web keyCode map'
);
return
_WebKeyLocationPair
(
result
!,
0
);
}
static
String
_getWebCode
(
PhysicalKeyboardKey
key
)
{
String
?
result
;
for
(
final
MapEntry
<
String
,
PhysicalKeyboardKey
>
entry
in
kWebToPhysicalKey
.
entries
)
{
if
(
entry
.
value
.
usbHidUsage
==
key
.
usbHidUsage
)
{
result
=
entry
.
key
;
break
;
}
}
assert
(
result
!=
null
,
'Key
$key
not found in web code map'
);
return
result
!;
return
result
!;
}
}
...
@@ -215,8 +261,6 @@ class KeyEventSimulator {
...
@@ -215,8 +261,6 @@ class KeyEventSimulator {
physicalKey
??=
_findPhysicalKeyByPlatform
(
key
,
platform
);
physicalKey
??=
_findPhysicalKeyByPlatform
(
key
,
platform
);
assert
(
key
.
debugName
!=
null
);
assert
(
key
.
debugName
!=
null
);
final
int
keyCode
=
_getKeyCode
(
key
,
platform
);
final
int
scanCode
=
_getScanCode
(
physicalKey
,
platform
);
final
Map
<
String
,
dynamic
>
result
=
<
String
,
dynamic
>{
final
Map
<
String
,
dynamic
>
result
=
<
String
,
dynamic
>{
'type'
:
isDown
?
'keydown'
:
'keyup'
,
'type'
:
isDown
?
'keydown'
:
'keyup'
,
...
@@ -225,14 +269,19 @@ class KeyEventSimulator {
...
@@ -225,14 +269,19 @@ class KeyEventSimulator {
final
String
resultCharacter
=
character
??
_keyLabel
(
key
)
??
''
;
final
String
resultCharacter
=
character
??
_keyLabel
(
key
)
??
''
;
void
assignWeb
()
{
void
assignWeb
()
{
result
[
'code'
]
=
_getWebKeyCode
(
key
);
final
_WebKeyLocationPair
keyLocation
=
_getWebKeyLocation
(
key
,
resultCharacter
);
result
[
'key'
]
=
resultCharacter
;
final
PhysicalKeyboardKey
actualPhysicalKey
=
physicalKey
??
_inferPhysicalKey
(
key
);
result
[
'code'
]
=
_getWebCode
(
actualPhysicalKey
);
result
[
'key'
]
=
keyLocation
.
key
;
result
[
'location'
]
=
keyLocation
.
location
;
result
[
'metaState'
]
=
_getWebModifierFlags
(
key
,
isDown
);
result
[
'metaState'
]
=
_getWebModifierFlags
(
key
,
isDown
);
}
}
if
(
kIsWeb
)
{
if
(
kIsWeb
)
{
assignWeb
();
assignWeb
();
return
result
;
return
result
;
}
}
final
int
keyCode
=
_getKeyCode
(
key
,
platform
);
final
int
scanCode
=
_getScanCode
(
physicalKey
,
platform
);
switch
(
platform
)
{
switch
(
platform
)
{
case
'android'
:
case
'android'
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment