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';
......
......@@ -2020,3 +2020,306 @@ const Map<String, LogicalKeyboardKey> kWebNumPadMap = <String, LogicalKeyboardKe
'NumpadParenLeft': LogicalKeyboardKey.numpadParenLeft,
'NumpadParenRight': LogicalKeyboardKey.numpadParenRight,
};
/// Maps Windows KeyboardEvent codes to the matching [LogicalKeyboardKey].
const Map<int, LogicalKeyboardKey> kWindowsToLogicalKey = <int, LogicalKeyboardKey>{
95: LogicalKeyboardKey.sleep,
65: LogicalKeyboardKey.keyA,
66: LogicalKeyboardKey.keyB,
67: LogicalKeyboardKey.keyC,
68: LogicalKeyboardKey.keyD,
69: LogicalKeyboardKey.keyE,
70: LogicalKeyboardKey.keyF,
71: LogicalKeyboardKey.keyG,
72: LogicalKeyboardKey.keyH,
73: LogicalKeyboardKey.keyI,
74: LogicalKeyboardKey.keyJ,
75: LogicalKeyboardKey.keyK,
76: LogicalKeyboardKey.keyL,
77: LogicalKeyboardKey.keyM,
78: LogicalKeyboardKey.keyN,
79: LogicalKeyboardKey.keyO,
80: LogicalKeyboardKey.keyP,
81: LogicalKeyboardKey.keyQ,
82: LogicalKeyboardKey.keyR,
83: LogicalKeyboardKey.keyS,
84: LogicalKeyboardKey.keyT,
85: LogicalKeyboardKey.keyU,
86: LogicalKeyboardKey.keyV,
87: LogicalKeyboardKey.keyW,
88: LogicalKeyboardKey.keyX,
89: LogicalKeyboardKey.keyY,
90: LogicalKeyboardKey.keyZ,
13: LogicalKeyboardKey.enter,
27: LogicalKeyboardKey.escape,
8: LogicalKeyboardKey.backspace,
9: LogicalKeyboardKey.tab,
32: LogicalKeyboardKey.space,
189: LogicalKeyboardKey.minus,
187: LogicalKeyboardKey.equal,
219: LogicalKeyboardKey.bracketLeft,
221: LogicalKeyboardKey.bracketRight,
220: LogicalKeyboardKey.backslash,
186: LogicalKeyboardKey.semicolon,
222: LogicalKeyboardKey.quote,
188: LogicalKeyboardKey.comma,
190: LogicalKeyboardKey.period,
191: LogicalKeyboardKey.slash,
20: LogicalKeyboardKey.capsLock,
112: LogicalKeyboardKey.f1,
113: LogicalKeyboardKey.f2,
114: LogicalKeyboardKey.f3,
115: LogicalKeyboardKey.f4,
116: LogicalKeyboardKey.f5,
117: LogicalKeyboardKey.f6,
118: LogicalKeyboardKey.f7,
119: LogicalKeyboardKey.f8,
120: LogicalKeyboardKey.f9,
121: LogicalKeyboardKey.f10,
122: LogicalKeyboardKey.f11,
123: LogicalKeyboardKey.f12,
19: LogicalKeyboardKey.pause,
45: LogicalKeyboardKey.insert,
36: LogicalKeyboardKey.home,
46: LogicalKeyboardKey.delete,
35: LogicalKeyboardKey.end,
39: LogicalKeyboardKey.arrowRight,
37: LogicalKeyboardKey.arrowLeft,
40: LogicalKeyboardKey.arrowDown,
38: LogicalKeyboardKey.arrowUp,
111: LogicalKeyboardKey.numpadDivide,
106: LogicalKeyboardKey.numpadMultiply,
109: LogicalKeyboardKey.numpadSubtract,
107: LogicalKeyboardKey.numpadAdd,
97: LogicalKeyboardKey.numpad1,
98: LogicalKeyboardKey.numpad2,
99: LogicalKeyboardKey.numpad3,
100: LogicalKeyboardKey.numpad4,
101: LogicalKeyboardKey.numpad5,
102: LogicalKeyboardKey.numpad6,
103: LogicalKeyboardKey.numpad7,
104: LogicalKeyboardKey.numpad8,
105: LogicalKeyboardKey.numpad9,
96: LogicalKeyboardKey.numpad0,
110: LogicalKeyboardKey.numpadDecimal,
146: LogicalKeyboardKey.numpadEqual,
124: LogicalKeyboardKey.f13,
125: LogicalKeyboardKey.f14,
126: LogicalKeyboardKey.f15,
127: LogicalKeyboardKey.f16,
128: LogicalKeyboardKey.f17,
129: LogicalKeyboardKey.f18,
130: LogicalKeyboardKey.f19,
131: LogicalKeyboardKey.f20,
132: LogicalKeyboardKey.f21,
133: LogicalKeyboardKey.f22,
134: LogicalKeyboardKey.f23,
135: LogicalKeyboardKey.f24,
47: LogicalKeyboardKey.help,
41: LogicalKeyboardKey.select,
28: LogicalKeyboardKey.convert,
162: LogicalKeyboardKey.controlLeft,
160: LogicalKeyboardKey.shiftLeft,
164: LogicalKeyboardKey.altLeft,
91: LogicalKeyboardKey.metaLeft,
163: LogicalKeyboardKey.controlRight,
161: LogicalKeyboardKey.shiftRight,
165: LogicalKeyboardKey.altRight,
92: LogicalKeyboardKey.metaRight,
178: LogicalKeyboardKey.mediaStop,
179: LogicalKeyboardKey.mediaPlayPause,
180: LogicalKeyboardKey.launchMail,
183: LogicalKeyboardKey.launchApp2,
182: LogicalKeyboardKey.launchApp1,
42: LogicalKeyboardKey.print,
170: LogicalKeyboardKey.browserSearch,
172: LogicalKeyboardKey.browserHome,
166: LogicalKeyboardKey.browserBack,
167: LogicalKeyboardKey.browserForward,
169: LogicalKeyboardKey.browserStop,
168: LogicalKeyboardKey.browserRefresh,
171: LogicalKeyboardKey.browserFavorites,
};
/// Maps Windows KeyboardEvent codes to the matching [PhysicalKeyboardKey].
const Map<int, PhysicalKeyboardKey> kWindowsToPhysicalKey = <int, PhysicalKeyboardKey>{
0x0000e05f: PhysicalKeyboardKey.sleep,
0x0000e063: PhysicalKeyboardKey.wakeUp,
0x000000ff: PhysicalKeyboardKey.usbErrorRollOver,
0x000000fc: PhysicalKeyboardKey.usbPostFail,
0x0000001e: PhysicalKeyboardKey.keyA,
0x00000030: PhysicalKeyboardKey.keyB,
0x0000002e: PhysicalKeyboardKey.keyC,
0x00000020: PhysicalKeyboardKey.keyD,
0x00000012: PhysicalKeyboardKey.keyE,
0x00000021: PhysicalKeyboardKey.keyF,
0x00000022: PhysicalKeyboardKey.keyG,
0x00000023: PhysicalKeyboardKey.keyH,
0x00000017: PhysicalKeyboardKey.keyI,
0x00000024: PhysicalKeyboardKey.keyJ,
0x00000025: PhysicalKeyboardKey.keyK,
0x00000026: PhysicalKeyboardKey.keyL,
0x00000032: PhysicalKeyboardKey.keyM,
0x00000031: PhysicalKeyboardKey.keyN,
0x00000018: PhysicalKeyboardKey.keyO,
0x00000019: PhysicalKeyboardKey.keyP,
0x00000010: PhysicalKeyboardKey.keyQ,
0x00000013: PhysicalKeyboardKey.keyR,
0x0000001f: PhysicalKeyboardKey.keyS,
0x00000014: PhysicalKeyboardKey.keyT,
0x00000016: PhysicalKeyboardKey.keyU,
0x0000002f: PhysicalKeyboardKey.keyV,
0x00000011: PhysicalKeyboardKey.keyW,
0x0000002d: PhysicalKeyboardKey.keyX,
0x00000015: PhysicalKeyboardKey.keyY,
0x0000002c: PhysicalKeyboardKey.keyZ,
0x00000002: PhysicalKeyboardKey.digit1,
0x00000003: PhysicalKeyboardKey.digit2,
0x00000004: PhysicalKeyboardKey.digit3,
0x00000005: PhysicalKeyboardKey.digit4,
0x00000006: PhysicalKeyboardKey.digit5,
0x00000007: PhysicalKeyboardKey.digit6,
0x00000008: PhysicalKeyboardKey.digit7,
0x00000009: PhysicalKeyboardKey.digit8,
0x0000000a: PhysicalKeyboardKey.digit9,
0x0000000b: PhysicalKeyboardKey.digit0,
0x0000001c: PhysicalKeyboardKey.enter,
0x00000001: PhysicalKeyboardKey.escape,
0x0000000e: PhysicalKeyboardKey.backspace,
0x0000000f: PhysicalKeyboardKey.tab,
0x00000039: PhysicalKeyboardKey.space,
0x0000000c: PhysicalKeyboardKey.minus,
0x0000000d: PhysicalKeyboardKey.equal,
0x0000001a: PhysicalKeyboardKey.bracketLeft,
0x0000001b: PhysicalKeyboardKey.bracketRight,
0x0000002b: PhysicalKeyboardKey.backslash,
0x00000027: PhysicalKeyboardKey.semicolon,
0x00000028: PhysicalKeyboardKey.quote,
0x00000029: PhysicalKeyboardKey.backquote,
0x00000033: PhysicalKeyboardKey.comma,
0x00000034: PhysicalKeyboardKey.period,
0x00000035: PhysicalKeyboardKey.slash,
0x0000003a: PhysicalKeyboardKey.capsLock,
0x0000003b: PhysicalKeyboardKey.f1,
0x0000003c: PhysicalKeyboardKey.f2,
0x0000003d: PhysicalKeyboardKey.f3,
0x0000003e: PhysicalKeyboardKey.f4,
0x0000003f: PhysicalKeyboardKey.f5,
0x00000040: PhysicalKeyboardKey.f6,
0x00000041: PhysicalKeyboardKey.f7,
0x00000042: PhysicalKeyboardKey.f8,
0x00000043: PhysicalKeyboardKey.f9,
0x00000044: PhysicalKeyboardKey.f10,
0x00000057: PhysicalKeyboardKey.f11,
0x00000058: PhysicalKeyboardKey.f12,
0x0000e037: PhysicalKeyboardKey.printScreen,
0x00000046: PhysicalKeyboardKey.scrollLock,
0x00000045: PhysicalKeyboardKey.pause,
0x0000e052: PhysicalKeyboardKey.insert,
0x0000e047: PhysicalKeyboardKey.home,
0x0000e049: PhysicalKeyboardKey.pageUp,
0x0000e053: PhysicalKeyboardKey.delete,
0x0000e04f: PhysicalKeyboardKey.end,
0x0000e051: PhysicalKeyboardKey.pageDown,
0x0000e04d: PhysicalKeyboardKey.arrowRight,
0x0000e04b: PhysicalKeyboardKey.arrowLeft,
0x0000e050: PhysicalKeyboardKey.arrowDown,
0x0000e048: PhysicalKeyboardKey.arrowUp,
0x0000e045: PhysicalKeyboardKey.numLock,
0x0000e035: PhysicalKeyboardKey.numpadDivide,
0x00000037: PhysicalKeyboardKey.numpadMultiply,
0x0000004a: PhysicalKeyboardKey.numpadSubtract,
0x0000004e: PhysicalKeyboardKey.numpadAdd,
0x0000e01c: PhysicalKeyboardKey.numpadEnter,
0x0000004f: PhysicalKeyboardKey.numpad1,
0x00000050: PhysicalKeyboardKey.numpad2,
0x00000051: PhysicalKeyboardKey.numpad3,
0x0000004b: PhysicalKeyboardKey.numpad4,
0x0000004c: PhysicalKeyboardKey.numpad5,
0x0000004d: PhysicalKeyboardKey.numpad6,
0x00000047: PhysicalKeyboardKey.numpad7,
0x00000048: PhysicalKeyboardKey.numpad8,
0x00000049: PhysicalKeyboardKey.numpad9,
0x00000052: PhysicalKeyboardKey.numpad0,
0x00000053: PhysicalKeyboardKey.numpadDecimal,
0x00000056: PhysicalKeyboardKey.intlBackslash,
0x0000e05d: PhysicalKeyboardKey.contextMenu,
0x0000e05e: PhysicalKeyboardKey.power,
0x00000059: PhysicalKeyboardKey.numpadEqual,
0x00000064: PhysicalKeyboardKey.f13,
0x00000065: PhysicalKeyboardKey.f14,
0x00000066: PhysicalKeyboardKey.f15,
0x00000067: PhysicalKeyboardKey.f16,
0x00000068: PhysicalKeyboardKey.f17,
0x00000069: PhysicalKeyboardKey.f18,
0x0000006a: PhysicalKeyboardKey.f19,
0x0000006b: PhysicalKeyboardKey.f20,
0x0000006c: PhysicalKeyboardKey.f21,
0x0000006d: PhysicalKeyboardKey.f22,
0x0000006e: PhysicalKeyboardKey.f23,
0x00000076: PhysicalKeyboardKey.f24,
0x0000e03b: PhysicalKeyboardKey.help,
0x0000e008: PhysicalKeyboardKey.undo,
0x0000e017: PhysicalKeyboardKey.cut,
0x0000e018: PhysicalKeyboardKey.copy,
0x0000e00a: PhysicalKeyboardKey.paste,
0x0000e020: PhysicalKeyboardKey.audioVolumeMute,
0x0000e030: PhysicalKeyboardKey.audioVolumeUp,
0x0000e02e: PhysicalKeyboardKey.audioVolumeDown,
0x0000007e: PhysicalKeyboardKey.numpadComma,
0x00000073: PhysicalKeyboardKey.intlRo,
0x00000070: PhysicalKeyboardKey.kanaMode,
0x0000007d: PhysicalKeyboardKey.intlYen,
0x00000079: PhysicalKeyboardKey.convert,
0x0000007b: PhysicalKeyboardKey.nonConvert,
0x00000072: PhysicalKeyboardKey.lang1,
0x00000071: PhysicalKeyboardKey.lang2,
0x00000078: PhysicalKeyboardKey.lang3,
0x00000077: PhysicalKeyboardKey.lang4,
0x0000001d: PhysicalKeyboardKey.controlLeft,
0x0000002a: PhysicalKeyboardKey.shiftLeft,
0x00000038: PhysicalKeyboardKey.altLeft,
0x0000e05b: PhysicalKeyboardKey.metaLeft,
0x0000e01d: PhysicalKeyboardKey.controlRight,
0x00000036: PhysicalKeyboardKey.shiftRight,
0x0000e038: PhysicalKeyboardKey.altRight,
0x0000e05c: PhysicalKeyboardKey.metaRight,
0x0000e019: PhysicalKeyboardKey.mediaTrackNext,
0x0000e010: PhysicalKeyboardKey.mediaTrackPrevious,
0x0000e024: PhysicalKeyboardKey.mediaStop,
0x0000e02c: PhysicalKeyboardKey.eject,
0x0000e022: PhysicalKeyboardKey.mediaPlayPause,
0x0000e06d: PhysicalKeyboardKey.mediaSelect,
0x0000e06c: PhysicalKeyboardKey.launchMail,
0x0000e021: PhysicalKeyboardKey.launchApp2,
0x0000e06b: PhysicalKeyboardKey.launchApp1,
0x0000e065: PhysicalKeyboardKey.browserSearch,
0x0000e032: PhysicalKeyboardKey.browserHome,
0x0000e06a: PhysicalKeyboardKey.browserBack,
0x0000e069: PhysicalKeyboardKey.browserForward,
0x0000e068: PhysicalKeyboardKey.browserStop,
0x0000e067: PhysicalKeyboardKey.browserRefresh,
0x0000e066: PhysicalKeyboardKey.browserFavorites,
};
/// 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>{
111: LogicalKeyboardKey.numpadDivide,
106: LogicalKeyboardKey.numpadMultiply,
109: LogicalKeyboardKey.numpadSubtract,
107: LogicalKeyboardKey.numpadAdd,
97: LogicalKeyboardKey.numpad1,
98: LogicalKeyboardKey.numpad2,
99: LogicalKeyboardKey.numpad3,
100: LogicalKeyboardKey.numpad4,
101: LogicalKeyboardKey.numpad5,
102: LogicalKeyboardKey.numpad6,
103: LogicalKeyboardKey.numpad7,
104: LogicalKeyboardKey.numpad8,
105: LogicalKeyboardKey.numpad9,
96: LogicalKeyboardKey.numpad0,
110: LogicalKeyboardKey.numpadDecimal,
146: LogicalKeyboardKey.numpadEqual,
};
......@@ -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
......
// Copyright 2014 The Flutter 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 Windows.
///
/// This object contains information about key events obtained from Windows's
/// win32 API.
///
/// See also:
///
/// * [RawKeyboard], which uses this interface to expose key data.
class RawKeyEventDataWindows extends RawKeyEventData {
/// Creates a key event data structure specific for Windows.
///
/// The [keyCode], [scanCode], [characterCodePoint], and [modifiers], arguments
/// must not be null.
const RawKeyEventDataWindows({
this.keyCode = 0,
this.scanCode = 0,
this.characterCodePoint = 0,
this.modifiers = 0,
}) : assert(keyCode != null),
assert(scanCode != null),
assert(characterCodePoint != null),
assert(modifiers != null);
/// The hardware key code corresponding to this key event.
///
/// This is the physical key that was pressed, not the Unicode character.
/// See [characterCodePoint] for the Unicode character.
final int keyCode;
/// The hardware scan code id corresponding to this key event.
///
/// These values are not reliable and vary from device to device, so this
/// information is mainly useful for debugging.
final int scanCode;
/// The Unicode code point represented by the key event, if any.
///
/// If there is no Unicode code point, this value is zero.
final int characterCodePoint;
/// A mask of the current modifiers. The modifier values must be in sync with
/// the ones defined in https://github.com/flutter/engine/blob/master/shell/platform/windows/key_event_handler.cc
final int modifiers;
@override
String get keyLabel => characterCodePoint == 0 ? null : String.fromCharCode(characterCodePoint);
@override
PhysicalKeyboardKey get physicalKey => kWindowsToPhysicalKey[scanCode] ?? 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 = kWindowsNumPadMap[keyCode];
if (numPadKey != null) {
return numPadKey;
}
// If it has a non-control-character label, then either return the existing
// constant, or construct a new Unicode-based key from it. Don't mark it as
// autogenerated, since the label uniquely identifies an ID from the Unicode
// plane.
if (keyLabel != null && keyLabel.isNotEmpty && !LogicalKeyboardKey.isControlCharacter(keyLabel)) {
final int keyId = LogicalKeyboardKey.unicodePlane | (characterCodePoint & LogicalKeyboardKey.valueMask);
return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey(
keyId,
keyLabel: keyLabel,
debugName: kReleaseMode ? null : 'Key ${keyLabel.toUpperCase()}',
);
}
// Look to see if the keyCode is one we know about and have a mapping for.
LogicalKeyboardKey newKey = kWindowsToLogicalKey[keyCode];
if (newKey != null) {
return newKey;
}
// 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 windowsKeyIdPlane = 0x00700000000;
newKey ??= LogicalKeyboardKey(
windowsKeyIdPlane | keyCode | LogicalKeyboardKey.autogeneratedMask,
debugName: kReleaseMode ? null : 'Unknown Windows key code $keyCode',
);
return newKey;
}
bool _isLeftRightModifierPressed(KeyboardSide side, int anyMask, int leftMask, int rightMask) {
if (modifiers & anyMask == 0 &&
modifiers & leftMask == 0 &&
modifiers & rightMask == 0) {
return false;
}
// If only the "anyMask" bit is set, then we respond true for requests of
// whether either left or right is pressed.
// Handles the case where Windows supplies just the "either" modifier flag,
// but not the left/right flag. (e.g. modifierShift but not
// modifierLeftShift).
final bool anyOnly = modifiers & (leftMask | rightMask | anyMask) == anyMask;
switch (side) {
case KeyboardSide.any:
return true;
case KeyboardSide.all:
return modifiers & leftMask != 0 && modifiers & rightMask != 0 || anyOnly;
case KeyboardSide.left:
return modifiers & leftMask != 0 || anyOnly;
case KeyboardSide.right:
return modifiers & rightMask != 0 || anyOnly;
}
return false;
}
@override
bool isModifierPressed(ModifierKey key, {KeyboardSide side = KeyboardSide.any}) {
bool result;
switch (key) {
case ModifierKey.controlModifier:
result = _isLeftRightModifierPressed(side, modifierControl, modifierLeftControl, modifierRightControl);
break;
case ModifierKey.shiftModifier:
result = _isLeftRightModifierPressed(side, modifierShift, modifierLeftShift, modifierRightShift);
break;
case ModifierKey.altModifier:
result = _isLeftRightModifierPressed(side, modifierAlt, modifierLeftAlt, modifierRightAlt);
break;
case ModifierKey.metaModifier:
// Windows does not provide an "any" key for win key press.
result = _isLeftRightModifierPressed(side, modifierLeftMeta | modifierRightMeta , modifierLeftMeta, modifierRightMeta);
break;
case ModifierKey.capsLockModifier:
result = modifiers & modifierCaps != 0;
break;
case ModifierKey.scrollLockModifier:
result = modifiers & modifierScrollLock != 0;
break;
case ModifierKey.numLockModifier:
result = modifiers & modifierNumLock != 0;
break;
// The OS does not expose the Fn key to the drivers, it doesn't generate a key message.
case ModifierKey.functionModifier:
case ModifierKey.symbolModifier:
// These modifier masks are not used in Windows keyboards.
result = false;
break;
}
assert(!result || getModifierSide(key) != null, "$runtimeType thinks that a modifier is pressed, but can't figure out what side it's on.");
return result;
}
@override
KeyboardSide getModifierSide(ModifierKey key) {
KeyboardSide findSide(int leftMask, int rightMask, int anyMask) {
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;
} else if (modifiers & (combinedMask | anyMask) == anyMask) {
// Handles the case where Windows supplies just the "either" modifier
// flag, but not the left/right flag. (e.g. modifierShift but not
// modifierLeftShift).
return KeyboardSide.any;
}
return null;
}
switch (key) {
case ModifierKey.controlModifier:
return findSide(modifierLeftControl, modifierRightControl, modifierControl);
case ModifierKey.shiftModifier:
return findSide(modifierLeftShift, modifierRightShift, modifierShift);
case ModifierKey.altModifier:
return findSide(modifierLeftAlt, modifierRightAlt, modifierAlt);
case ModifierKey.metaModifier:
return findSide(modifierLeftMeta, modifierRightMeta, 0);
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;
}
// These are not the values defined by the Windows header for each modifier. Since they
// can't be packaged into a single int, we are re-defining them here to reduce the size
// of the message from the embedder. Embedders should map these values to the native key codes.
// Keep this in sync with https://github.com/flutter/engine/blob/master/shell/platform/windows/key_event_handler.cc
/// This mask is used to check the [modifiers] field to test whether one of the
/// SHIFT modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierShift = 1 << 0;
/// This mask is used to check the [modifiers] field to test whether the left
/// SHIFT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierLeftShift = 1 << 1;
/// This mask is used to check the [modifiers] field to test whether the right
/// SHIFT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierRightShift = 1 << 2;
/// This mask is used to check the [modifiers] field to test whether one of the
/// CTRL modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierControl = 1 << 3;
/// This mask is used to check the [modifiers] field to test whether the left
/// CTRL modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierLeftControl = 1 << 4;
/// This mask is used to check the [modifiers] field to test whether the right
/// CTRL modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierRightControl = 1 << 5;
/// This mask is used to check the [modifiers] field to test whether one of the
/// ALT modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierAlt = 1 << 6;
/// This mask is used to check the [modifiers] field to test whether the left
/// ALT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierLeftAlt = 1 << 7;
/// This mask is used to check the [modifiers] field to test whether the right
/// ALT modifier key is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierRightAlt = 1 << 8;
/// This mask is used to check the [modifiers] field to test whether the left
/// WIN modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierLeftMeta = 1 << 9;
/// This mask is used to check the [modifiers] field to test whether the right
/// WIN modifier keys is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierRightMeta = 1 << 10;
/// This mask is used to check the [modifiers] field to test whether the CAPS LOCK key
/// is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierCaps = 1 << 11;
/// This mask is used to check the [modifiers] field to test whether the NUM LOCK key
/// is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierNumLock = 1 << 12;
/// This mask is used to check the [modifiers] field to test whether the SCROLL LOCK key
/// is pressed.
///
/// {@macro flutter.services.rawKeyEventDataWindows.modifiers}
static const int modifierScrollLock = 1 << 13;
}
......@@ -15,7 +15,7 @@ class _ModifierCheck {
void main() {
group('RawKeyboard', () {
testWidgets('keysPressed is maintained', (WidgetTester tester) async {
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia']) {
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows']) {
RawKeyboard.instance.clearKeysPressed();
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
......@@ -70,8 +70,8 @@ void main() {
);
await simulateKeyUpEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
// The Fn key isn't mapped on linux.
if (platform != 'linux') {
// The Fn key isn't mapped on linux or Windows.
if (platform != 'linux' && platform != 'windows') {
await simulateKeyDownEvent(LogicalKeyboardKey.fn, platform: platform);
expect(
RawKeyboard.instance.keysPressed,
......@@ -107,7 +107,7 @@ void main() {
}, skip: kIsWeb);
testWidgets('keysPressed is correct when modifier is released before key', (WidgetTester tester) async {
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia']) {
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows']) {
RawKeyboard.instance.clearKeysPressed();
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform, physicalKey: PhysicalKeyboardKey.shiftLeft);
......@@ -176,6 +176,31 @@ void main() {
);
});
testWidgets('keysPressed modifiers are synchronized with key events on Windows', (WidgetTester tester) async {
expect(RawKeyboard.instance.keysPressed, isEmpty);
// Generate the data for a regular key down event.
final Map<String, dynamic> data = KeyEventSimulator.getKeyData(
LogicalKeyboardKey.keyA,
platform: 'windows',
isDown: true,
);
// Change the modifiers so that they show the shift key as already down
// when this event is received, but it's not in keysPressed yet.
data['modifiers'] |= RawKeyEventDataWindows.modifierLeftShift | RawKeyEventDataWindows.modifierShift;
// dispatch the modified data.
await ServicesBinding.instance.defaultBinaryMessenger.handlePlatformMessage(
SystemChannels.keyEvent.name,
SystemChannels.keyEvent.codec.encodeMessage(data),
(ByteData data) {},
);
expect(
RawKeyboard.instance.keysPressed,
equals(
<LogicalKeyboardKey>{LogicalKeyboardKey.shiftLeft, LogicalKeyboardKey.keyA},
),
);
});
testWidgets('keysPressed modifiers are synchronized with key events on android', (WidgetTester tester) async {
expect(RawKeyboard.instance.keysPressed, isEmpty);
// Generate the data for a regular key down event.
......@@ -746,6 +771,151 @@ void main() {
expect(data.logicalKey.keyLabel, isNull);
});
}, skip: isBrowser);
group('RawKeyEventDataWindows', () {
const Map<int, _ModifierCheck> modifierTests = <int, _ModifierCheck>{
RawKeyEventDataWindows.modifierLeftAlt: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.left),
RawKeyEventDataWindows.modifierRightAlt: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.right),
RawKeyEventDataWindows.modifierLeftShift: _ModifierCheck(ModifierKey.shiftModifier, KeyboardSide.left),
RawKeyEventDataWindows.modifierRightShift: _ModifierCheck(ModifierKey.shiftModifier, KeyboardSide.right),
RawKeyEventDataWindows.modifierLeftControl: _ModifierCheck(ModifierKey.controlModifier, KeyboardSide.left),
RawKeyEventDataWindows.modifierRightControl: _ModifierCheck(ModifierKey.controlModifier, KeyboardSide.right),
RawKeyEventDataWindows.modifierLeftMeta: _ModifierCheck(ModifierKey.metaModifier, KeyboardSide.left),
RawKeyEventDataWindows.modifierRightMeta: _ModifierCheck(ModifierKey.metaModifier, KeyboardSide.right),
RawKeyEventDataWindows.modifierShift: _ModifierCheck(ModifierKey.shiftModifier, KeyboardSide.any),
RawKeyEventDataWindows.modifierControl: _ModifierCheck(ModifierKey.controlModifier, KeyboardSide.any),
RawKeyEventDataWindows.modifierAlt: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.any),
RawKeyEventDataWindows.modifierCaps: _ModifierCheck(ModifierKey.capsLockModifier, KeyboardSide.all),
RawKeyEventDataWindows.modifierNumLock: _ModifierCheck(ModifierKey.numLockModifier, KeyboardSide.all),
RawKeyEventDataWindows.modifierScrollLock: _ModifierCheck(ModifierKey.scrollLockModifier, KeyboardSide.all),
};
test('modifier keys are recognized individually', () {
for (final int modifier in modifierTests.keys) {
final RawKeyEvent event = RawKeyEvent.fromMessage(<String, dynamic>{
'type': 'keydown',
'keymap': 'windows',
'keyCode': 0x04,
'characterCodePoint': 0,
'scanCode': 0x04,
'modifiers': modifier,
});
final RawKeyEventDataWindows data = event.data as RawKeyEventDataWindows;
for (final 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 modifier $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 (final int modifier in modifierTests.keys) {
if (modifier == RawKeyEventDataWindows.modifierCaps) {
// No need to combine caps lock key with itself.
continue;
}
final RawKeyEvent event = RawKeyEvent.fromMessage(<String, dynamic>{
'type': 'keydown',
'keymap': 'windows',
'keyCode': 0x04,
'characterCodePoint': 0,
'scanCode': 0x04,
'modifiers': modifier | RawKeyEventDataWindows.modifierCaps,
});
final RawKeyEventDataWindows data = event.data as RawKeyEventDataWindows;
for (final ModifierKey key in ModifierKey.values) {
if (modifierTests[modifier].key == key || key == ModifierKey.capsLockModifier) {
expect(
data.isModifierPressed(key, side: modifierTests[modifier].side),
isTrue,
reason: '$key should be pressed with metaState $modifier '
"and additional key ${RawKeyEventDataWindows.modifierCaps}, but isn't.",
);
if (key != ModifierKey.capsLockModifier) {
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 '
'and additional key ${RawKeyEventDataWindows.modifierCaps}.',
);
}
}
}
});
test('Printable keyboard keys are correctly translated', () {
const int unmodifiedCharacter = 97; // ASCII value for 'a'.
final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
'type': 'keydown',
'keymap': 'windows',
'keyCode': 0x00000000,
'characterCodePoint': unmodifiedCharacter,
'scanCode': 0x0000001e,
'modifiers': 0x0,
});
final RawKeyEventDataWindows data = keyAEvent.data as RawKeyEventDataWindows;
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': 'windows',
'keyCode': 27, // keycode for escape key
'scanCode': 0x00000001, // scanCode for escape key
'characterCodePoint': 0,
'modifiers': 0x0,
});
final RawKeyEventDataWindows data = escapeKeyEvent.data as RawKeyEventDataWindows;
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': 'windows',
'keyCode': 160, // keyCode for left shift.
'scanCode': 0x0000002a, // scanCode for left shift.
'characterCodePoint': 0,
'modifiers': RawKeyEventDataWindows.modifierLeftShift,
});
final RawKeyEventDataWindows data = shiftLeftKeyEvent.data as RawKeyEventDataWindows;
expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft));
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
expect(data.keyLabel, isNull);
});
test('Unprintable keyboard keys are correctly translated', () {
final RawKeyEvent leftArrowKey = RawKeyEvent.fromMessage(const <String, dynamic>{
'type': 'keydown',
'keymap': 'windows',
'keyCode': 37, // keyCode for left arrow.
'scanCode': 0x0000e04b, // scanCode for left arrow.
'characterCodePoint': 0,
'modifiers': 0,
});
final RawKeyEventDataWindows data = leftArrowKey.data as RawKeyEventDataWindows;
expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowLeft));
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowLeft));
expect(data.logicalKey.keyLabel, isNull);
});
}, skip: isBrowser);
group('RawKeyEventDataLinux-GFLW', () {
const Map<int, _ModifierCheck> modifierTests = <int, _ModifierCheck>{
GLFWKeyHelper.modifierAlt: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.any),
......
......@@ -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