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
073cefad
Unverified
Commit
073cefad
authored
Nov 21, 2022
by
Bruno Leroux
Committed by
GitHub
Nov 21, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[RawKeyboard] Fix Linux remapped CapsLock throws (#115009)
Co-authored-by:
Bruno Leroux
<
bruno.leroux@gmail.com
>
parent
567d0045
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
95 additions
and
36 deletions
+95
-36
raw_keyboard.dart
packages/flutter/lib/src/services/raw_keyboard.dart
+12
-3
raw_keyboard_web.dart
packages/flutter/lib/src/services/raw_keyboard_web.dart
+2
-2
raw_keyboard_test.dart
packages/flutter/test/services/raw_keyboard_test.dart
+81
-31
No files found.
packages/flutter/lib/src/services/raw_keyboard.dart
View file @
073cefad
...
...
@@ -824,9 +824,18 @@ class RawKeyboard {
modifierKeys
[
physicalModifier
]
=
_allModifiers
[
physicalModifier
]!;
}
}
_allModifiersExceptFn
.
keys
.
where
((
PhysicalKeyboardKey
key
)
=>
!
anySideKeys
.
contains
(
key
))
.
forEach
(
_keysPressed
.
remove
);
// On Linux, CapsLock key can be mapped to a non-modifier logical key:
// https://github.com/flutter/flutter/issues/114591.
// This is also affecting Flutter Web on Linux.
final
bool
nonModifierCapsLock
=
(
event
.
data
is
RawKeyEventDataLinux
||
event
.
data
is
RawKeyEventDataWeb
)
&&
_keysPressed
[
PhysicalKeyboardKey
.
capsLock
]
!=
null
&&
_keysPressed
[
PhysicalKeyboardKey
.
capsLock
]
!=
LogicalKeyboardKey
.
capsLock
;
for
(
final
PhysicalKeyboardKey
physicalKey
in
_allModifiersExceptFn
.
keys
)
{
final
bool
skipReleasingKey
=
nonModifierCapsLock
&&
physicalKey
==
PhysicalKeyboardKey
.
capsLock
;
if
(!
anySideKeys
.
contains
(
physicalKey
)
&&
!
skipReleasingKey
)
{
_keysPressed
.
remove
(
physicalKey
);
}
}
if
(
event
.
data
is
!
RawKeyEventDataFuchsia
&&
event
.
data
is
!
RawKeyEventDataMacOs
)
{
// On Fuchsia and macOS, the Fn key is not considered a modifier key.
_keysPressed
.
remove
(
PhysicalKeyboardKey
.
fn
);
...
...
packages/flutter/lib/src/services/raw_keyboard_web.dart
View file @
073cefad
...
...
@@ -106,8 +106,8 @@ class RawKeyEventDataWeb extends RawKeyEventData {
return
maybeLocationKey
;
}
// Look to see if the [
code
] is one we know about and have a mapping for.
final
LogicalKeyboardKey
?
newKey
=
kWebToLogicalKey
[
code
];
// Look to see if the [
key
] is one we know about and have a mapping for.
final
LogicalKeyboardKey
?
newKey
=
kWebToLogicalKey
[
key
];
if
(
newKey
!=
null
)
{
return
newKey
;
}
...
...
packages/flutter/test/services/raw_keyboard_test.dart
View file @
073cefad
...
...
@@ -350,6 +350,33 @@ void main() {
);
},
skip:
isBrowser
);
// [intended] This is a GLFW-specific test.
Future
<
void
>
simulateGTKKeyEvent
(
bool
keyDown
,
int
scancode
,
int
keycode
,
int
modifiers
)
async
{
final
Map
<
String
,
dynamic
>
data
=
<
String
,
dynamic
>{
'type'
:
keyDown
?
'keydown'
:
'keyup'
,
'keymap'
:
'linux'
,
'toolkit'
:
'gtk'
,
'scanCode'
:
scancode
,
'keyCode'
:
keycode
,
'modifiers'
:
modifiers
,
};
// Dispatch an empty key data to disable HardwareKeyboard sanity check,
// since we're only testing if the raw keyboard can handle the message.
// In a real application, the embedder responder will send the correct key data
// (which is tested in the engine).
TestDefaultBinaryMessengerBinding
.
instance
!.
keyEventManager
.
handleKeyData
(
const
ui
.
KeyData
(
type:
ui
.
KeyEventType
.
down
,
timeStamp:
Duration
.
zero
,
logical:
0
,
physical:
0
,
character:
null
,
synthesized:
false
,
));
await
TestDefaultBinaryMessengerBinding
.
instance
!.
defaultBinaryMessenger
.
handlePlatformMessage
(
SystemChannels
.
keyEvent
.
name
,
SystemChannels
.
keyEvent
.
codec
.
encodeMessage
(
data
),
(
ByteData
?
data
)
{},
);
}
// Regression test for https://github.com/flutter/flutter/issues/93278 .
//
...
...
@@ -357,38 +384,11 @@ void main() {
// result in a AltRight down event without Alt bitmask.
testWidgets
(
'keysPressed modifiers are synchronized with key events on Linux GTK (down events)'
,
(
WidgetTester
tester
)
async
{
expect
(
RawKeyboard
.
instance
.
keysPressed
,
isEmpty
);
Future
<
void
>
simulate
(
bool
keyDown
,
int
scancode
,
int
keycode
,
int
modifiers
)
async
{
final
Map
<
String
,
dynamic
>
data
=
<
String
,
dynamic
>{
'type'
:
keyDown
?
'keydown'
:
'keyup'
,
'keymap'
:
'linux'
,
'toolkit'
:
'gtk'
,
'scanCode'
:
scancode
,
'keyCode'
:
keycode
,
'modifiers'
:
modifiers
,
};
// Dispatch an empty key data to disable HardwareKeyboard sanity check,
// since we're only testing if the raw keyboard can handle the message.
// In real application the embedder responder will send correct key data
// (which is tested in the engine.)
TestDefaultBinaryMessengerBinding
.
instance
!.
keyEventManager
.
handleKeyData
(
const
ui
.
KeyData
(
type:
ui
.
KeyEventType
.
down
,
timeStamp:
Duration
.
zero
,
logical:
0
,
physical:
0
,
character:
null
,
synthesized:
false
,
));
await
TestDefaultBinaryMessengerBinding
.
instance
!.
defaultBinaryMessenger
.
handlePlatformMessage
(
SystemChannels
.
keyEvent
.
name
,
SystemChannels
.
keyEvent
.
codec
.
encodeMessage
(
data
),
(
ByteData
?
data
)
{},
);
}
await
simulate
(
true
,
0x6c
/*AltRight*/
,
0xffea
/*AltRight*/
,
0x2000000
);
await
simulate
(
true
,
0x32
/*ShiftLeft*/
,
0xfe08
/*NextGroup*/
,
0x2000008
/*MOD3*/
);
await
simulate
(
false
,
0x6c
/*AltRight*/
,
0xfe03
/*AltRight*/
,
0x2002008
/*MOD3|Reserve14*/
);
await
simulate
(
true
,
0x6c
/*AltRight*/
,
0xfe03
/*AltRight*/
,
0x2002000
/*Reserve14*/
);
await
simulate
GTKKeyEvent
(
true
,
0x6c
/*AltRight*/
,
0xffea
/*AltRight*/
,
0x2000000
);
await
simulate
GTKKeyEvent
(
true
,
0x32
/*ShiftLeft*/
,
0xfe08
/*NextGroup*/
,
0x2000008
/*MOD3*/
);
await
simulate
GTKKeyEvent
(
false
,
0x6c
/*AltRight*/
,
0xfe03
/*AltRight*/
,
0x2002008
/*MOD3|Reserve14*/
);
await
simulate
GTKKeyEvent
(
true
,
0x6c
/*AltRight*/
,
0xfe03
/*AltRight*/
,
0x2002000
/*Reserve14*/
);
expect
(
RawKeyboard
.
instance
.
keysPressed
,
equals
(
...
...
@@ -399,6 +399,56 @@ void main() {
);
},
skip:
isBrowser
);
// [intended] This is a GTK-specific test.
// Regression test for https://github.com/flutter/flutter/issues/114591 .
//
// On Linux, CapsLock can be remapped to a non-modifier key.
testWidgets
(
'CapsLock should not be release when remapped on Linux'
,
(
WidgetTester
tester
)
async
{
expect
(
RawKeyboard
.
instance
.
keysPressed
,
isEmpty
);
await
simulateGTKKeyEvent
(
true
,
0x42
/*CapsLock*/
,
0xff08
/*Backspace*/
,
0x2000000
);
expect
(
RawKeyboard
.
instance
.
keysPressed
,
equals
(
<
LogicalKeyboardKey
>{
LogicalKeyboardKey
.
backspace
,
},
),
);
},
skip:
isBrowser
);
// [intended] This is a GTK-specific test.
// Regression test for https://github.com/flutter/flutter/issues/114591 .
//
// On Web, CapsLock can be remapped to a non-modifier key.
testWidgets
(
'CapsLock should not be release when remapped on Web'
,
(
WidgetTester
_
)
async
{
final
List
<
RawKeyEvent
>
events
=
<
RawKeyEvent
>[];
RawKeyboard
.
instance
.
addListener
(
events
.
add
);
addTearDown
(()
{
RawKeyboard
.
instance
.
removeListener
(
events
.
add
);
});
await
TestDefaultBinaryMessengerBinding
.
instance
!.
defaultBinaryMessenger
.
handlePlatformMessage
(
SystemChannels
.
keyEvent
.
name
,
SystemChannels
.
keyEvent
.
codec
.
encodeMessage
(
const
<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'web'
,
'code'
:
'CapsLock'
,
'key'
:
'Backspace'
,
'location'
:
0
,
'metaState'
:
0
,
'keyCode'
:
8
,
}),
(
ByteData
?
data
)
{
},
);
expect
(
RawKeyboard
.
instance
.
keysPressed
,
equals
(
<
LogicalKeyboardKey
>{
LogicalKeyboardKey
.
backspace
,
},
),
);
},
skip:
!
isBrowser
);
// [intended] This is a Browser-specific test.
testWidgets
(
'keysPressed modifiers are synchronized with key events on web'
,
(
WidgetTester
tester
)
async
{
expect
(
RawKeyboard
.
instance
.
keysPressed
,
isEmpty
);
// Generate the data for a regular key down event. Change the modifiers so
...
...
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