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
baac9a8a
Unverified
Commit
baac9a8a
authored
May 21, 2022
by
Tong Mu
Committed by
GitHub
May 21, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[Keyboard, Windows] Fix that IME events are still dispatched to FocusNode.onKey (#104244)
parent
a79233cb
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
65 additions
and
34 deletions
+65
-34
hardware_keyboard.dart
packages/flutter/lib/src/services/hardware_keyboard.dart
+36
-12
raw_keyboard.dart
packages/flutter/lib/src/services/raw_keyboard.dart
+5
-20
raw_keyboard_test.dart
packages/flutter/test/services/raw_keyboard_test.dart
+24
-2
No files found.
packages/flutter/lib/src/services/hardware_keyboard.dart
View file @
baac9a8a
...
...
@@ -766,6 +766,11 @@ class KeyEventManager {
// dispatchable [RawKeyEvent] is available.
final
List
<
KeyEvent
>
_keyEventsSinceLastMessage
=
<
KeyEvent
>[];
// When a RawKeyDownEvent is skipped ([RawKeyEventData.shouldDispatchEvent]
// is false), its physical key will be recorded here, so that its up event
// can also be properly skipped.
final
Set
<
PhysicalKeyboardKey
>
_skippedRawKeysPressed
=
<
PhysicalKeyboardKey
>{};
/// Dispatch a key data to global and leaf listeners.
///
/// This method is the handler to the global `onKeyData` API.
...
...
@@ -843,21 +848,40 @@ class KeyEventManager {
_rawKeyboard
.
addListener
(
_convertRawEventAndStore
);
}
final
RawKeyEvent
rawEvent
=
RawKeyEvent
.
fromMessage
(
message
as
Map
<
String
,
dynamic
>);
// The following `handleRawKeyEvent` will call `_convertRawEventAndStore`
// unless the event is not dispatched.
bool
handled
=
_rawKeyboard
.
handleRawKeyEvent
(
rawEvent
);
for
(
final
KeyEvent
event
in
_keyEventsSinceLastMessage
)
{
handled
=
_hardwareKeyboard
.
handleKeyEvent
(
event
)
||
handled
;
}
if
(
_transitMode
==
KeyDataTransitMode
.
rawKeyData
)
{
assert
(
setEquals
(
_rawKeyboard
.
physicalKeysPressed
,
_hardwareKeyboard
.
physicalKeysPressed
),
'RawKeyboard reported
${_rawKeyboard.physicalKeysPressed}
, '
'while HardwareKeyboard reported
${_hardwareKeyboard.physicalKeysPressed}
'
);
bool
shouldDispatch
=
true
;
if
(
rawEvent
is
RawKeyDownEvent
)
{
if
(!
rawEvent
.
data
.
shouldDispatchEvent
())
{
shouldDispatch
=
false
;
_skippedRawKeysPressed
.
add
(
rawEvent
.
physicalKey
);
}
else
{
_skippedRawKeysPressed
.
remove
(
rawEvent
.
physicalKey
);
}
}
else
if
(
rawEvent
is
RawKeyUpEvent
)
{
if
(
_skippedRawKeysPressed
.
contains
(
rawEvent
.
physicalKey
))
{
_skippedRawKeysPressed
.
remove
(
rawEvent
.
physicalKey
);
shouldDispatch
=
false
;
}
}
handled
=
_dispatchKeyMessage
(
_keyEventsSinceLastMessage
,
rawEvent
)
||
handled
;
_keyEventsSinceLastMessage
.
clear
();
bool
handled
=
true
;
if
(
shouldDispatch
)
{
// The following `handleRawKeyEvent` will call `_convertRawEventAndStore`
// unless the event is not dispatched.
handled
=
_rawKeyboard
.
handleRawKeyEvent
(
rawEvent
);
for
(
final
KeyEvent
event
in
_keyEventsSinceLastMessage
)
{
handled
=
_hardwareKeyboard
.
handleKeyEvent
(
event
)
||
handled
;
}
if
(
_transitMode
==
KeyDataTransitMode
.
rawKeyData
)
{
assert
(
setEquals
(
_rawKeyboard
.
physicalKeysPressed
,
_hardwareKeyboard
.
physicalKeysPressed
),
'RawKeyboard reported
${_rawKeyboard.physicalKeysPressed}
, '
'while HardwareKeyboard reported
${_hardwareKeyboard.physicalKeysPressed}
'
);
}
handled
=
_dispatchKeyMessage
(
_keyEventsSinceLastMessage
,
rawEvent
)
||
handled
;
_keyEventsSinceLastMessage
.
clear
();
}
return
<
String
,
dynamic
>{
'handled'
:
handled
};
}
...
...
packages/flutter/lib/src/services/raw_keyboard.dart
View file @
baac9a8a
...
...
@@ -661,27 +661,13 @@ class RawKeyboard {
/// Process a new [RawKeyEvent] by recording the state changes and
/// dispatching to listeners.
bool
handleRawKeyEvent
(
RawKeyEvent
event
)
{
bool
shouldDispatch
=
true
;
if
(
event
is
RawKeyDownEvent
)
{
if
(
event
.
data
.
shouldDispatchEvent
())
{
_keysPressed
[
event
.
physicalKey
]
=
event
.
logicalKey
;
}
else
{
shouldDispatch
=
false
;
_hiddenKeysPressed
.
add
(
event
.
physicalKey
);
}
_keysPressed
[
event
.
physicalKey
]
=
event
.
logicalKey
;
}
else
if
(
event
is
RawKeyUpEvent
)
{
if
(!
_hiddenKeysPressed
.
contains
(
event
.
physicalKey
))
{
// Use the physical key in the key up event to find the physical key from
// the corresponding key down event and remove it, even if the logical
// keys don't match.
_keysPressed
.
remove
(
event
.
physicalKey
);
}
else
{
_hiddenKeysPressed
.
remove
(
event
.
physicalKey
);
shouldDispatch
=
false
;
}
}
if
(!
shouldDispatch
)
{
return
true
;
// Use the physical key in the key up event to find the physical key from
// the corresponding key down event and remove it, even if the logical
// keys don't match.
_keysPressed
.
remove
(
event
.
physicalKey
);
}
// Make sure that the modifiers reflect reality, in case a modifier key was
// pressed/released while the app didn't have focus.
...
...
@@ -855,7 +841,6 @@ class RawKeyboard {
}
final
Map
<
PhysicalKeyboardKey
,
LogicalKeyboardKey
>
_keysPressed
=
<
PhysicalKeyboardKey
,
LogicalKeyboardKey
>{};
final
Set
<
PhysicalKeyboardKey
>
_hiddenKeysPressed
=
<
PhysicalKeyboardKey
>{};
/// Returns the set of keys currently pressed.
Set
<
LogicalKeyboardKey
>
get
keysPressed
=>
_keysPressed
.
values
.
toSet
();
...
...
packages/flutter/test/services/raw_keyboard_test.dart
View file @
baac9a8a
...
...
@@ -1936,6 +1936,28 @@ void main() {
const
String
platform
=
'windows'
;
bool
lastHandled
=
true
;
final
List
<
RawKeyEvent
>
events
=
<
RawKeyEvent
>[];
// Test both code paths: addListener, and FocusNode.onKey.
RawKeyboard
.
instance
.
addListener
(
events
.
add
);
final
FocusNode
node
=
FocusNode
(
onKey:
(
_
,
RawKeyEvent
event
)
{
events
.
add
(
event
);
return
KeyEventResult
.
ignored
;
},
);
await
tester
.
pumpWidget
(
RawKeyboardListener
(
focusNode:
node
,
child:
Container
(),
));
node
.
requestFocus
();
await
tester
.
pumpAndSettle
();
// Dispatch an arbitrary key press for the correct transit mode.
await
simulateKeyDownEvent
(
LogicalKeyboardKey
.
keyA
);
await
simulateKeyUpEvent
(
LogicalKeyboardKey
.
keyA
);
expect
(
events
,
hasLength
(
4
));
events
.
clear
();
// Simulate raw events because VK_PROCESSKEY does not exist in the key mapping.
Future
<
void
>
simulateKeyEventMessage
(
String
type
,
int
keyCode
,
int
scanCode
)
{
return
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
handlePlatformMessage
(
...
...
@@ -1953,7 +1975,7 @@ void main() {
},
);
}
RawKeyboard
.
instance
.
addListener
(
events
.
add
);
await
simulateKeyEventMessage
(
'keydown'
,
229
,
30
);
expect
(
events
,
isEmpty
);
expect
(
lastHandled
,
true
);
...
...
@@ -1962,7 +1984,7 @@ void main() {
expect
(
events
,
isEmpty
);
expect
(
lastHandled
,
true
);
expect
(
RawKeyboard
.
instance
.
keysPressed
,
isEmpty
);
});
}
,
variant:
KeySimulatorTransitModeVariant
.
keyDataThenRawKeyData
()
);
test
(
'data.toString'
,
()
{
expect
(
RawKeyEvent
.
fromMessage
(
const
<
String
,
Object
?>{
...
...
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