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
7959c395
Unverified
Commit
7959c395
authored
Feb 28, 2022
by
Tong Mu
Committed by
GitHub
Feb 28, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Keyboard] Correctly convert down events that are immediately synthesized released (#99200)
parent
b44cbe1d
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
72 additions
and
7 deletions
+72
-7
hardware_keyboard.dart
packages/flutter/lib/src/services/hardware_keyboard.dart
+22
-7
hardware_keyboard_test.dart
packages/flutter/test/services/hardware_keyboard_test.dart
+50
-0
No files found.
packages/flutter/lib/src/services/hardware_keyboard.dart
View file @
7959c395
...
...
@@ -887,6 +887,7 @@ class KeyEventManager {
final
PhysicalKeyboardKey
physicalKey
=
rawEvent
.
physicalKey
;
final
LogicalKeyboardKey
logicalKey
=
rawEvent
.
logicalKey
;
final
Set
<
PhysicalKeyboardKey
>
physicalKeysPressed
=
_hardwareKeyboard
.
physicalKeysPressed
;
final
List
<
KeyEvent
>
eventAfterwards
=
<
KeyEvent
>[];
final
KeyEvent
?
mainEvent
;
final
LogicalKeyboardKey
?
recordedLogicalMain
=
_hardwareKeyboard
.
lookUpLayout
(
physicalKey
);
final
Duration
timeStamp
=
ServicesBinding
.
instance
.
currentSystemFrameTimeStamp
;
...
...
@@ -923,12 +924,24 @@ class KeyEventManager {
}
}
for
(
final
PhysicalKeyboardKey
key
in
physicalKeysPressed
.
difference
(
_rawKeyboard
.
physicalKeysPressed
))
{
_keyEventsSinceLastMessage
.
add
(
KeyUpEvent
(
physicalKey:
key
,
logicalKey:
_hardwareKeyboard
.
lookUpLayout
(
key
)!,
timeStamp:
timeStamp
,
synthesized:
true
,
));
if
(
key
==
physicalKey
)
{
// Somehow, a down event is dispatched but the key is absent from
// keysPressed. Synthesize a up event for the key, but this event must
// be added after the main key down event.
eventAfterwards
.
add
(
KeyUpEvent
(
physicalKey:
key
,
logicalKey:
logicalKey
,
timeStamp:
timeStamp
,
synthesized:
true
,
));
}
else
{
_keyEventsSinceLastMessage
.
add
(
KeyUpEvent
(
physicalKey:
key
,
logicalKey:
_hardwareKeyboard
.
lookUpLayout
(
key
)!,
timeStamp:
timeStamp
,
synthesized:
true
,
));
}
}
for
(
final
PhysicalKeyboardKey
key
in
_rawKeyboard
.
physicalKeysPressed
.
difference
(
physicalKeysPressed
))
{
_keyEventsSinceLastMessage
.
add
(
KeyDownEvent
(
...
...
@@ -938,8 +951,10 @@ class KeyEventManager {
synthesized:
true
,
));
}
if
(
mainEvent
!=
null
)
if
(
mainEvent
!=
null
)
{
_keyEventsSinceLastMessage
.
add
(
mainEvent
);
}
_keyEventsSinceLastMessage
.
addAll
(
eventAfterwards
);
}
/// Reset the inferred platform transit mode and related states.
...
...
packages/flutter/test/services/hardware_keyboard_test.dart
View file @
7959c395
...
...
@@ -195,6 +195,56 @@ void main() {
logs
.
clear
();
},
variant:
KeySimulatorTransitModeVariant
.
all
());
// Regression test for https://github.com/flutter/flutter/issues/99196 .
//
// In rawKeyData mode, if a key down event is dispatched but immediately
// synthesized to be released, the old logic would trigger a Null check
// _CastError on _hardwareKeyboard.lookUpLayout(key). The original scenario
// that this is triggered on Android is unknown. Here we make up a scenario
// where a ShiftLeft key down is dispatched but the modifier bit is not set.
testWidgets
(
'Correctly convert down events that are synthesized released'
,
(
WidgetTester
tester
)
async
{
final
FocusNode
focusNode
=
FocusNode
();
final
List
<
KeyEvent
>
events
=
<
KeyEvent
>[];
await
tester
.
pumpWidget
(
KeyboardListener
(
autofocus:
true
,
focusNode:
focusNode
,
child:
Container
(),
onKeyEvent:
(
KeyEvent
event
)
{
events
.
add
(
event
);
},
),
);
// Dispatch an arbitrary event to bypass the pressedKeys check.
await
simulateKeyDownEvent
(
LogicalKeyboardKey
.
keyA
,
platform:
'web'
);
// Dispatch an
final
Map
<
String
,
dynamic
>
data2
=
KeyEventSimulator
.
getKeyData
(
LogicalKeyboardKey
.
shiftLeft
,
platform:
'web'
,
)..[
'metaState'
]
=
0
;
await
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
handlePlatformMessage
(
SystemChannels
.
keyEvent
.
name
,
SystemChannels
.
keyEvent
.
codec
.
encodeMessage
(
data2
),
(
ByteData
?
data
)
{},
);
expect
(
events
,
hasLength
(
3
));
expect
(
events
[
1
],
isA
<
KeyDownEvent
>());
expect
(
events
[
1
].
logicalKey
,
LogicalKeyboardKey
.
shiftLeft
);
expect
(
events
[
1
].
synthesized
,
false
);
expect
(
events
[
2
],
isA
<
KeyUpEvent
>());
expect
(
events
[
2
].
logicalKey
,
LogicalKeyboardKey
.
shiftLeft
);
expect
(
events
[
2
].
synthesized
,
true
);
expect
(
ServicesBinding
.
instance
.
keyboard
.
physicalKeysPressed
,
equals
(<
PhysicalKeyboardKey
>{
PhysicalKeyboardKey
.
keyA
,
}));
},
variant:
const
KeySimulatorTransitModeVariant
(<
KeyDataTransitMode
>{
KeyDataTransitMode
.
rawKeyData
,
}));
testWidgets
(
'Instantly dispatch synthesized key events when the queue is empty'
,
(
WidgetTester
tester
)
async
{
final
FocusNode
focusNode
=
FocusNode
();
final
List
<
int
>
logs
=
<
int
>[];
...
...
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