Unverified Commit a0f7f6ca authored by Francisco Magdaleno's avatar Francisco Magdaleno Committed by GitHub

[windows] Adds support for keyboard mapping. (#54227)

parent 45bf8380
......@@ -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}'));
......
......@@ -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 keyCodeMapUri = 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 keyCodesUri = 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.
......
......@@ -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
......@@ -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"],
......
......@@ -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();
}
......
......@@ -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@@@
};
......@@ -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();
......
......@@ -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';
......
......@@ -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
......
This diff is collapsed.
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment