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
c163ed96
Unverified
Commit
c163ed96
authored
Mar 18, 2019
by
Francisco Magdaleno
Committed by
GitHub
Mar 18, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adds macOS raw keyboard mapping (#29231)
parent
75c50da5
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
649 additions
and
1 deletion
+649
-1
raw_keyboard.dart
dev/manual_tests/lib/raw_keyboard.dart
+5
-0
keyboard_maps.tmpl
dev/tools/gen_keycodes/data/keyboard_maps.tmpl
+12
-0
code_gen.dart
dev/tools/gen_keycodes/lib/code_gen.dart
+30
-0
services.dart
packages/flutter/lib/services.dart
+1
-0
keyboard_maps.dart
packages/flutter/lib/src/services/keyboard_maps.dart
+147
-0
raw_keyboard.dart
packages/flutter/lib/src/services/raw_keyboard.dart
+10
-1
raw_keyboard_macos.dart
packages/flutter/lib/src/services/raw_keyboard_macos.dart
+315
-0
raw_keyboard_test.dart
packages/flutter/test/services/raw_keyboard_test.dart
+129
-0
No files found.
dev/manual_tests/lib/raw_keyboard.dart
View file @
c163ed96
...
...
@@ -92,6 +92,11 @@ class _HardwareKeyDemoState extends State<RawKeyboardDemo> {
dataText
.
add
(
Text
(
'codePoint:
${data.codePoint}
(
${_asHex(data.codePoint)}
)'
));
dataText
.
add
(
Text
(
'hidUsage:
${data.hidUsage}
(
${_asHex(data.hidUsage)}
)'
));
dataText
.
add
(
Text
(
'modifiers:
${data.modifiers}
(
${_asHex(data.modifiers)}
)'
));
}
else
if
(
data
is
RawKeyEventDataMacOs
)
{
dataText
.
add
(
Text
(
'keyCode:
${data.keyCode}
(
${_asHex(data.keyCode)}
)'
));
dataText
.
add
(
Text
(
'characters:
${data.characters}
'
));
dataText
.
add
(
Text
(
'charactersIgnoringModifiers:
${data.charactersIgnoringModifiers}
'
));
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/data/keyboard_maps.tmpl
View file @
c163ed96
...
...
@@ -38,3 +38,15 @@ const Map<int, LogicalKeyboardKey> kFuchsiaToLogicalKey = <int, LogicalKeyboardK
const Map<int, PhysicalKeyboardKey> kFuchsiaToPhysicalKey = <int, PhysicalKeyboardKey>{
@@@FUCHSIA_SCAN_CODE_MAP@@@
};
/// Maps macOS-specific key code values representing [PhysicalKeyboardKey].
const Map<int, PhysicalKeyboardKey> kMacOsToPhysicalKey = <int, PhysicalKeyboardKey>{
@@@MACOS_SCAN_CODE_MAP@@@
};
/// A map of macOS key 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> kMacOsNumPadMap = <int, LogicalKeyboardKey>{
@@@MACOS_NUMPAD_MAP@@@
};
dev/tools/gen_keycodes/lib/code_gen.dart
View file @
c163ed96
...
...
@@ -135,6 +135,31 @@ $otherComments static const LogicalKeyboardKey ${entry.constantName} = LogicalK
return
androidScanCodeMap
.
toString
().
trimRight
();
}
/// This generates the map of macOS key codes to physical keys.
String
get
macOsScanCodeMap
{
final
StringBuffer
macOsScanCodeMap
=
StringBuffer
();
for
(
Key
entry
in
keyData
.
data
)
{
if
(
entry
.
macOsScanCode
!=
null
)
{
macOsScanCodeMap
.
writeln
(
'
${toHex(entry.macOsScanCode)}
: PhysicalKeyboardKey.
${entry.constantName}
,'
);
}
}
return
macOsScanCodeMap
.
toString
().
trimRight
();
}
/// This generates the map of macOS number pad key codes to logical keys.
String
get
macOsNumpadMap
{
final
StringBuffer
macOsNumPadMap
=
StringBuffer
();
final
List
<
Key
>
onlyNumpads
=
keyData
.
data
.
where
((
Key
entry
)
{
return
entry
.
constantName
.
startsWith
(
'numpad'
)
&&
entry
.
keyLabel
!=
null
;
}).
toList
();
for
(
Key
entry
in
onlyNumpads
)
{
if
(
entry
.
macOsScanCode
!=
null
)
{
macOsNumPadMap
.
writeln
(
'
${toHex(entry.macOsScanCode)}
: LogicalKeyboardKey.
${entry.constantName}
,'
);
}
}
return
macOsNumPadMap
.
toString
().
trimRight
();
}
/// This generates the map of Fuchsia key codes to logical keys.
String
get
fuchsiaKeyCodeMap
{
final
StringBuffer
fuchsiaKeyCodeMap
=
StringBuffer
();
...
...
@@ -174,12 +199,17 @@ $otherComments static const LogicalKeyboardKey ${entry.constantName} = LogicalK
/// Substitutes the various platform specific maps into the template file for
/// keyboard_maps.dart.
String
generateKeyboardMaps
()
{
// There is no macOS keycode map since macOS uses keycode to represent a physical key.
// The LogicalKeyboardKey is generated by raw_keyboard_macos.dart from the unmodified characters
// from NSEvent.
final
Map
<
String
,
String
>
mappings
=
<
String
,
String
>{
'ANDROID_SCAN_CODE_MAP'
:
androidScanCodeMap
,
'ANDROID_KEY_CODE_MAP'
:
androidKeyCodeMap
,
'ANDROID_NUMPAD_MAP'
:
androidNumpadMap
,
'FUCHSIA_SCAN_CODE_MAP'
:
fuchsiaHidCodeMap
,
'FUCHSIA_KEY_CODE_MAP'
:
fuchsiaKeyCodeMap
,
'MACOS_SCAN_CODE_MAP'
:
macOsScanCodeMap
,
'MACOS_NUMPAD_MAP'
:
macOsNumpadMap
,
};
final
String
template
=
File
(
path
.
join
(
flutterRoot
.
path
,
'dev'
,
'tools'
,
'gen_keycodes'
,
'data'
,
'keyboard_maps.tmpl'
)).
readAsStringSync
();
...
...
packages/flutter/lib/services.dart
View file @
c163ed96
...
...
@@ -24,6 +24,7 @@ export 'src/services/platform_views.dart';
export
'src/services/raw_keyboard.dart'
;
export
'src/services/raw_keyboard_android.dart'
;
export
'src/services/raw_keyboard_fuchsia.dart'
;
export
'src/services/raw_keyboard_macos.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 @
c163ed96
...
...
@@ -842,3 +842,150 @@ const Map<int, PhysicalKeyboardKey> kFuchsiaToPhysicalKey = <int, PhysicalKeyboa
0x000c028b
:
PhysicalKeyboardKey
.
mailForward
,
0x000c028c
:
PhysicalKeyboardKey
.
mailSend
,
};
/// Maps macOS-specific key code values representing [PhysicalKeyboardKey].
/// MacOS doesn't provide a scan code, but a virtual keycode to represent a physical key.
const
Map
<
int
,
PhysicalKeyboardKey
>
kMacOsToPhysicalKey
=
<
int
,
PhysicalKeyboardKey
>{
0x00000000
:
PhysicalKeyboardKey
.
keyA
,
0x0000000b
:
PhysicalKeyboardKey
.
keyB
,
0x00000008
:
PhysicalKeyboardKey
.
keyC
,
0x00000002
:
PhysicalKeyboardKey
.
keyD
,
0x0000000e
:
PhysicalKeyboardKey
.
keyE
,
0x00000003
:
PhysicalKeyboardKey
.
keyF
,
0x00000005
:
PhysicalKeyboardKey
.
keyG
,
0x00000004
:
PhysicalKeyboardKey
.
keyH
,
0x00000022
:
PhysicalKeyboardKey
.
keyI
,
0x00000026
:
PhysicalKeyboardKey
.
keyJ
,
0x00000028
:
PhysicalKeyboardKey
.
keyK
,
0x00000025
:
PhysicalKeyboardKey
.
keyL
,
0x0000002e
:
PhysicalKeyboardKey
.
keyM
,
0x0000002d
:
PhysicalKeyboardKey
.
keyN
,
0x0000001f
:
PhysicalKeyboardKey
.
keyO
,
0x00000023
:
PhysicalKeyboardKey
.
keyP
,
0x0000000c
:
PhysicalKeyboardKey
.
keyQ
,
0x0000000f
:
PhysicalKeyboardKey
.
keyR
,
0x00000001
:
PhysicalKeyboardKey
.
keyS
,
0x00000011
:
PhysicalKeyboardKey
.
keyT
,
0x00000020
:
PhysicalKeyboardKey
.
keyU
,
0x00000009
:
PhysicalKeyboardKey
.
keyV
,
0x0000000d
:
PhysicalKeyboardKey
.
keyW
,
0x00000007
:
PhysicalKeyboardKey
.
keyX
,
0x00000010
:
PhysicalKeyboardKey
.
keyY
,
0x00000006
:
PhysicalKeyboardKey
.
keyZ
,
0x00000012
:
PhysicalKeyboardKey
.
digit1
,
0x00000013
:
PhysicalKeyboardKey
.
digit2
,
0x00000014
:
PhysicalKeyboardKey
.
digit3
,
0x00000015
:
PhysicalKeyboardKey
.
digit4
,
0x00000017
:
PhysicalKeyboardKey
.
digit5
,
0x00000016
:
PhysicalKeyboardKey
.
digit6
,
0x0000001a
:
PhysicalKeyboardKey
.
digit7
,
0x0000001c
:
PhysicalKeyboardKey
.
digit8
,
0x00000019
:
PhysicalKeyboardKey
.
digit9
,
0x0000001d
:
PhysicalKeyboardKey
.
digit0
,
0x00000024
:
PhysicalKeyboardKey
.
enter
,
0x00000035
:
PhysicalKeyboardKey
.
escape
,
0x00000033
:
PhysicalKeyboardKey
.
backspace
,
0x00000030
:
PhysicalKeyboardKey
.
tab
,
0x00000031
:
PhysicalKeyboardKey
.
space
,
0x0000001b
:
PhysicalKeyboardKey
.
minus
,
0x00000018
:
PhysicalKeyboardKey
.
equal
,
0x00000021
:
PhysicalKeyboardKey
.
bracketLeft
,
0x0000001e
:
PhysicalKeyboardKey
.
bracketRight
,
0x0000002a
:
PhysicalKeyboardKey
.
backslash
,
0x00000029
:
PhysicalKeyboardKey
.
semicolon
,
0x00000027
:
PhysicalKeyboardKey
.
quote
,
0x00000032
:
PhysicalKeyboardKey
.
backquote
,
0x0000002b
:
PhysicalKeyboardKey
.
comma
,
0x0000002f
:
PhysicalKeyboardKey
.
period
,
0x0000002c
:
PhysicalKeyboardKey
.
slash
,
0x00000039
:
PhysicalKeyboardKey
.
capsLock
,
0x0000007a
:
PhysicalKeyboardKey
.
f1
,
0x00000078
:
PhysicalKeyboardKey
.
f2
,
0x00000063
:
PhysicalKeyboardKey
.
f3
,
0x00000076
:
PhysicalKeyboardKey
.
f4
,
0x00000060
:
PhysicalKeyboardKey
.
f5
,
0x00000061
:
PhysicalKeyboardKey
.
f6
,
0x00000062
:
PhysicalKeyboardKey
.
f7
,
0x00000064
:
PhysicalKeyboardKey
.
f8
,
0x00000065
:
PhysicalKeyboardKey
.
f9
,
0x0000006d
:
PhysicalKeyboardKey
.
f10
,
0x00000067
:
PhysicalKeyboardKey
.
f11
,
0x0000006f
:
PhysicalKeyboardKey
.
f12
,
0x00000072
:
PhysicalKeyboardKey
.
insert
,
0x00000073
:
PhysicalKeyboardKey
.
home
,
0x00000074
:
PhysicalKeyboardKey
.
pageUp
,
0x00000075
:
PhysicalKeyboardKey
.
delete
,
0x00000077
:
PhysicalKeyboardKey
.
end
,
0x00000079
:
PhysicalKeyboardKey
.
pageDown
,
0x0000007c
:
PhysicalKeyboardKey
.
arrowRight
,
0x0000007b
:
PhysicalKeyboardKey
.
arrowLeft
,
0x0000007d
:
PhysicalKeyboardKey
.
arrowDown
,
0x0000007e
:
PhysicalKeyboardKey
.
arrowUp
,
0x00000047
:
PhysicalKeyboardKey
.
numLock
,
0x0000004b
:
PhysicalKeyboardKey
.
numpadDivide
,
0x00000043
:
PhysicalKeyboardKey
.
numpadMultiply
,
0x0000004e
:
PhysicalKeyboardKey
.
numpadSubtract
,
0x00000045
:
PhysicalKeyboardKey
.
numpadAdd
,
0x0000004c
:
PhysicalKeyboardKey
.
numpadEnter
,
0x00000053
:
PhysicalKeyboardKey
.
numpad1
,
0x00000054
:
PhysicalKeyboardKey
.
numpad2
,
0x00000055
:
PhysicalKeyboardKey
.
numpad3
,
0x00000056
:
PhysicalKeyboardKey
.
numpad4
,
0x00000057
:
PhysicalKeyboardKey
.
numpad5
,
0x00000058
:
PhysicalKeyboardKey
.
numpad6
,
0x00000059
:
PhysicalKeyboardKey
.
numpad7
,
0x0000005b
:
PhysicalKeyboardKey
.
numpad8
,
0x0000005c
:
PhysicalKeyboardKey
.
numpad9
,
0x00000052
:
PhysicalKeyboardKey
.
numpad0
,
0x00000041
:
PhysicalKeyboardKey
.
numpadDecimal
,
0x0000000a
:
PhysicalKeyboardKey
.
intlBackslash
,
0x0000006e
:
PhysicalKeyboardKey
.
contextMenu
,
0x00000051
:
PhysicalKeyboardKey
.
numpadEqual
,
0x00000069
:
PhysicalKeyboardKey
.
f13
,
0x0000006b
:
PhysicalKeyboardKey
.
f14
,
0x00000071
:
PhysicalKeyboardKey
.
f15
,
0x0000006a
:
PhysicalKeyboardKey
.
f16
,
0x00000040
:
PhysicalKeyboardKey
.
f17
,
0x0000004f
:
PhysicalKeyboardKey
.
f18
,
0x00000050
:
PhysicalKeyboardKey
.
f19
,
0x0000005a
:
PhysicalKeyboardKey
.
f20
,
0x0000004a
:
PhysicalKeyboardKey
.
audioVolumeMute
,
0x00000048
:
PhysicalKeyboardKey
.
audioVolumeUp
,
0x00000049
:
PhysicalKeyboardKey
.
audioVolumeDown
,
0x0000005f
:
PhysicalKeyboardKey
.
numpadComma
,
0x0000005e
:
PhysicalKeyboardKey
.
intlRo
,
0x00000068
:
PhysicalKeyboardKey
.
kanaMode
,
0x0000005d
:
PhysicalKeyboardKey
.
intlYen
,
0x0000003b
:
PhysicalKeyboardKey
.
controlLeft
,
0x00000038
:
PhysicalKeyboardKey
.
shiftLeft
,
0x0000003a
:
PhysicalKeyboardKey
.
altLeft
,
0x00000037
:
PhysicalKeyboardKey
.
metaLeft
,
0x0000003e
:
PhysicalKeyboardKey
.
controlRight
,
0x0000003c
:
PhysicalKeyboardKey
.
shiftRight
,
0x0000003d
:
PhysicalKeyboardKey
.
altRight
,
0x00000036
:
PhysicalKeyboardKey
.
metaRight
,
};
/// A map of macOS key 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
>
kMacOsNumPadMap
=
<
int
,
LogicalKeyboardKey
>{
0x0000004b
:
LogicalKeyboardKey
.
numpadDivide
,
0x00000043
:
LogicalKeyboardKey
.
numpadMultiply
,
0x0000004e
:
LogicalKeyboardKey
.
numpadSubtract
,
0x00000045
:
LogicalKeyboardKey
.
numpadAdd
,
0x00000053
:
LogicalKeyboardKey
.
numpad1
,
0x00000054
:
LogicalKeyboardKey
.
numpad2
,
0x00000055
:
LogicalKeyboardKey
.
numpad3
,
0x00000056
:
LogicalKeyboardKey
.
numpad4
,
0x00000057
:
LogicalKeyboardKey
.
numpad5
,
0x00000058
:
LogicalKeyboardKey
.
numpad6
,
0x00000059
:
LogicalKeyboardKey
.
numpad7
,
0x0000005b
:
LogicalKeyboardKey
.
numpad8
,
0x0000005c
:
LogicalKeyboardKey
.
numpad9
,
0x00000052
:
LogicalKeyboardKey
.
numpad0
,
0x00000041
:
LogicalKeyboardKey
.
numpadDecimal
,
0x00000051
:
LogicalKeyboardKey
.
numpadEqual
,
0x0000005f
:
LogicalKeyboardKey
.
numpadComma
,
};
packages/flutter/lib/src/services/raw_keyboard.dart
View file @
c163ed96
...
...
@@ -9,6 +9,7 @@ import 'package:flutter/foundation.dart';
import
'keyboard_key.dart'
;
import
'raw_keyboard_android.dart'
;
import
'raw_keyboard_fuchsia.dart'
;
import
'raw_keyboard_macos.dart'
;
import
'system_channels.dart'
;
/// An enum describing the side of the keyboard that a key is on, to allow
...
...
@@ -263,6 +264,14 @@ abstract class RawKeyEvent {
modifiers:
message
[
'modifiers'
]
??
0
,
);
break
;
case
'macos'
:
data
=
RawKeyEventDataMacOs
(
characters:
message
[
'characters'
]
??
''
,
charactersIgnoringModifiers:
message
[
'charactersIgnoringModifiers'
]
??
''
,
keyCode:
message
[
'keyCode'
]
??
0
,
modifiers:
message
[
'modifiers'
]
??
0
);
break
;
default
:
// We don't yet implement raw key events on iOS or other platforms, but
// we don't hit this exception because the engine never sends us these
...
...
packages/flutter/lib/src/services/raw_keyboard_macos.dart
0 → 100644
View file @
c163ed96
// Copyright 2019 The Chromium 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 macOS.
///
/// This object contains information about key events obtained from macOS's
/// `NSEvent` interface.
///
/// See also:
///
/// * [RawKeyboard], which uses this interface to expose key data.
class
RawKeyEventDataMacOs
extends
RawKeyEventData
{
/// Creates a key event data structure specific for macOS.
///
/// The [characters], [charactersIgnoringModifiers], and [modifiers], arguments
/// must not be null.
const
RawKeyEventDataMacOs
({
this
.
characters
=
''
,
this
.
charactersIgnoringModifiers
=
''
,
this
.
keyCode
=
0
,
this
.
modifiers
=
0
,
})
:
assert
(
characters
!=
null
),
assert
(
charactersIgnoringModifiers
!=
null
),
assert
(
keyCode
!=
null
),
assert
(
modifiers
!=
null
);
/// The Unicode characters associated with a key-up or key-down event.
///
/// See also:
///
/// * [Apple's NSEvent documentation](https://developer.apple.com/documentation/appkit/nsevent/1534183-characters?language=objc)
final
String
characters
;
/// The characters generated by a key event as if no modifier key (except for
/// Shift) applies.
///
/// See also:
///
/// * [Apple's NSEvent documentation](https://developer.apple.com/documentation/appkit/nsevent/1524605-charactersignoringmodifiers?language=objc)
final
String
charactersIgnoringModifiers
;
/// The virtual key code for the keyboard key associated with a key event.
///
/// See also:
///
/// * [Apple's NSEvent documentation](https://developer.apple.com/documentation/appkit/nsevent/1534513-keycode?language=objc)
final
int
keyCode
;
/// A mask of the current modifiers using the values in Modifier Flags.
///
/// See also:
///
/// * [Apple's NSEvent documentation](https://developer.apple.com/documentation/appkit/nsevent/1535211-modifierflags?language=objc)
final
int
modifiers
;
@override
String
get
keyLabel
=>
charactersIgnoringModifiers
.
isEmpty
?
null
:
charactersIgnoringModifiers
;
@override
PhysicalKeyboardKey
get
physicalKey
=>
kMacOsToPhysicalKey
[
keyCode
]
??
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
=
kMacOsNumPadMap
[
keyCode
];
if
(
numPadKey
!=
null
)
{
return
numPadKey
;
}
// Look to see if the keyCode is one we know about and have a mapping for.
if
(
keyLabel
!=
null
&&
!
LogicalKeyboardKey
.
isControlCharacter
(
keyLabel
))
{
assert
(
charactersIgnoringModifiers
.
length
<=
2
);
int
codeUnit
=
charactersIgnoringModifiers
.
codeUnitAt
(
0
);
if
(
charactersIgnoringModifiers
.
length
==
2
)
{
// Not covering length > 2 case since > 1 is already unlikely.
final
int
secondCode
=
charactersIgnoringModifiers
.
codeUnitAt
(
1
);
codeUnit
=
(
codeUnit
<<
16
)
|
secondCode
;
}
final
int
keyId
=
LogicalKeyboardKey
.
unicodePlane
|
(
codeUnit
&
LogicalKeyboardKey
.
valueMask
);
return
LogicalKeyboardKey
.
findKeyByKeyId
(
keyId
)
??
LogicalKeyboardKey
(
keyId
,
keyLabel:
keyLabel
,
debugName:
kReleaseMode
?
null
:
'Key
${keyLabel.toUpperCase()}
'
,
);
}
// 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
macOsKeyIdPlane
=
0x00500000000
;
// Keys like "backspace" won't have a character, but it's known by the physical keyboard.
// Since there is no logical keycode map for macOS (macOS uses the keycode to reference
// physical keys), a LogicalKeyboardKey is created with the physical key's HID usage and
// debugName. This avoids the need for duplicating the physical key map.
if
(
physicalKey
!=
PhysicalKeyboardKey
.
none
)
{
final
int
keyId
=
physicalKey
.
usbHidUsage
|
LogicalKeyboardKey
.
hidPlane
;
return
LogicalKeyboardKey
.
findKeyByKeyId
(
keyId
)
??
LogicalKeyboardKey
(
keyId
,
keyLabel:
physicalKey
.
debugName
,
debugName:
physicalKey
.
debugName
,
);
}
return
LogicalKeyboardKey
(
macOsKeyIdPlane
|
keyCode
|
LogicalKeyboardKey
.
autogeneratedMask
,
debugName:
kReleaseMode
?
null
:
'Unknown macOS key code
$keyCode
'
,
);
}
bool
_isLeftRightModifierPressed
(
KeyboardSide
side
,
int
anyMask
,
int
leftMask
,
int
rightMask
)
{
if
(
modifiers
&
anyMask
==
0
)
{
return
false
;
}
switch
(
side
)
{
case
KeyboardSide
.
any
:
return
true
;
case
KeyboardSide
.
all
:
return
modifiers
&
leftMask
!=
0
&&
modifiers
&
rightMask
!=
0
;
case
KeyboardSide
.
left
:
return
modifiers
&
leftMask
!=
0
;
case
KeyboardSide
.
right
:
return
modifiers
&
rightMask
!=
0
;
}
return
false
;
}
@override
bool
isModifierPressed
(
ModifierKey
key
,
{
KeyboardSide
side
=
KeyboardSide
.
any
})
{
final
int
independentModifier
=
modifiers
&
deviceIndependentMask
;
switch
(
key
)
{
case
ModifierKey
.
controlModifier
:
return
_isLeftRightModifierPressed
(
side
,
independentModifier
&
modifierControl
,
modifierLeftControl
,
modifierRightControl
);
case
ModifierKey
.
shiftModifier
:
return
_isLeftRightModifierPressed
(
side
,
independentModifier
&
modifierShift
,
modifierLeftShift
,
modifierRightShift
);
case
ModifierKey
.
altModifier
:
return
_isLeftRightModifierPressed
(
side
,
independentModifier
&
modifierOption
,
modifierLeftOption
,
modifierRightOption
);
case
ModifierKey
.
metaModifier
:
return
_isLeftRightModifierPressed
(
side
,
independentModifier
&
modifierCommand
,
modifierLeftCommand
,
modifierRightCommand
);
case
ModifierKey
.
capsLockModifier
:
return
independentModifier
&
modifierCapsLock
!=
0
;
case
ModifierKey
.
numLockModifier
:
return
independentModifier
&
modifierNumericPad
!=
0
;
case
ModifierKey
.
functionModifier
:
return
independentModifier
&
modifierFunction
!=
0
;
case
ModifierKey
.
symbolModifier
:
case
ModifierKey
.
scrollLockModifier
:
// These are not used in macOS keyboards.
return
false
;
}
return
false
;
}
@override
KeyboardSide
getModifierSide
(
ModifierKey
key
)
{
KeyboardSide
findSide
(
int
leftMask
,
int
rightMask
)
{
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
;
}
return
null
;
}
switch
(
key
)
{
case
ModifierKey
.
controlModifier
:
return
findSide
(
modifierLeftControl
,
modifierRightControl
);
case
ModifierKey
.
shiftModifier
:
return
findSide
(
modifierLeftShift
,
modifierRightShift
);
case
ModifierKey
.
altModifier
:
return
findSide
(
modifierLeftOption
,
modifierRightOption
);
case
ModifierKey
.
metaModifier
:
return
findSide
(
modifierLeftCommand
,
modifierRightCommand
);
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
;
}
// Modifier key masks. See Apple's NSEvent documentation
// https://developer.apple.com/documentation/appkit/nseventmodifierflags?language=objc
// https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-86/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h.auto.html
/// This mask is used to check the [modifiers] field to test whether the CAPS
/// LOCK modifier key is on.
///
/// {@template flutter.services.logicalKeyboardKey.modifiers}
/// Use this value if you need to decode the [modifiers] field yourself, but
/// it's much easier to use [isModifierPressed] if you just want to know if
/// a modifier is pressed.
/// {@endtemplate}
static
const
int
modifierCapsLock
=
0x10000
;
/// This mask is used to check the [modifiers] field to test whether one of the
/// SHIFT modifier keys is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierShift
=
0x20000
;
/// This mask is used to check the [modifiers] field to test whether the left
/// SHIFT modifier key is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierLeftShift
=
0x02
;
/// This mask is used to check the [modifiers] field to test whether the right
/// SHIFT modifier key is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierRightShift
=
0x04
;
/// This mask is used to check the [modifiers] field to test whether one of the
/// CTRL modifier keys is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierControl
=
0x40000
;
/// This mask is used to check the [modifiers] field to test whether the left
/// CTRL modifier key is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierLeftControl
=
0x01
;
/// This mask is used to check the [modifiers] field to test whether the right
/// CTRL modifier key is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierRightControl
=
0x2000
;
/// This mask is used to check the [modifiers] field to test whether one of the
/// ALT modifier keys is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierOption
=
0x80000
;
/// This mask is used to check the [modifiers] field to test whether the left
/// ALT modifier key is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierLeftOption
=
0x20
;
/// This mask is used to check the [modifiers] field to test whether the right
/// ALT modifier key is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierRightOption
=
0x40
;
/// This mask is used to check the [modifiers] field to test whether one of the
/// CMD modifier keys is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierCommand
=
0x100000
;
/// This mask is used to check the [modifiers] field to test whether the left
/// CMD modifier keys is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierLeftCommand
=
0x08
;
/// This mask is used to check the [modifiers] field to test whether the right
/// CMD modifier keys is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierRightCommand
=
0x10
;
/// This mask is used to check the [modifiers] field to test whether any key in
/// the numeric keypad is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierNumericPad
=
0x200000
;
/// This mask is used to check the [modifiers] field to test whether the
/// HELP modifier key is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierHelp
=
0x400000
;
/// This mask is used to check the [modifiers] field to test whether one of the
/// FUNCTION modifier keys is pressed.
///
/// {@macro flutter.services.logicalKeyboardKey.modifiers}
static
const
int
modifierFunction
=
0x800000
;
/// Used to retrieve only the device-independent modifier flags, allowing
/// applications to mask off the device-dependent modifier flags, including
/// event coalescing information.
static
const
int
deviceIndependentMask
=
0xffff0000
;
@override
String
toString
()
{
return
'
$runtimeType
(keyLabel:
$keyLabel
, keyCode:
$keyCode
, characters:
$characters
,'
' unmodifiedCharacters:
$charactersIgnoringModifiers
, modifiers:
$modifiers
, '
'modifiers down:
$modifiersPressed
)'
;
}
}
packages/flutter/test/services/raw_keyboard_test.dart
View file @
c163ed96
...
...
@@ -264,4 +264,133 @@ void main() {
expect
(
data
.
keyLabel
,
isNull
);
});
});
group
(
'RawKeyEventDataMacOs'
,
()
{
const
Map
<
int
,
_ModifierCheck
>
modifierTests
=
<
int
,
_ModifierCheck
>{
RawKeyEventDataMacOs
.
modifierOption
|
RawKeyEventDataMacOs
.
modifierLeftOption
:
_ModifierCheck
(
ModifierKey
.
altModifier
,
KeyboardSide
.
left
),
RawKeyEventDataMacOs
.
modifierOption
|
RawKeyEventDataMacOs
.
modifierRightOption
:
_ModifierCheck
(
ModifierKey
.
altModifier
,
KeyboardSide
.
right
),
RawKeyEventDataMacOs
.
modifierShift
|
RawKeyEventDataMacOs
.
modifierLeftShift
:
_ModifierCheck
(
ModifierKey
.
shiftModifier
,
KeyboardSide
.
left
),
RawKeyEventDataMacOs
.
modifierShift
|
RawKeyEventDataMacOs
.
modifierRightShift
:
_ModifierCheck
(
ModifierKey
.
shiftModifier
,
KeyboardSide
.
right
),
RawKeyEventDataMacOs
.
modifierFunction
:
_ModifierCheck
(
ModifierKey
.
functionModifier
,
KeyboardSide
.
all
),
RawKeyEventDataMacOs
.
modifierControl
|
RawKeyEventDataMacOs
.
modifierLeftControl
:
_ModifierCheck
(
ModifierKey
.
controlModifier
,
KeyboardSide
.
left
),
RawKeyEventDataMacOs
.
modifierControl
|
RawKeyEventDataMacOs
.
modifierRightControl
:
_ModifierCheck
(
ModifierKey
.
controlModifier
,
KeyboardSide
.
right
),
RawKeyEventDataMacOs
.
modifierCommand
|
RawKeyEventDataMacOs
.
modifierLeftCommand
:
_ModifierCheck
(
ModifierKey
.
metaModifier
,
KeyboardSide
.
left
),
RawKeyEventDataMacOs
.
modifierCommand
|
RawKeyEventDataMacOs
.
modifierRightCommand
:
_ModifierCheck
(
ModifierKey
.
metaModifier
,
KeyboardSide
.
right
),
RawKeyEventDataMacOs
.
modifierCapsLock
:
_ModifierCheck
(
ModifierKey
.
capsLockModifier
,
KeyboardSide
.
all
),
};
test
(
'modifier keys are recognized individually'
,
()
{
for
(
int
modifier
in
modifierTests
.
keys
)
{
final
RawKeyEvent
event
=
RawKeyEvent
.
fromMessage
(<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'macos'
,
'keyCode'
:
0x04
,
'characters'
:
'a'
,
'charactersIgnoringModifiers'
:
'a'
,
'modifiers'
:
modifier
,
});
final
RawKeyEventDataMacOs
data
=
event
.
data
;
for
(
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 metaState
$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
(
int
modifier
in
modifierTests
.
keys
)
{
if
(
modifier
==
RawKeyEventDataMacOs
.
modifierFunction
)
{
// No need to combine function key with itself.
continue
;
}
final
RawKeyEvent
event
=
RawKeyEvent
.
fromMessage
(<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'macos'
,
'keyCode'
:
0x04
,
'plainCodePoint'
:
0x64
,
'characters'
:
'a'
,
'charactersIgnoringModifiers'
:
'a'
,
'modifiers'
:
modifier
|
RawKeyEventDataMacOs
.
modifierFunction
,
});
final
RawKeyEventDataMacOs
data
=
event
.
data
;
for
(
ModifierKey
key
in
ModifierKey
.
values
)
{
if
(
modifierTests
[
modifier
].
key
==
key
||
key
==
ModifierKey
.
functionModifier
)
{
expect
(
data
.
isModifierPressed
(
key
,
side:
modifierTests
[
modifier
].
side
),
isTrue
,
reason:
'
$key
should be pressed with metaState
$modifier
'
"and additional key
${RawKeyEventDataMacOs.modifierFunction}
, but isn't."
,
);
if
(
key
!=
ModifierKey
.
functionModifier
)
{
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
with metaState
$modifier
'
'and additional key
${RawKeyEventDataMacOs.modifierFunction}
.'
,
);
}
}
}
});
test
(
'Printable keyboard keys are correctly translated'
,
()
{
const
String
unmodifiedCharacter
=
'a'
;
final
RawKeyEvent
keyAEvent
=
RawKeyEvent
.
fromMessage
(
const
<
String
,
dynamic
>{
'type'
:
'keydown'
,
'keymap'
:
'macos'
,
'keyCode'
:
0x00000000
,
'characters'
:
'a'
,
'charactersIgnoringModifiers'
:
unmodifiedCharacter
,
'modifiers'
:
0x0
,
});
final
RawKeyEventDataMacOs
data
=
keyAEvent
.
data
;
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'
:
'macos'
,
'keyCode'
:
0x00000035
,
'characters'
:
''
,
'charactersIgnoringModifiers'
:
''
,
'character'
:
null
,
'modifiers'
:
0x0
,
});
final
RawKeyEventDataMacOs
data
=
escapeKeyEvent
.
data
;
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'
:
'macos'
,
'keyCode'
:
0x00000038
,
'characters'
:
''
,
'charactersIgnoringModifiers'
:
''
,
'character'
:
null
,
'modifiers'
:
RawKeyEventDataMacOs
.
modifierLeftShift
,
});
final
RawKeyEventDataMacOs
data
=
shiftLeftKeyEvent
.
data
;
expect
(
data
.
physicalKey
,
equals
(
PhysicalKeyboardKey
.
shiftLeft
));
expect
(
data
.
logicalKey
,
equals
(
LogicalKeyboardKey
.
shiftLeft
));
expect
(
data
.
keyLabel
,
isNull
);
});
});
}
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