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
a0f7f6ca
Unverified
Commit
a0f7f6ca
authored
Apr 08, 2020
by
Francisco Magdaleno
Committed by
GitHub
Apr 08, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[windows] Adds support for keyboard mapping. (#54227)
parent
45bf8380
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
941 additions
and
43 deletions
+941
-43
raw_keyboard.dart
dev/manual_tests/lib/raw_keyboard.dart
+5
-0
gen_keycodes.dart
dev/tools/gen_keycodes/bin/gen_keycodes.dart
+2
-2
key_data.json
dev/tools/gen_keycodes/data/key_data.json
+25
-32
key_name_to_windows_name.json
dev/tools/gen_keycodes/data/key_name_to_windows_name.json
+4
-4
keyboard_key.tmpl
dev/tools/gen_keycodes/data/keyboard_key.tmpl
+1
-1
keyboard_maps.tmpl
dev/tools/gen_keycodes/data/keyboard_maps.tmpl
+17
-0
dart_code_gen.dart
dev/tools/gen_keycodes/lib/dart_code_gen.dart
+40
-0
services.dart
packages/flutter/lib/services.dart
+1
-0
keyboard_maps.dart
packages/flutter/lib/src/services/keyboard_maps.dart
+303
-0
raw_keyboard.dart
packages/flutter/lib/src/services/raw_keyboard.dart
+9
-0
raw_keyboard_windows.dart
packages/flutter/lib/src/services/raw_keyboard_windows.dart
+291
-0
raw_keyboard_test.dart
packages/flutter/test/services/raw_keyboard_test.dart
+174
-4
event_simulation.dart
packages/flutter_test/lib/src/event_simulation.dart
+69
-0
No files found.
dev/manual_tests/lib/raw_keyboard.dart
View file @
a0f7f6ca
...
...
@@ -109,6 +109,11 @@ class _HardwareKeyDemoState extends State<RawKeyboardDemo> {
dataText
.
add
(
Text
(
'scanCode:
${data.scanCode}
'
));
dataText
.
add
(
Text
(
'unicodeScalarValues:
${data.unicodeScalarValues}
'
));
dataText
.
add
(
Text
(
'modifiers:
${data.modifiers}
(
${_asHex(data.modifiers)}
)'
));
}
else
if
(
data
is
RawKeyEventDataWindows
)
{
dataText
.
add
(
Text
(
'keyCode:
${data.keyCode}
(
${_asHex(data.keyCode)}
)'
));
dataText
.
add
(
Text
(
'scanCode:
${data.scanCode}
'
));
dataText
.
add
(
Text
(
'characterCodePoint:
${data.characterCodePoint}
'
));
dataText
.
add
(
Text
(
'modifiers:
${data.modifiers}
(
${_asHex(data.modifiers)}
)'
));
}
dataText
.
add
(
Text
(
'logical:
${_event.logicalKey}
'
));
dataText
.
add
(
Text
(
'physical:
${_event.physicalKey}
'
));
...
...
dev/tools/gen_keycodes/bin/gen_keycodes.dart
View file @
a0f7f6ca
...
...
@@ -18,8 +18,8 @@ import 'package:gen_keycodes/utils.dart';
/// Get contents of the file that contains the key code mapping in Chromium
/// source.
Future
<
String
>
getChromiumConversions
()
async
{
final
Uri
keyCode
MapUri
=
Uri
.
parse
(
'https://cs.chromium.org/codesearch/f/chromium/src/ui/events/keycodes/dom/dom_code_data.inc
'
);
return
await
http
.
read
(
keyCodeMapUri
);
final
Uri
keyCode
sUri
=
Uri
.
parse
(
'https://chromium.googlesource.com/codesearch/chromium/src/+/refs/heads/master/ui/events/keycodes/dom/dom_code_data.inc?format=TEXT
'
);
return
utf8
.
decode
(
base64
.
decode
(
await
http
.
read
(
keyCodesUri
))
);
}
/// Get contents of the file that contains the key codes in Android source.
...
...
dev/tools/gen_keycodes/data/key_data.json
View file @
a0f7f6ca
...
...
@@ -191,29 +191,6 @@
"windows"
:
null
}
},
"privacyScreenToggle"
:
{
"names"
:
{
"domkey"
:
"PrivacyScreenToggle"
,
"android"
:
null
,
"english"
:
"Privacy Screen Toggle"
,
"chromium"
:
"privacyScreenToggle"
,
"glfw"
:
null
,
"windows"
:
null
},
"scanCodes"
:
{
"android"
:
null
,
"usb"
:
23
,
"linux"
:
633
,
"xkb"
:
641
,
"windows"
:
null
,
"macos"
:
null
},
"keyCodes"
:
{
"android"
:
null
,
"glfw"
:
null
,
"windows"
:
null
}
},
"sleep"
:
{
"names"
:
{
"domkey"
:
"Sleep"
,
...
...
@@ -3080,7 +3057,9 @@
"glfw"
:
[
"RIGHT"
],
"windows"
:
null
"windows"
:
[
"RIGHT"
]
},
"scanCodes"
:
{
"android"
:
[
...
...
@@ -3099,7 +3078,9 @@
"glfw"
:
[
262
],
"windows"
:
null
"windows"
:
[
39
]
}
},
"arrowLeft"
:
{
...
...
@@ -3113,7 +3094,9 @@
"glfw"
:
[
"LEFT"
],
"windows"
:
null
"windows"
:
[
"LEFT"
]
},
"scanCodes"
:
{
"android"
:
[
...
...
@@ -3132,7 +3115,9 @@
"glfw"
:
[
263
],
"windows"
:
null
"windows"
:
[
37
]
}
},
"arrowDown"
:
{
...
...
@@ -3146,7 +3131,9 @@
"glfw"
:
[
"DOWN"
],
"windows"
:
null
"windows"
:
[
"DOWN"
]
},
"scanCodes"
:
{
"android"
:
[
...
...
@@ -3165,7 +3152,9 @@
"glfw"
:
[
264
],
"windows"
:
null
"windows"
:
[
40
]
}
},
"arrowUp"
:
{
...
...
@@ -3179,7 +3168,9 @@
"glfw"
:
[
"UP"
],
"windows"
:
null
"windows"
:
[
"UP"
]
},
"scanCodes"
:
{
"android"
:
[
...
...
@@ -3198,7 +3189,9 @@
"glfw"
:
[
265
],
"windows"
:
null
"windows"
:
[
38
]
}
},
"numLock"
:
{
...
...
@@ -8276,4 +8269,4 @@
"windows"
:
null
}
}
}
}
\ No newline at end of file
dev/tools/gen_keycodes/data/key_name_to_windows_name.json
View file @
a0f7f6ca
...
...
@@ -31,10 +31,10 @@
"next"
:
[
"NEXT"
],
"end"
:
[
"END"
],
"home"
:
[
"HOME"
],
"
leftArrow
"
:
[
"LEFT"
],
"
upArrow
"
:
[
"UP"
],
"
rightArrow
"
:
[
"RIGHT"
],
"
downArrow
"
:
[
"DOWN"
],
"
arrowLeft
"
:
[
"LEFT"
],
"
arrowUp
"
:
[
"UP"
],
"
arrowRight
"
:
[
"RIGHT"
],
"
arrowDown
"
:
[
"DOWN"
],
"select"
:
[
"SELECT"
],
"print"
:
[
"PRINT"
],
"execute"
:
[
"EXECUTE"
],
...
...
dev/tools/gen_keycodes/data/keyboard_key.tmpl
View file @
a0f7f6ca
...
...
@@ -19,7 +19,7 @@ import 'package:flutter/foundation.dart';
/// that are returned from [RawKeyEvent.physicalKey].
/// * [LogicalKeyboardKey], a class with static values that describe the keys
/// that are returned from [RawKeyEvent.logicalKey].
abstract class KeyboardKey
extends
Diagnosticable {
abstract class KeyboardKey
with
Diagnosticable {
/// A const constructor so that subclasses may be const.
const KeyboardKey();
}
...
...
dev/tools/gen_keycodes/data/keyboard_maps.tmpl
View file @
a0f7f6ca
...
...
@@ -92,3 +92,20 @@ const Map<String, PhysicalKeyboardKey> kWebToPhysicalKey = <String, PhysicalKeyb
const Map<String, LogicalKeyboardKey> kWebNumPadMap = <String, LogicalKeyboardKey>{
@@@WEB_NUMPAD_MAP@@@
};
/// Maps Windows KeyboardEvent codes to the matching [LogicalKeyboardKey].
const Map<int, LogicalKeyboardKey> kWindowsToLogicalKey = <int, LogicalKeyboardKey>{
@@@WINDOWS_LOGICAL_KEY_MAP@@@
};
/// Maps Windows KeyboardEvent codes to the matching [PhysicalKeyboardKey].
const Map<int, PhysicalKeyboardKey> kWindowsToPhysicalKey = <int, PhysicalKeyboardKey>{
@@@WINDOWS_PHYSICAL_KEY_MAP@@@
};
/// A map of Windows KeyboardEvent codes which have printable representations, but appear
/// on the number pad. Used to provide different key objects for keys like
/// KEY_EQUALS and NUMPAD_EQUALS.
const Map<int, LogicalKeyboardKey> kWindowsNumPadMap = <int, LogicalKeyboardKey>{
@@@WINDOWS_NUMPAD_MAP@@@
};
dev/tools/gen_keycodes/lib/dart_code_gen.dart
View file @
a0f7f6ca
...
...
@@ -225,6 +225,43 @@ $otherComments static const LogicalKeyboardKey $constantName = LogicalKeyboardK
return
androidScanCodeMap
.
toString
().
trimRight
();
}
/// This generates the map of Windows scan codes to physical keys.
String
get
windowsScanCodeMap
{
final
StringBuffer
windowsScanCodeMap
=
StringBuffer
();
for
(
final
Key
entry
in
keyData
.
data
)
{
if
(
entry
.
windowsScanCode
!=
null
)
{
windowsScanCodeMap
.
writeln
(
'
${toHex(entry.windowsScanCode)}
: PhysicalKeyboardKey.
${entry.constantName}
,'
);
}
}
return
windowsScanCodeMap
.
toString
().
trimRight
();
}
/// This generates the map of Windows number pad key codes to logical keys.
String
get
windowsNumpadMap
{
final
StringBuffer
windowsNumPadMap
=
StringBuffer
();
for
(
final
Key
entry
in
numpadKeyData
)
{
if
(
entry
.
windowsKeyCodes
!=
null
){
for
(
final
int
code
in
entry
.
windowsKeyCodes
)
{
windowsNumPadMap
.
writeln
(
'
$code
: LogicalKeyboardKey.
${entry.constantName}
,'
);
}
}
}
return
windowsNumPadMap
.
toString
().
trimRight
();
}
/// This generates the map of Windows key codes to logical keys.
String
get
windowsKeyCodeMap
{
final
StringBuffer
windowsKeyCodeMap
=
StringBuffer
();
for
(
final
Key
entry
in
keyData
.
data
)
{
if
(
entry
.
windowsKeyCodes
!=
null
)
{
for
(
final
int
code
in
entry
.
windowsKeyCodes
)
{
windowsKeyCodeMap
.
writeln
(
'
$code
: LogicalKeyboardKey.
${entry.constantName}
,'
);
}
}
}
return
windowsKeyCodeMap
.
toString
().
trimRight
();
}
/// This generates the map of macOS key codes to physical keys.
String
get
macOsScanCodeMap
{
final
StringBuffer
macOsScanCodeMap
=
StringBuffer
();
...
...
@@ -381,6 +418,9 @@ $otherComments static const LogicalKeyboardKey $constantName = LogicalKeyboardK
'WEB_LOGICAL_KEY_MAP'
:
webLogicalKeyMap
,
'WEB_PHYSICAL_KEY_MAP'
:
webPhysicalKeyMap
,
'WEB_NUMPAD_MAP'
:
webNumpadMap
,
'WINDOWS_LOGICAL_KEY_MAP'
:
windowsKeyCodeMap
,
'WINDOWS_PHYSICAL_KEY_MAP'
:
windowsScanCodeMap
,
'WINDOWS_NUMPAD_MAP'
:
windowsNumpadMap
,
};
final
String
template
=
File
(
path
.
join
(
flutterRoot
.
path
,
'dev'
,
'tools'
,
'gen_keycodes'
,
'data'
,
'keyboard_maps.tmpl'
)).
readAsStringSync
();
...
...
packages/flutter/lib/services.dart
View file @
a0f7f6ca
...
...
@@ -29,6 +29,7 @@ export 'src/services/raw_keyboard_fuchsia.dart';
export
'src/services/raw_keyboard_linux.dart'
;
export
'src/services/raw_keyboard_macos.dart'
;
export
'src/services/raw_keyboard_web.dart'
;
export
'src/services/raw_keyboard_windows.dart'
;
export
'src/services/system_channels.dart'
;
export
'src/services/system_chrome.dart'
;
export
'src/services/system_navigator.dart'
;
...
...
packages/flutter/lib/src/services/keyboard_maps.dart
View file @
a0f7f6ca
...
...
@@ -2020,3 +2020,306 @@ const Map<String, LogicalKeyboardKey> kWebNumPadMap = <String, LogicalKeyboardKe
'NumpadParenLeft'
:
LogicalKeyboardKey
.
numpadParenLeft
,
'NumpadParenRight'
:
LogicalKeyboardKey
.
numpadParenRight
,
};
/// Maps Windows KeyboardEvent codes to the matching [LogicalKeyboardKey].
const
Map
<
int
,
LogicalKeyboardKey
>
kWindowsToLogicalKey
=
<
int
,
LogicalKeyboardKey
>{
95
:
LogicalKeyboardKey
.
sleep
,
65
:
LogicalKeyboardKey
.
keyA
,
66
:
LogicalKeyboardKey
.
keyB
,
67
:
LogicalKeyboardKey
.
keyC
,
68
:
LogicalKeyboardKey
.
keyD
,
69
:
LogicalKeyboardKey
.
keyE
,
70
:
LogicalKeyboardKey
.
keyF
,
71
:
LogicalKeyboardKey
.
keyG
,
72
:
LogicalKeyboardKey
.
keyH
,
73
:
LogicalKeyboardKey
.
keyI
,
74
:
LogicalKeyboardKey
.
keyJ
,
75
:
LogicalKeyboardKey
.
keyK
,
76
:
LogicalKeyboardKey
.
keyL
,
77
:
LogicalKeyboardKey
.
keyM
,
78
:
LogicalKeyboardKey
.
keyN
,
79
:
LogicalKeyboardKey
.
keyO
,
80
:
LogicalKeyboardKey
.
keyP
,
81
:
LogicalKeyboardKey
.
keyQ
,
82
:
LogicalKeyboardKey
.
keyR
,
83
:
LogicalKeyboardKey
.
keyS
,
84
:
LogicalKeyboardKey
.
keyT
,
85
:
LogicalKeyboardKey
.
keyU
,
86
:
LogicalKeyboardKey
.
keyV
,
87
:
LogicalKeyboardKey
.
keyW
,
88
:
LogicalKeyboardKey
.
keyX
,
89
:
LogicalKeyboardKey
.
keyY
,
90
:
LogicalKeyboardKey
.
keyZ
,
13
:
LogicalKeyboardKey
.
enter
,
27
:
LogicalKeyboardKey
.
escape
,
8
:
LogicalKeyboardKey
.
backspace
,
9
:
LogicalKeyboardKey
.
tab
,
32
:
LogicalKeyboardKey
.
space
,
189
:
LogicalKeyboardKey
.
minus
,
187
:
LogicalKeyboardKey
.
equal
,
219
:
LogicalKeyboardKey
.
bracketLeft
,
221
:
LogicalKeyboardKey
.
bracketRight
,
220
:
LogicalKeyboardKey
.
backslash
,
186
:
LogicalKeyboardKey
.
semicolon
,
222
:
LogicalKeyboardKey
.
quote
,
188
:
LogicalKeyboardKey
.
comma
,
190
:
LogicalKeyboardKey
.
period
,
191
:
LogicalKeyboardKey
.
slash
,
20
:
LogicalKeyboardKey
.
capsLock
,
112
:
LogicalKeyboardKey
.
f1
,
113
:
LogicalKeyboardKey
.
f2
,
114
:
LogicalKeyboardKey
.
f3
,
115
:
LogicalKeyboardKey
.
f4
,
116
:
LogicalKeyboardKey
.
f5
,
117
:
LogicalKeyboardKey
.
f6
,
118
:
LogicalKeyboardKey
.
f7
,
119
:
LogicalKeyboardKey
.
f8
,
120
:
LogicalKeyboardKey
.
f9
,
121
:
LogicalKeyboardKey
.
f10
,
122
:
LogicalKeyboardKey
.
f11
,
123
:
LogicalKeyboardKey
.
f12
,
19
:
LogicalKeyboardKey
.
pause
,
45
:
LogicalKeyboardKey
.
insert
,
36
:
LogicalKeyboardKey
.
home
,
46
:
LogicalKeyboardKey
.
delete
,
35
:
LogicalKeyboardKey
.
end
,
39
:
LogicalKeyboardKey
.
arrowRight
,
37
:
LogicalKeyboardKey
.
arrowLeft
,
40
:
LogicalKeyboardKey
.
arrowDown
,
38
:
LogicalKeyboardKey
.
arrowUp
,
111
:
LogicalKeyboardKey
.
numpadDivide
,
106
:
LogicalKeyboardKey
.
numpadMultiply
,
109
:
LogicalKeyboardKey
.
numpadSubtract
,
107
:
LogicalKeyboardKey
.
numpadAdd
,
97
:
LogicalKeyboardKey
.
numpad1
,
98
:
LogicalKeyboardKey
.
numpad2
,
99
:
LogicalKeyboardKey
.
numpad3
,
100
:
LogicalKeyboardKey
.
numpad4
,
101
:
LogicalKeyboardKey
.
numpad5
,
102
:
LogicalKeyboardKey
.
numpad6
,
103
:
LogicalKeyboardKey
.
numpad7
,
104
:
LogicalKeyboardKey
.
numpad8
,
105
:
LogicalKeyboardKey
.
numpad9
,
96
:
LogicalKeyboardKey
.
numpad0
,
110
:
LogicalKeyboardKey
.
numpadDecimal
,
146
:
LogicalKeyboardKey
.
numpadEqual
,
124
:
LogicalKeyboardKey
.
f13
,
125
:
LogicalKeyboardKey
.
f14
,
126
:
LogicalKeyboardKey
.
f15
,
127
:
LogicalKeyboardKey
.
f16
,
128
:
LogicalKeyboardKey
.
f17
,
129
:
LogicalKeyboardKey
.
f18
,
130
:
LogicalKeyboardKey
.
f19
,
131
:
LogicalKeyboardKey
.
f20
,
132
:
LogicalKeyboardKey
.
f21
,
133
:
LogicalKeyboardKey
.
f22
,
134
:
LogicalKeyboardKey
.
f23
,
135
:
LogicalKeyboardKey
.
f24
,
47
:
LogicalKeyboardKey
.
help
,
41
:
LogicalKeyboardKey
.
select
,
28
:
LogicalKeyboardKey
.
convert
,
162
:
LogicalKeyboardKey
.
controlLeft
,
160
:
LogicalKeyboardKey
.
shiftLeft
,
164
:
LogicalKeyboardKey
.
altLeft
,
91
:
LogicalKeyboardKey
.
metaLeft
,
163
:
LogicalKeyboardKey
.
controlRight
,
161
:
LogicalKeyboardKey
.
shiftRight
,
165
:
LogicalKeyboardKey
.
altRight
,
92
:
LogicalKeyboardKey
.
metaRight
,
178
:
LogicalKeyboardKey
.
mediaStop
,
179
:
LogicalKeyboardKey
.
mediaPlayPause
,
180
:
LogicalKeyboardKey
.
launchMail
,
183
:
LogicalKeyboardKey
.
launchApp2
,
182
:
LogicalKeyboardKey
.
launchApp1
,
42
:
LogicalKeyboardKey
.
print
,
170
:
LogicalKeyboardKey
.
browserSearch
,
172
:
LogicalKeyboardKey
.
browserHome
,
166
:
LogicalKeyboardKey
.
browserBack
,
167
:
LogicalKeyboardKey
.
browserForward
,
169
:
LogicalKeyboardKey
.
browserStop
,
168
:
LogicalKeyboardKey
.
browserRefresh
,
171
:
LogicalKeyboardKey
.
browserFavorites
,
};
/// Maps Windows KeyboardEvent codes to the matching [PhysicalKeyboardKey].
const
Map
<
int
,
PhysicalKeyboardKey
>
kWindowsToPhysicalKey
=
<
int
,
PhysicalKeyboardKey
>{
0x0000e05f
:
PhysicalKeyboardKey
.
sleep
,
0x0000e063
:
PhysicalKeyboardKey
.
wakeUp
,
0x000000ff
:
PhysicalKeyboardKey
.
usbErrorRollOver
,
0x000000fc
:
PhysicalKeyboardKey
.
usbPostFail
,
0x0000001e
:
PhysicalKeyboardKey
.
keyA
,
0x00000030
:
PhysicalKeyboardKey
.
keyB
,
0x0000002e
:
PhysicalKeyboardKey
.
keyC
,
0x00000020
:
PhysicalKeyboardKey
.
keyD
,
0x00000012
:
PhysicalKeyboardKey
.
keyE
,
0x00000021
:
PhysicalKeyboardKey
.
keyF
,
0x00000022
:
PhysicalKeyboardKey
.
keyG
,
0x00000023
:
PhysicalKeyboardKey
.
keyH
,
0x00000017
:
PhysicalKeyboardKey
.
keyI
,
0x00000024
:
PhysicalKeyboardKey
.
keyJ
,
0x00000025
:
PhysicalKeyboardKey
.
keyK
,
0x00000026
:
PhysicalKeyboardKey
.
keyL
,
0x00000032
:
PhysicalKeyboardKey
.
keyM
,
0x00000031
:
PhysicalKeyboardKey
.
keyN
,
0x00000018
:
PhysicalKeyboardKey
.
keyO
,
0x00000019
:
PhysicalKeyboardKey
.
keyP
,
0x00000010
:
PhysicalKeyboardKey
.
keyQ
,
0x00000013
:
PhysicalKeyboardKey
.
keyR
,
0x0000001f
:
PhysicalKeyboardKey
.
keyS
,
0x00000014
:
PhysicalKeyboardKey
.
keyT
,
0x00000016
:
PhysicalKeyboardKey
.
keyU
,
0x0000002f
:
PhysicalKeyboardKey
.
keyV
,
0x00000011
:
PhysicalKeyboardKey
.
keyW
,
0x0000002d
:
PhysicalKeyboardKey
.
keyX
,
0x00000015
:
PhysicalKeyboardKey
.
keyY
,
0x0000002c
:
PhysicalKeyboardKey
.
keyZ
,
0x00000002
:
PhysicalKeyboardKey
.
digit1
,
0x00000003
:
PhysicalKeyboardKey
.
digit2
,
0x00000004
:
PhysicalKeyboardKey
.
digit3
,
0x00000005
:
PhysicalKeyboardKey
.
digit4
,
0x00000006
:
PhysicalKeyboardKey
.
digit5
,
0x00000007
:
PhysicalKeyboardKey
.
digit6
,
0x00000008
:
PhysicalKeyboardKey
.
digit7
,
0x00000009
:
PhysicalKeyboardKey
.
digit8
,
0x0000000a
:
PhysicalKeyboardKey
.
digit9
,
0x0000000b
:
PhysicalKeyboardKey
.
digit0
,
0x0000001c
:
PhysicalKeyboardKey
.
enter
,
0x00000001
:
PhysicalKeyboardKey
.
escape
,
0x0000000e
:
PhysicalKeyboardKey
.
backspace
,
0x0000000f
:
PhysicalKeyboardKey
.
tab
,
0x00000039
:
PhysicalKeyboardKey
.
space
,
0x0000000c
:
PhysicalKeyboardKey
.
minus
,
0x0000000d
:
PhysicalKeyboardKey
.
equal
,
0x0000001a
:
PhysicalKeyboardKey
.
bracketLeft
,
0x0000001b
:
PhysicalKeyboardKey
.
bracketRight
,
0x0000002b
:
PhysicalKeyboardKey
.
backslash
,
0x00000027
:
PhysicalKeyboardKey
.
semicolon
,
0x00000028
:
PhysicalKeyboardKey
.
quote
,
0x00000029
:
PhysicalKeyboardKey
.
backquote
,
0x00000033
:
PhysicalKeyboardKey
.
comma
,
0x00000034
:
PhysicalKeyboardKey
.
period
,
0x00000035
:
PhysicalKeyboardKey
.
slash
,
0x0000003a
:
PhysicalKeyboardKey
.
capsLock
,
0x0000003b
:
PhysicalKeyboardKey
.
f1
,
0x0000003c
:
PhysicalKeyboardKey
.
f2
,
0x0000003d
:
PhysicalKeyboardKey
.
f3
,
0x0000003e
:
PhysicalKeyboardKey
.
f4
,
0x0000003f
:
PhysicalKeyboardKey
.
f5
,
0x00000040
:
PhysicalKeyboardKey
.
f6
,
0x00000041
:
PhysicalKeyboardKey
.
f7
,
0x00000042
:
PhysicalKeyboardKey
.
f8
,
0x00000043
:
PhysicalKeyboardKey
.
f9
,
0x00000044
:
PhysicalKeyboardKey
.
f10
,
0x00000057
:
PhysicalKeyboardKey
.
f11
,
0x00000058
:
PhysicalKeyboardKey
.
f12
,
0x0000e037
:
PhysicalKeyboardKey
.
printScreen
,
0x00000046
:
PhysicalKeyboardKey
.
scrollLock
,
0x00000045
:
PhysicalKeyboardKey
.
pause
,
0x0000e052
:
PhysicalKeyboardKey
.
insert
,
0x0000e047
:
PhysicalKeyboardKey
.
home
,
0x0000e049
:
PhysicalKeyboardKey
.
pageUp
,
0x0000e053
:
PhysicalKeyboardKey
.
delete
,
0x0000e04f
:
PhysicalKeyboardKey
.
end
,
0x0000e051
:
PhysicalKeyboardKey
.
pageDown
,
0x0000e04d
:
PhysicalKeyboardKey
.
arrowRight
,
0x0000e04b
:
PhysicalKeyboardKey
.
arrowLeft
,
0x0000e050
:
PhysicalKeyboardKey
.
arrowDown
,
0x0000e048
:
PhysicalKeyboardKey
.
arrowUp
,
0x0000e045
:
PhysicalKeyboardKey
.
numLock
,
0x0000e035
:
PhysicalKeyboardKey
.
numpadDivide
,
0x00000037
:
PhysicalKeyboardKey
.
numpadMultiply
,
0x0000004a
:
PhysicalKeyboardKey
.
numpadSubtract
,
0x0000004e
:
PhysicalKeyboardKey
.
numpadAdd
,
0x0000e01c
:
PhysicalKeyboardKey
.
numpadEnter
,
0x0000004f
:
PhysicalKeyboardKey
.
numpad1
,
0x00000050
:
PhysicalKeyboardKey
.
numpad2
,
0x00000051
:
PhysicalKeyboardKey
.
numpad3
,
0x0000004b
:
PhysicalKeyboardKey
.
numpad4
,
0x0000004c
:
PhysicalKeyboardKey
.
numpad5
,
0x0000004d
:
PhysicalKeyboardKey
.
numpad6
,
0x00000047
:
PhysicalKeyboardKey
.
numpad7
,
0x00000048
:
PhysicalKeyboardKey
.
numpad8
,
0x00000049
:
PhysicalKeyboardKey
.
numpad9
,
0x00000052
:
PhysicalKeyboardKey
.
numpad0
,
0x00000053
:
PhysicalKeyboardKey
.
numpadDecimal
,
0x00000056
:
PhysicalKeyboardKey
.
intlBackslash
,
0x0000e05d
:
PhysicalKeyboardKey
.
contextMenu
,
0x0000e05e
:
PhysicalKeyboardKey
.
power
,
0x00000059
:
PhysicalKeyboardKey
.
numpadEqual
,
0x00000064
:
PhysicalKeyboardKey
.
f13
,
0x00000065
:
PhysicalKeyboardKey
.
f14
,
0x00000066
:
PhysicalKeyboardKey
.
f15
,
0x00000067
:
PhysicalKeyboardKey
.
f16
,
0x00000068
:
PhysicalKeyboardKey
.
f17
,
0x00000069
:
PhysicalKeyboardKey
.
f18
,
0x0000006a
:
PhysicalKeyboardKey
.
f19
,
0x0000006b
:
PhysicalKeyboardKey
.
f20
,
0x0000006c
:
PhysicalKeyboardKey
.
f21
,
0x0000006d
:
PhysicalKeyboardKey
.
f22
,
0x0000006e
:
PhysicalKeyboardKey
.
f23
,
0x00000076
:
PhysicalKeyboardKey
.
f24
,
0x0000e03b
:
PhysicalKeyboardKey
.
help
,
0x0000e008
:
PhysicalKeyboardKey
.
undo
,
0x0000e017
:
PhysicalKeyboardKey
.
cut
,
0x0000e018
:
PhysicalKeyboardKey
.
copy
,
0x0000e00a
:
PhysicalKeyboardKey
.
paste
,
0x0000e020
:
PhysicalKeyboardKey
.
audioVolumeMute
,
0x0000e030
:
PhysicalKeyboardKey
.
audioVolumeUp
,
0x0000e02e
:
PhysicalKeyboardKey
.
audioVolumeDown
,
0x0000007e
:
PhysicalKeyboardKey
.
numpadComma
,
0x00000073
:
PhysicalKeyboardKey
.
intlRo
,
0x00000070
:
PhysicalKeyboardKey
.
kanaMode
,
0x0000007d
:
PhysicalKeyboardKey
.
intlYen
,
0x00000079
:
PhysicalKeyboardKey
.
convert
,
0x0000007b
:
PhysicalKeyboardKey
.
nonConvert
,
0x00000072
:
PhysicalKeyboardKey
.
lang1
,
0x00000071
:
PhysicalKeyboardKey
.
lang2
,
0x00000078
:
PhysicalKeyboardKey
.
lang3
,
0x00000077
:
PhysicalKeyboardKey
.
lang4
,
0x0000001d
:
PhysicalKeyboardKey
.
controlLeft
,
0x0000002a
:
PhysicalKeyboardKey
.
shiftLeft
,
0x00000038
:
PhysicalKeyboardKey
.
altLeft
,
0x0000e05b
:
PhysicalKeyboardKey
.
metaLeft
,
0x0000e01d
:
PhysicalKeyboardKey
.
controlRight
,
0x00000036
:
PhysicalKeyboardKey
.
shiftRight
,
0x0000e038
:
PhysicalKeyboardKey
.
altRight
,
0x0000e05c
:
PhysicalKeyboardKey
.
metaRight
,
0x0000e019
:
PhysicalKeyboardKey
.
mediaTrackNext
,
0x0000e010
:
PhysicalKeyboardKey
.
mediaTrackPrevious
,
0x0000e024
:
PhysicalKeyboardKey
.
mediaStop
,
0x0000e02c
:
PhysicalKeyboardKey
.
eject
,
0x0000e022
:
PhysicalKeyboardKey
.
mediaPlayPause
,
0x0000e06d
:
PhysicalKeyboardKey
.
mediaSelect
,
0x0000e06c
:
PhysicalKeyboardKey
.
launchMail
,
0x0000e021
:
PhysicalKeyboardKey
.
launchApp2
,
0x0000e06b
:
PhysicalKeyboardKey
.
launchApp1
,
0x0000e065
:
PhysicalKeyboardKey
.
browserSearch
,
0x0000e032
:
PhysicalKeyboardKey
.
browserHome
,
0x0000e06a
:
PhysicalKeyboardKey
.
browserBack
,
0x0000e069
:
PhysicalKeyboardKey
.
browserForward
,
0x0000e068
:
PhysicalKeyboardKey
.
browserStop
,
0x0000e067
:
PhysicalKeyboardKey
.
browserRefresh
,
0x0000e066
:
PhysicalKeyboardKey
.
browserFavorites
,
};
/// A map of Windows KeyboardEvent codes which have printable representations, but appear
/// on the number pad. Used to provide different key objects for keys like
/// KEY_EQUALS and NUMPAD_EQUALS.
const
Map
<
int
,
LogicalKeyboardKey
>
kWindowsNumPadMap
=
<
int
,
LogicalKeyboardKey
>{
111
:
LogicalKeyboardKey
.
numpadDivide
,
106
:
LogicalKeyboardKey
.
numpadMultiply
,
109
:
LogicalKeyboardKey
.
numpadSubtract
,
107
:
LogicalKeyboardKey
.
numpadAdd
,
97
:
LogicalKeyboardKey
.
numpad1
,
98
:
LogicalKeyboardKey
.
numpad2
,
99
:
LogicalKeyboardKey
.
numpad3
,
100
:
LogicalKeyboardKey
.
numpad4
,
101
:
LogicalKeyboardKey
.
numpad5
,
102
:
LogicalKeyboardKey
.
numpad6
,
103
:
LogicalKeyboardKey
.
numpad7
,
104
:
LogicalKeyboardKey
.
numpad8
,
105
:
LogicalKeyboardKey
.
numpad9
,
96
:
LogicalKeyboardKey
.
numpad0
,
110
:
LogicalKeyboardKey
.
numpadDecimal
,
146
:
LogicalKeyboardKey
.
numpadEqual
,
};
packages/flutter/lib/src/services/raw_keyboard.dart
View file @
a0f7f6ca
...
...
@@ -14,6 +14,7 @@ import 'raw_keyboard_fuchsia.dart';
import
'raw_keyboard_linux.dart'
;
import
'raw_keyboard_macos.dart'
;
import
'raw_keyboard_web.dart'
;
import
'raw_keyboard_windows.dart'
;
import
'system_channels.dart'
;
/// An enum describing the side of the keyboard that a key is on, to allow
...
...
@@ -296,6 +297,14 @@ abstract class RawKeyEvent with Diagnosticable {
metaState:
message
[
'metaState'
]
as
int
,
);
break
;
case
'windows'
:
data
=
RawKeyEventDataWindows
(
keyCode:
message
[
'keyCode'
]
as
int
,
scanCode:
message
[
'scanCode'
]
as
int
,
characterCodePoint:
message
[
'characterCodePoint'
]
as
int
,
modifiers:
message
[
'modifiers'
]
as
int
,
);
break
;
default
:
// Raw key events are not yet implemented on iOS or other platforms,
// but this exception isn't hit, because the engine never sends these
...
...
packages/flutter/lib/src/services/raw_keyboard_windows.dart
0 → 100644
View file @
a0f7f6ca
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/foundation.dart'
;
import
'keyboard_key.dart'
;
import
'keyboard_maps.dart'
;
import
'raw_keyboard.dart'
;
/// Platform-specific key event data for Windows.
///
/// This object contains information about key events obtained from Windows's
/// win32 API.
///
/// See also:
///
/// * [RawKeyboard], which uses this interface to expose key data.
class
RawKeyEventDataWindows
extends
RawKeyEventData
{
/// Creates a key event data structure specific for Windows.
///
/// The [keyCode], [scanCode], [characterCodePoint], and [modifiers], arguments
/// must not be null.
const
RawKeyEventDataWindows
({
this
.
keyCode
=
0
,
this
.
scanCode
=
0
,
this
.
characterCodePoint
=
0
,
this
.
modifiers
=
0
,
})
:
assert
(
keyCode
!=
null
),
assert
(
scanCode
!=
null
),
assert
(
characterCodePoint
!=
null
),
assert
(
modifiers
!=
null
);
/// The hardware key code corresponding to this key event.
///
/// This is the physical key that was pressed, not the Unicode character.
/// See [characterCodePoint] for the Unicode character.
final
int
keyCode
;
/// The hardware scan code id corresponding to this key event.
///
/// These values are not reliable and vary from device to device, so this
/// information is mainly useful for debugging.
final
int
scanCode
;
/// The Unicode code point represented by the key event, if any.
///
/// If there is no Unicode code point, this value is zero.
final
int
characterCodePoint
;
/// A mask of the current modifiers. The modifier values must be in sync with
/// the ones defined in https://github.com/flutter/engine/blob/master/shell/platform/windows/key_event_handler.cc
final
int
modifiers
;
@override
String
get
keyLabel
=>
characterCodePoint
==
0
?
null
:
String
.
fromCharCode
(
characterCodePoint
);
@override
PhysicalKeyboardKey
get
physicalKey
=>
kWindowsToPhysicalKey
[
scanCode
]
??
PhysicalKeyboardKey
.
none
;
@override
LogicalKeyboardKey
get
logicalKey
{
// Look to see if the keyCode is a printable number pad key, so that a
// difference between regular keys (e.g. "=") and the number pad version
// (e.g. the "=" on the number pad) can be determined.
final
LogicalKeyboardKey
numPadKey
=
kWindowsNumPadMap
[
keyCode
];
if
(
numPadKey
!=
null
)
{
return
numPadKey
;
}
// If it has a non-control-character label, then either return the existing
// constant, or construct a new Unicode-based key from it. Don't mark it as
// autogenerated, since the label uniquely identifies an ID from the Unicode
// plane.
if
(
keyLabel
!=
null
&&
keyLabel
.
isNotEmpty
&&
!
LogicalKeyboardKey
.
isControlCharacter
(
keyLabel
))
{
final
int
keyId
=
LogicalKeyboardKey
.
unicodePlane
|
(
characterCodePoint
&
LogicalKeyboardKey
.
valueMask
);
return
LogicalKeyboardKey
.
findKeyByKeyId
(
keyId
)
??
LogicalKeyboardKey
(
keyId
,
keyLabel:
keyLabel
,
debugName:
kReleaseMode
?
null
:
'Key
${keyLabel.toUpperCase()}
'
,
);
}
// Look to see if the keyCode is one we know about and have a mapping for.
LogicalKeyboardKey
newKey
=
kWindowsToLogicalKey
[
keyCode
];
if
(
newKey
!=
null
)
{
return
newKey
;
}
// This is a non-printable key that we don't know about, so we mint a new
// code with the autogenerated bit set.
const
int
windowsKeyIdPlane
=
0x00700000000
;
newKey
??=
LogicalKeyboardKey
(
windowsKeyIdPlane
|
keyCode
|
LogicalKeyboardKey
.
autogeneratedMask
,
debugName:
kReleaseMode
?
null
:
'Unknown Windows key code
$keyCode
'
,
);
return
newKey
;
}
bool
_isLeftRightModifierPressed
(
KeyboardSide
side
,
int
anyMask
,
int
leftMask
,
int
rightMask
)
{
if
(
modifiers
&
anyMask
==
0
&&
modifiers
&
leftMask
==
0
&&
modifiers
&
rightMask
==
0
)
{
return
false
;
}
// If only the "anyMask" bit is set, then we respond true for requests of
// whether either left or right is pressed.
// Handles the case where Windows supplies just the "either" modifier flag,
// but not the left/right flag. (e.g. modifierShift but not
// modifierLeftShift).
final
bool
anyOnly
=
modifiers
&
(
leftMask
|
rightMask
|
anyMask
)
==
anyMask
;
switch
(
side
)
{
case
KeyboardSide
.
any
:
return
true
;
case
KeyboardSide
.
all
:
return
modifiers
&
leftMask
!=
0
&&
modifiers
&
rightMask
!=
0
||
anyOnly
;
case
KeyboardSide
.
left
:
return
modifiers
&
leftMask
!=
0
||
anyOnly
;
case
KeyboardSide
.
right
:
return
modifiers
&
rightMask
!=
0
||
anyOnly
;
}
return
false
;
}
@override
bool
isModifierPressed
(
ModifierKey
key
,
{
KeyboardSide
side
=
KeyboardSide
.
any
})
{
bool
result
;
switch
(
key
)
{
case
ModifierKey
.
controlModifier
:
result
=
_isLeftRightModifierPressed
(
side
,
modifierControl
,
modifierLeftControl
,
modifierRightControl
);
break
;
case
ModifierKey
.
shiftModifier
:
result
=
_isLeftRightModifierPressed
(
side
,
modifierShift
,
modifierLeftShift
,
modifierRightShift
);
break
;
case
ModifierKey
.
altModifier
:
result
=
_isLeftRightModifierPressed
(
side
,
modifierAlt
,
modifierLeftAlt
,
modifierRightAlt
);
break
;
case
ModifierKey
.
metaModifier
:
// Windows does not provide an "any" key for win key press.
result
=
_isLeftRightModifierPressed
(
side
,
modifierLeftMeta
|
modifierRightMeta
,
modifierLeftMeta
,
modifierRightMeta
);
break
;
case
ModifierKey
.
capsLockModifier
:
result
=
modifiers
&
modifierCaps
!=
0
;
break
;
case
ModifierKey
.
scrollLockModifier
:
result
=
modifiers
&
modifierScrollLock
!=
0
;
break
;
case
ModifierKey
.
numLockModifier
:
result
=
modifiers
&
modifierNumLock
!=
0
;
break
;
// The OS does not expose the Fn key to the drivers, it doesn't generate a key message.
case
ModifierKey
.
functionModifier
:
case
ModifierKey
.
symbolModifier
:
// These modifier masks are not used in Windows keyboards.
result
=
false
;
break
;
}
assert
(!
result
||
getModifierSide
(
key
)
!=
null
,
"
$runtimeType
thinks that a modifier is pressed, but can't figure out what side it's on."
);
return
result
;
}
@override
KeyboardSide
getModifierSide
(
ModifierKey
key
)
{
KeyboardSide
findSide
(
int
leftMask
,
int
rightMask
,
int
anyMask
)
{
final
int
combinedMask
=
leftMask
|
rightMask
;
final
int
combined
=
modifiers
&
combinedMask
;
if
(
combined
==
leftMask
)
{
return
KeyboardSide
.
left
;
}
else
if
(
combined
==
rightMask
)
{
return
KeyboardSide
.
right
;
}
else
if
(
combined
==
combinedMask
)
{
return
KeyboardSide
.
all
;
}
else
if
(
modifiers
&
(
combinedMask
|
anyMask
)
==
anyMask
)
{
// Handles the case where Windows supplies just the "either" modifier
// flag, but not the left/right flag. (e.g. modifierShift but not
// modifierLeftShift).
return
KeyboardSide
.
any
;
}
return
null
;
}
switch
(
key
)
{
case
ModifierKey
.
controlModifier
:
return
findSide
(
modifierLeftControl
,
modifierRightControl
,
modifierControl
);
case
ModifierKey
.
shiftModifier
:
return
findSide
(
modifierLeftShift
,
modifierRightShift
,
modifierShift
);
case
ModifierKey
.
altModifier
:
return
findSide
(
modifierLeftAlt
,
modifierRightAlt
,
modifierAlt
);
case
ModifierKey
.
metaModifier
:
return
findSide
(
modifierLeftMeta
,
modifierRightMeta
,
0
);
case
ModifierKey
.
capsLockModifier
:
case
ModifierKey
.
numLockModifier
:
case
ModifierKey
.
scrollLockModifier
:
case
ModifierKey
.
functionModifier
:
case
ModifierKey
.
symbolModifier
:
return
KeyboardSide
.
all
;
}
assert
(
false
,
'Not handling
$key
type properly.'
);
return
null
;
}
// These are not the values defined by the Windows header for each modifier. Since they
// can't be packaged into a single int, we are re-defining them here to reduce the size
// of the message from the embedder. Embedders should map these values to the native key codes.
// Keep this in sync with https://github.com/flutter/engine/blob/master/shell/platform/windows/key_event_handler.cc
/// This mask is used to check the [modifiers] field to test whether one of the
/// SHIFT modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierShift
=
1
<<
0
;
/// This mask is used to check the [modifiers] field to test whether the left
/// SHIFT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierLeftShift
=
1
<<
1
;
/// This mask is used to check the [modifiers] field to test whether the right
/// SHIFT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierRightShift
=
1
<<
2
;
/// This mask is used to check the [modifiers] field to test whether one of the
/// CTRL modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierControl
=
1
<<
3
;
/// This mask is used to check the [modifiers] field to test whether the left
/// CTRL modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierLeftControl
=
1
<<
4
;
/// This mask is used to check the [modifiers] field to test whether the right
/// CTRL modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierRightControl
=
1
<<
5
;
/// This mask is used to check the [modifiers] field to test whether one of the
/// ALT modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierAlt
=
1
<<
6
;
/// This mask is used to check the [modifiers] field to test whether the left
/// ALT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierLeftAlt
=
1
<<
7
;
/// This mask is used to check the [modifiers] field to test whether the right
/// ALT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierRightAlt
=
1
<<
8
;
/// This mask is used to check the [modifiers] field to test whether the left
/// WIN modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierLeftMeta
=
1
<<
9
;
/// This mask is used to check the [modifiers] field to test whether the right
/// WIN modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierRightMeta
=
1
<<
10
;
/// This mask is used to check the [modifiers] field to test whether the CAPS LOCK key
/// is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierCaps
=
1
<<
11
;
/// This mask is used to check the [modifiers] field to test whether the NUM LOCK key
/// is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierNumLock
=
1
<<
12
;
/// This mask is used to check the [modifiers] field to test whether the SCROLL LOCK key
/// is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static
const
int
modifierScrollLock
=
1
<<
13
;
}
packages/flutter/test/services/raw_keyboard_test.dart
View file @
a0f7f6ca
...
...
@@ -15,7 +15,7 @@ class _ModifierCheck {
void
main
(
)
{
group
(
'RawKeyboard'
,
()
{
testWidgets
(
'keysPressed is maintained'
,
(
WidgetTester
tester
)
async
{
for
(
final
String
platform
in
<
String
>[
'linux'
,
'android'
,
'macos'
,
'fuchsia'
])
{
for
(
final
String
platform
in
<
String
>[
'linux'
,
'android'
,
'macos'
,
'fuchsia'
,
'windows'
])
{
RawKeyboard
.
instance
.
clearKeysPressed
();
expect
(
RawKeyboard
.
instance
.
keysPressed
,
isEmpty
,
reason:
'on
$platform
'
);
await
simulateKeyDownEvent
(
LogicalKeyboardKey
.
shiftLeft
,
platform:
platform
);
...
...
@@ -70,8 +70,8 @@ void main() {
);
await
simulateKeyUpEvent
(
LogicalKeyboardKey
.
shiftLeft
,
platform:
platform
);
expect
(
RawKeyboard
.
instance
.
keysPressed
,
isEmpty
,
reason:
'on
$platform
'
);
// The Fn key isn't mapped on linux.
if
(
platform
!=
'linux'
)
{
// The Fn key isn't mapped on linux
or Windows
.
if
(
platform
!=
'linux'
&&
platform
!=
'windows'
)
{
await
simulateKeyDownEvent
(
LogicalKeyboardKey
.
fn
,
platform:
platform
);
expect
(
RawKeyboard
.
instance
.
keysPressed
,
...
...
@@ -107,7 +107,7 @@ void main() {
},
skip:
kIsWeb
);
testWidgets
(
'keysPressed is correct when modifier is released before key'
,
(
WidgetTester
tester
)
async
{
for
(
final
String
platform
in
<
String
>[
'linux'
,
'android'
,
'macos'
,
'fuchsia'
])
{
for
(
final
String
platform
in
<
String
>[
'linux'
,
'android'
,
'macos'
,
'fuchsia'
,
'windows'
])
{
RawKeyboard
.
instance
.
clearKeysPressed
();
expect
(
RawKeyboard
.
instance
.
keysPressed
,
isEmpty
,
reason:
'on
$platform
'
);
await
simulateKeyDownEvent
(
LogicalKeyboardKey
.
shiftLeft
,
platform:
platform
,
physicalKey:
PhysicalKeyboardKey
.
shiftLeft
);
...
...
@@ -176,6 +176,31 @@ void main() {
);
});
testWidgets
(
'keysPressed modifiers are synchronized with key events on Windows'
,
(
WidgetTester
tester
)
async
{
expect
(
RawKeyboard
.
instance
.
keysPressed
,
isEmpty
);
// Generate the data for a regular key down event.
final
Map
<
String
,
dynamic
>
data
=
KeyEventSimulator
.
getKeyData
(
LogicalKeyboardKey
.
keyA
,
platform:
'windows'
,
isDown:
true
,
);
// Change the modifiers so that they show the shift key as already down
// when this event is received, but it's not in keysPressed yet.
data
[
'modifiers'
]
|=
RawKeyEventDataWindows
.
modifierLeftShift
|
RawKeyEventDataWindows
.
modifierShift
;
// dispatch the modified data.
await
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
handlePlatformMessage
(
SystemChannels
.
keyEvent
.
name
,
SystemChannels
.
keyEvent
.
codec
.
encodeMessage
(
data
),
(
ByteData
data
)
{},
);
expect
(
RawKeyboard
.
instance
.
keysPressed
,
equals
(
<
LogicalKeyboardKey
>{
LogicalKeyboardKey
.
shiftLeft
,
LogicalKeyboardKey
.
keyA
},
),
);
});
testWidgets
(
'keysPressed modifiers are synchronized with key events on android'
,
(
WidgetTester
tester
)
async
{
expect
(
RawKeyboard
.
instance
.
keysPressed
,
isEmpty
);
// Generate the data for a regular key down event.
...
...
@@ -746,6 +771,151 @@ void main() {
expect
(
data
.
logicalKey
.
keyLabel
,
isNull
);
});
},
skip:
isBrowser
);
group
(
'RawKeyEventDataWindows'
,
()
{
const
Map
<
int
,
_ModifierCheck
>
modifierTests
=
<
int
,
_ModifierCheck
>{
RawKeyEventDataWindows
.
modifierLeftAlt
:
_ModifierCheck
(
ModifierKey
.
altModifier
,
KeyboardSide
.
left
),
RawKeyEventDataWindows
.
modifierRightAlt
:
_ModifierCheck
(
ModifierKey
.
altModifier
,
KeyboardSide
.
right
),
RawKeyEventDataWindows
.
modifierLeftShift
:
_ModifierCheck
(
ModifierKey
.
shiftModifier
,
KeyboardSide
.
left
),
RawKeyEventDataWindows
.
modifierRightShift
:
_ModifierCheck
(
ModifierKey
.
shiftModifier
,
KeyboardSide
.
right
),
RawKeyEventDataWindows
.
modifierLeftControl
:
_ModifierCheck
(
ModifierKey
.
controlModifier
,
KeyboardSide
.
left
),
RawKeyEventDataWindows
.
modifierRightControl
:
_ModifierCheck
(
ModifierKey
.
controlModifier
,
KeyboardSide
.
right
),
RawKeyEventDataWindows
.
modifierLeftMeta
:
_ModifierCheck
(
ModifierKey
.
metaModifier
,
KeyboardSide
.
left
),
RawKeyEventDataWindows
.
modifierRightMeta
:
_ModifierCheck
(
ModifierKey
.
metaModifier
,
KeyboardSide
.
right
),
RawKeyEventDataWindows
.
modifierShift
:
_ModifierCheck
(
ModifierKey
.
shiftModifier
,
KeyboardSide
.
any
),
RawKeyEventDataWindows
.
modifierControl
:
_ModifierCheck
(
ModifierKey
.
controlModifier
,
KeyboardSide
.
any
),
RawKeyEventDataWindows
.
modifierAlt
:
_ModifierCheck
(
ModifierKey
.
altModifier
,
KeyboardSide
.
any
),
RawKeyEventDataWindows
.
modifierCaps
:
_ModifierCheck
(
ModifierKey
.
capsLockModifier
,
KeyboardSide
.
all
),
RawKeyEventDataWindows
.
modifierNumLock
:
_ModifierCheck
(
ModifierKey
.
numLockModifier
,
KeyboardSide
.
all
),
RawKeyEventDataWindows
.
modifierScrollLock
:
_ModifierCheck
(
ModifierKey
.
scrollLockModifier
,
KeyboardSide
.
all
),
};
test
(
'modifier keys are recognized individually'
,
()
{
for
(
final
int
modifier
in
modifierTests
.
keys
)
{
final
RawKeyEvent
event
=
RawKeyEvent
.
fromMessage
(<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'windows'
,
'keyCode'
:
0x04
,
'characterCodePoint'
:
0
,
'scanCode'
:
0x04
,
'modifiers'
:
modifier
,
});
final
RawKeyEventDataWindows
data
=
event
.
data
as
RawKeyEventDataWindows
;
for
(
final
ModifierKey
key
in
ModifierKey
.
values
)
{
if
(
modifierTests
[
modifier
].
key
==
key
)
{
expect
(
data
.
isModifierPressed
(
key
,
side:
modifierTests
[
modifier
].
side
),
isTrue
,
reason:
"
$key
should be pressed with modifier
$modifier
, but isn't."
,
);
expect
(
data
.
getModifierSide
(
key
),
equals
(
modifierTests
[
modifier
].
side
));
}
else
{
expect
(
data
.
isModifierPressed
(
key
,
side:
modifierTests
[
modifier
].
side
),
isFalse
,
reason:
'
$key
should not be pressed with metaState
$modifier
.'
,
);
}
}
}
});
test
(
'modifier keys are recognized when combined'
,
()
{
for
(
final
int
modifier
in
modifierTests
.
keys
)
{
if
(
modifier
==
RawKeyEventDataWindows
.
modifierCaps
)
{
// No need to combine caps lock key with itself.
continue
;
}
final
RawKeyEvent
event
=
RawKeyEvent
.
fromMessage
(<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'windows'
,
'keyCode'
:
0x04
,
'characterCodePoint'
:
0
,
'scanCode'
:
0x04
,
'modifiers'
:
modifier
|
RawKeyEventDataWindows
.
modifierCaps
,
});
final
RawKeyEventDataWindows
data
=
event
.
data
as
RawKeyEventDataWindows
;
for
(
final
ModifierKey
key
in
ModifierKey
.
values
)
{
if
(
modifierTests
[
modifier
].
key
==
key
||
key
==
ModifierKey
.
capsLockModifier
)
{
expect
(
data
.
isModifierPressed
(
key
,
side:
modifierTests
[
modifier
].
side
),
isTrue
,
reason:
'
$key
should be pressed with metaState
$modifier
'
"and additional key
${RawKeyEventDataWindows.modifierCaps}
, but isn't."
,
);
if
(
key
!=
ModifierKey
.
capsLockModifier
)
{
expect
(
data
.
getModifierSide
(
key
),
equals
(
modifierTests
[
modifier
].
side
));
}
else
{
expect
(
data
.
getModifierSide
(
key
),
equals
(
KeyboardSide
.
all
));
}
}
else
{
expect
(
data
.
isModifierPressed
(
key
,
side:
modifierTests
[
modifier
].
side
),
isFalse
,
reason:
'
$key
should not be pressed with metaState
$modifier
'
'and additional key
${RawKeyEventDataWindows.modifierCaps}
.'
,
);
}
}
}
});
test
(
'Printable keyboard keys are correctly translated'
,
()
{
const
int
unmodifiedCharacter
=
97
;
// ASCII value for 'a'.
final
RawKeyEvent
keyAEvent
=
RawKeyEvent
.
fromMessage
(
const
<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'windows'
,
'keyCode'
:
0x00000000
,
'characterCodePoint'
:
unmodifiedCharacter
,
'scanCode'
:
0x0000001e
,
'modifiers'
:
0x0
,
});
final
RawKeyEventDataWindows
data
=
keyAEvent
.
data
as
RawKeyEventDataWindows
;
expect
(
data
.
physicalKey
,
equals
(
PhysicalKeyboardKey
.
keyA
));
expect
(
data
.
logicalKey
,
equals
(
LogicalKeyboardKey
.
keyA
));
expect
(
data
.
keyLabel
,
equals
(
'a'
));
});
test
(
'Control keyboard keys are correctly translated'
,
()
{
final
RawKeyEvent
escapeKeyEvent
=
RawKeyEvent
.
fromMessage
(
const
<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'windows'
,
'keyCode'
:
27
,
// keycode for escape key
'scanCode'
:
0x00000001
,
// scanCode for escape key
'characterCodePoint'
:
0
,
'modifiers'
:
0x0
,
});
final
RawKeyEventDataWindows
data
=
escapeKeyEvent
.
data
as
RawKeyEventDataWindows
;
expect
(
data
.
physicalKey
,
equals
(
PhysicalKeyboardKey
.
escape
));
expect
(
data
.
logicalKey
,
equals
(
LogicalKeyboardKey
.
escape
));
expect
(
data
.
keyLabel
,
isNull
);
});
test
(
'Modifier keyboard keys are correctly translated'
,
()
{
final
RawKeyEvent
shiftLeftKeyEvent
=
RawKeyEvent
.
fromMessage
(
const
<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'windows'
,
'keyCode'
:
160
,
// keyCode for left shift.
'scanCode'
:
0x0000002a
,
// scanCode for left shift.
'characterCodePoint'
:
0
,
'modifiers'
:
RawKeyEventDataWindows
.
modifierLeftShift
,
});
final
RawKeyEventDataWindows
data
=
shiftLeftKeyEvent
.
data
as
RawKeyEventDataWindows
;
expect
(
data
.
physicalKey
,
equals
(
PhysicalKeyboardKey
.
shiftLeft
));
expect
(
data
.
logicalKey
,
equals
(
LogicalKeyboardKey
.
shiftLeft
));
expect
(
data
.
keyLabel
,
isNull
);
});
test
(
'Unprintable keyboard keys are correctly translated'
,
()
{
final
RawKeyEvent
leftArrowKey
=
RawKeyEvent
.
fromMessage
(
const
<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'windows'
,
'keyCode'
:
37
,
// keyCode for left arrow.
'scanCode'
:
0x0000e04b
,
// scanCode for left arrow.
'characterCodePoint'
:
0
,
'modifiers'
:
0
,
});
final
RawKeyEventDataWindows
data
=
leftArrowKey
.
data
as
RawKeyEventDataWindows
;
expect
(
data
.
physicalKey
,
equals
(
PhysicalKeyboardKey
.
arrowLeft
));
expect
(
data
.
logicalKey
,
equals
(
LogicalKeyboardKey
.
arrowLeft
));
expect
(
data
.
logicalKey
.
keyLabel
,
isNull
);
});
},
skip:
isBrowser
);
group
(
'RawKeyEventDataLinux-GFLW'
,
()
{
const
Map
<
int
,
_ModifierCheck
>
modifierTests
=
<
int
,
_ModifierCheck
>{
GLFWKeyHelper
.
modifierAlt
:
_ModifierCheck
(
ModifierKey
.
altModifier
,
KeyboardSide
.
any
),
...
...
packages/flutter_test/lib/src/event_simulation.dart
View file @
a0f7f6ca
...
...
@@ -40,6 +40,7 @@ class KeyEventSimulator {
case
'macos'
:
case
'linux'
:
case
'web'
:
case
'windows'
:
return
true
;
}
return
false
;
...
...
@@ -62,6 +63,9 @@ class KeyEventSimulator {
case
'linux'
:
map
=
kLinuxToPhysicalKey
;
break
;
case
'windows'
:
map
=
kWindowsToPhysicalKey
;
break
;
case
'web'
:
// web doesn't have int type code
return
null
;
...
...
@@ -95,6 +99,9 @@ class KeyEventSimulator {
case
'linux'
:
map
=
kGlfwToLogicalKey
;
break
;
case
'windows'
:
map
=
kWindowsToLogicalKey
;
break
;
}
for
(
final
int
code
in
map
.
keys
)
{
if
(
key
.
keyId
==
map
[
code
].
keyId
)
{
...
...
@@ -132,6 +139,9 @@ class KeyEventSimulator {
case
'web'
:
map
=
kWebToPhysicalKey
;
break
;
case
'windows'
:
map
=
kWindowsToPhysicalKey
;
break
;
}
for
(
final
PhysicalKeyboardKey
physicalKey
in
map
.
values
)
{
if
(
key
.
debugName
==
physicalKey
.
debugName
)
{
...
...
@@ -195,6 +205,12 @@ class KeyEventSimulator {
result
[
'code'
]
=
_getWebKeyCode
(
key
);
result
[
'key'
]
=
''
;
result
[
'metaState'
]
=
_getWebModifierFlags
(
key
,
isDown
);
break
;
case
'windows'
:
result
[
'keyCode'
]
=
keyCode
;
result
[
'scanCode'
]
=
scanCode
;
result
[
'characterCodePoint'
]
=
key
.
keyLabel
?.
codeUnitAt
(
0
)
??
0
;
result
[
'modifiers'
]
=
_getWindowsModifierFlags
(
key
,
isDown
);
}
return
result
;
}
...
...
@@ -272,6 +288,59 @@ class KeyEventSimulator {
return
result
;
}
static
int
_getWindowsModifierFlags
(
LogicalKeyboardKey
newKey
,
bool
isDown
)
{
int
result
=
0
;
final
Set
<
LogicalKeyboardKey
>
pressed
=
RawKeyboard
.
instance
.
keysPressed
;
if
(
isDown
)
{
pressed
.
add
(
newKey
);
}
else
{
pressed
.
remove
(
newKey
);
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
shift
))
{
result
|=
RawKeyEventDataWindows
.
modifierShift
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
shiftLeft
))
{
result
|=
RawKeyEventDataWindows
.
modifierLeftShift
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
shiftRight
))
{
result
|=
RawKeyEventDataWindows
.
modifierRightShift
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
metaLeft
))
{
result
|=
RawKeyEventDataWindows
.
modifierLeftMeta
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
metaRight
))
{
result
|=
RawKeyEventDataWindows
.
modifierRightMeta
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
control
))
{
result
|=
RawKeyEventDataWindows
.
modifierControl
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
controlLeft
))
{
result
|=
RawKeyEventDataWindows
.
modifierLeftControl
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
controlRight
))
{
result
|=
RawKeyEventDataWindows
.
modifierRightControl
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
alt
))
{
result
|=
RawKeyEventDataWindows
.
modifierAlt
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
altLeft
))
{
result
|=
RawKeyEventDataWindows
.
modifierLeftAlt
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
altRight
))
{
result
|=
RawKeyEventDataWindows
.
modifierRightAlt
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
capsLock
))
{
result
|=
RawKeyEventDataWindows
.
modifierCaps
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
numLock
))
{
result
|=
RawKeyEventDataWindows
.
modifierNumLock
;
}
if
(
pressed
.
contains
(
LogicalKeyboardKey
.
scrollLock
))
{
result
|=
RawKeyEventDataWindows
.
modifierScrollLock
;
}
return
result
;
}
static
int
_getFuchsiaModifierFlags
(
LogicalKeyboardKey
newKey
,
bool
isDown
)
{
int
result
=
0
;
final
Set
<
LogicalKeyboardKey
>
pressed
=
RawKeyboard
.
instance
.
keysPressed
;
...
...
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