[windows] Adds support for keyboard mapping. (#54227)
This commit is contained in:
parent
45bf838014
commit
a0f7f6ca6d
@ -109,6 +109,11 @@ class _HardwareKeyDemoState extends State<RawKeyboardDemo> {
|
|||||||
dataText.add(Text('scanCode: ${data.scanCode}'));
|
dataText.add(Text('scanCode: ${data.scanCode}'));
|
||||||
dataText.add(Text('unicodeScalarValues: ${data.unicodeScalarValues}'));
|
dataText.add(Text('unicodeScalarValues: ${data.unicodeScalarValues}'));
|
||||||
dataText.add(Text('modifiers: ${data.modifiers} (${_asHex(data.modifiers)})'));
|
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('logical: ${_event.logicalKey}'));
|
||||||
dataText.add(Text('physical: ${_event.physicalKey}'));
|
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
|
/// Get contents of the file that contains the key code mapping in Chromium
|
||||||
/// source.
|
/// source.
|
||||||
Future<String> getChromiumConversions() async {
|
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');
|
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 await http.read(keyCodeMapUri);
|
return utf8.decode(base64.decode(await http.read(keyCodesUri)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get contents of the file that contains the key codes in Android source.
|
/// Get contents of the file that contains the key codes in Android source.
|
||||||
|
@ -191,29 +191,6 @@
|
|||||||
"windows": null
|
"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": {
|
"sleep": {
|
||||||
"names": {
|
"names": {
|
||||||
"domkey": "Sleep",
|
"domkey": "Sleep",
|
||||||
@ -3080,7 +3057,9 @@
|
|||||||
"glfw": [
|
"glfw": [
|
||||||
"RIGHT"
|
"RIGHT"
|
||||||
],
|
],
|
||||||
"windows": null
|
"windows": [
|
||||||
|
"RIGHT"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"scanCodes": {
|
"scanCodes": {
|
||||||
"android": [
|
"android": [
|
||||||
@ -3099,7 +3078,9 @@
|
|||||||
"glfw": [
|
"glfw": [
|
||||||
262
|
262
|
||||||
],
|
],
|
||||||
"windows": null
|
"windows": [
|
||||||
|
39
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"arrowLeft": {
|
"arrowLeft": {
|
||||||
@ -3113,7 +3094,9 @@
|
|||||||
"glfw": [
|
"glfw": [
|
||||||
"LEFT"
|
"LEFT"
|
||||||
],
|
],
|
||||||
"windows": null
|
"windows": [
|
||||||
|
"LEFT"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"scanCodes": {
|
"scanCodes": {
|
||||||
"android": [
|
"android": [
|
||||||
@ -3132,7 +3115,9 @@
|
|||||||
"glfw": [
|
"glfw": [
|
||||||
263
|
263
|
||||||
],
|
],
|
||||||
"windows": null
|
"windows": [
|
||||||
|
37
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"arrowDown": {
|
"arrowDown": {
|
||||||
@ -3146,7 +3131,9 @@
|
|||||||
"glfw": [
|
"glfw": [
|
||||||
"DOWN"
|
"DOWN"
|
||||||
],
|
],
|
||||||
"windows": null
|
"windows": [
|
||||||
|
"DOWN"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"scanCodes": {
|
"scanCodes": {
|
||||||
"android": [
|
"android": [
|
||||||
@ -3165,7 +3152,9 @@
|
|||||||
"glfw": [
|
"glfw": [
|
||||||
264
|
264
|
||||||
],
|
],
|
||||||
"windows": null
|
"windows": [
|
||||||
|
40
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"arrowUp": {
|
"arrowUp": {
|
||||||
@ -3179,7 +3168,9 @@
|
|||||||
"glfw": [
|
"glfw": [
|
||||||
"UP"
|
"UP"
|
||||||
],
|
],
|
||||||
"windows": null
|
"windows": [
|
||||||
|
"UP"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"scanCodes": {
|
"scanCodes": {
|
||||||
"android": [
|
"android": [
|
||||||
@ -3198,7 +3189,9 @@
|
|||||||
"glfw": [
|
"glfw": [
|
||||||
265
|
265
|
||||||
],
|
],
|
||||||
"windows": null
|
"windows": [
|
||||||
|
38
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"numLock": {
|
"numLock": {
|
||||||
|
@ -31,10 +31,10 @@
|
|||||||
"next": ["NEXT"],
|
"next": ["NEXT"],
|
||||||
"end": ["END"],
|
"end": ["END"],
|
||||||
"home": ["HOME"],
|
"home": ["HOME"],
|
||||||
"leftArrow": ["LEFT"],
|
"arrowLeft": ["LEFT"],
|
||||||
"upArrow": ["UP"],
|
"arrowUp": ["UP"],
|
||||||
"rightArrow": ["RIGHT"],
|
"arrowRight": ["RIGHT"],
|
||||||
"downArrow": ["DOWN"],
|
"arrowDown": ["DOWN"],
|
||||||
"select": ["SELECT"],
|
"select": ["SELECT"],
|
||||||
"print": ["PRINT"],
|
"print": ["PRINT"],
|
||||||
"execute": ["EXECUTE"],
|
"execute": ["EXECUTE"],
|
||||||
|
@ -19,7 +19,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
/// that are returned from [RawKeyEvent.physicalKey].
|
/// that are returned from [RawKeyEvent.physicalKey].
|
||||||
/// * [LogicalKeyboardKey], a class with static values that describe the keys
|
/// * [LogicalKeyboardKey], a class with static values that describe the keys
|
||||||
/// that are returned from [RawKeyEvent.logicalKey].
|
/// 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.
|
/// A const constructor so that subclasses may be const.
|
||||||
const KeyboardKey();
|
const KeyboardKey();
|
||||||
}
|
}
|
||||||
|
@ -92,3 +92,20 @@ const Map<String, PhysicalKeyboardKey> kWebToPhysicalKey = <String, PhysicalKeyb
|
|||||||
const Map<String, LogicalKeyboardKey> kWebNumPadMap = <String, LogicalKeyboardKey>{
|
const Map<String, LogicalKeyboardKey> kWebNumPadMap = <String, LogicalKeyboardKey>{
|
||||||
@@@WEB_NUMPAD_MAP@@@
|
@@@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();
|
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.
|
/// This generates the map of macOS key codes to physical keys.
|
||||||
String get macOsScanCodeMap {
|
String get macOsScanCodeMap {
|
||||||
final StringBuffer macOsScanCodeMap = StringBuffer();
|
final StringBuffer macOsScanCodeMap = StringBuffer();
|
||||||
@ -381,6 +418,9 @@ $otherComments static const LogicalKeyboardKey $constantName = LogicalKeyboardK
|
|||||||
'WEB_LOGICAL_KEY_MAP': webLogicalKeyMap,
|
'WEB_LOGICAL_KEY_MAP': webLogicalKeyMap,
|
||||||
'WEB_PHYSICAL_KEY_MAP': webPhysicalKeyMap,
|
'WEB_PHYSICAL_KEY_MAP': webPhysicalKeyMap,
|
||||||
'WEB_NUMPAD_MAP': webNumpadMap,
|
'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();
|
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_linux.dart';
|
||||||
export 'src/services/raw_keyboard_macos.dart';
|
export 'src/services/raw_keyboard_macos.dart';
|
||||||
export 'src/services/raw_keyboard_web.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_channels.dart';
|
||||||
export 'src/services/system_chrome.dart';
|
export 'src/services/system_chrome.dart';
|
||||||
export 'src/services/system_navigator.dart';
|
export 'src/services/system_navigator.dart';
|
||||||
|
@ -2020,3 +2020,306 @@ const Map<String, LogicalKeyboardKey> kWebNumPadMap = <String, LogicalKeyboardKe
|
|||||||
'NumpadParenLeft': LogicalKeyboardKey.numpadParenLeft,
|
'NumpadParenLeft': LogicalKeyboardKey.numpadParenLeft,
|
||||||
'NumpadParenRight': LogicalKeyboardKey.numpadParenRight,
|
'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_linux.dart';
|
||||||
import 'raw_keyboard_macos.dart';
|
import 'raw_keyboard_macos.dart';
|
||||||
import 'raw_keyboard_web.dart';
|
import 'raw_keyboard_web.dart';
|
||||||
|
import 'raw_keyboard_windows.dart';
|
||||||
import 'system_channels.dart';
|
import 'system_channels.dart';
|
||||||
|
|
||||||
/// An enum describing the side of the keyboard that a key is on, to allow
|
/// 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,
|
metaState: message['metaState'] as int,
|
||||||
);
|
);
|
||||||
break;
|
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:
|
default:
|
||||||
// Raw key events are not yet implemented on iOS or other platforms,
|
// Raw key events are not yet implemented on iOS or other platforms,
|
||||||
// but this exception isn't hit, because the engine never sends these
|
// but this exception isn't hit, because the engine never sends these
|
||||||
|
291
packages/flutter/lib/src/services/raw_keyboard_windows.dart
Normal file
291
packages/flutter/lib/src/services/raw_keyboard_windows.dart
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
// 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() {
|
void main() {
|
||||||
group('RawKeyboard', () {
|
group('RawKeyboard', () {
|
||||||
testWidgets('keysPressed is maintained', (WidgetTester tester) async {
|
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();
|
RawKeyboard.instance.clearKeysPressed();
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
|
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
|
||||||
@ -70,8 +70,8 @@ void main() {
|
|||||||
);
|
);
|
||||||
await simulateKeyUpEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
|
await simulateKeyUpEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
||||||
// The Fn key isn't mapped on linux.
|
// The Fn key isn't mapped on linux or Windows.
|
||||||
if (platform != 'linux') {
|
if (platform != 'linux' && platform != 'windows') {
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.fn, platform: platform);
|
await simulateKeyDownEvent(LogicalKeyboardKey.fn, platform: platform);
|
||||||
expect(
|
expect(
|
||||||
RawKeyboard.instance.keysPressed,
|
RawKeyboard.instance.keysPressed,
|
||||||
@ -107,7 +107,7 @@ void main() {
|
|||||||
}, skip: kIsWeb);
|
}, skip: kIsWeb);
|
||||||
|
|
||||||
testWidgets('keysPressed is correct when modifier is released before key', (WidgetTester tester) async {
|
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();
|
RawKeyboard.instance.clearKeysPressed();
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
expect(RawKeyboard.instance.keysPressed, isEmpty, reason: 'on $platform');
|
||||||
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform, physicalKey: PhysicalKeyboardKey.shiftLeft);
|
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 {
|
testWidgets('keysPressed modifiers are synchronized with key events on android', (WidgetTester tester) async {
|
||||||
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
expect(RawKeyboard.instance.keysPressed, isEmpty);
|
||||||
// Generate the data for a regular key down event.
|
// Generate the data for a regular key down event.
|
||||||
@ -746,6 +771,151 @@ void main() {
|
|||||||
expect(data.logicalKey.keyLabel, isNull);
|
expect(data.logicalKey.keyLabel, isNull);
|
||||||
});
|
});
|
||||||
}, skip: isBrowser);
|
}, 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', () {
|
group('RawKeyEventDataLinux-GFLW', () {
|
||||||
const Map<int, _ModifierCheck> modifierTests = <int, _ModifierCheck>{
|
const Map<int, _ModifierCheck> modifierTests = <int, _ModifierCheck>{
|
||||||
GLFWKeyHelper.modifierAlt: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.any),
|
GLFWKeyHelper.modifierAlt: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.any),
|
||||||
|
@ -40,6 +40,7 @@ class KeyEventSimulator {
|
|||||||
case 'macos':
|
case 'macos':
|
||||||
case 'linux':
|
case 'linux':
|
||||||
case 'web':
|
case 'web':
|
||||||
|
case 'windows':
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -62,6 +63,9 @@ class KeyEventSimulator {
|
|||||||
case 'linux':
|
case 'linux':
|
||||||
map = kLinuxToPhysicalKey;
|
map = kLinuxToPhysicalKey;
|
||||||
break;
|
break;
|
||||||
|
case 'windows':
|
||||||
|
map = kWindowsToPhysicalKey;
|
||||||
|
break;
|
||||||
case 'web':
|
case 'web':
|
||||||
// web doesn't have int type code
|
// web doesn't have int type code
|
||||||
return null;
|
return null;
|
||||||
@ -95,6 +99,9 @@ class KeyEventSimulator {
|
|||||||
case 'linux':
|
case 'linux':
|
||||||
map = kGlfwToLogicalKey;
|
map = kGlfwToLogicalKey;
|
||||||
break;
|
break;
|
||||||
|
case 'windows':
|
||||||
|
map = kWindowsToLogicalKey;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
for (final int code in map.keys) {
|
for (final int code in map.keys) {
|
||||||
if (key.keyId == map[code].keyId) {
|
if (key.keyId == map[code].keyId) {
|
||||||
@ -132,6 +139,9 @@ class KeyEventSimulator {
|
|||||||
case 'web':
|
case 'web':
|
||||||
map = kWebToPhysicalKey;
|
map = kWebToPhysicalKey;
|
||||||
break;
|
break;
|
||||||
|
case 'windows':
|
||||||
|
map = kWindowsToPhysicalKey;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
for (final PhysicalKeyboardKey physicalKey in map.values) {
|
for (final PhysicalKeyboardKey physicalKey in map.values) {
|
||||||
if (key.debugName == physicalKey.debugName) {
|
if (key.debugName == physicalKey.debugName) {
|
||||||
@ -195,6 +205,12 @@ class KeyEventSimulator {
|
|||||||
result['code'] = _getWebKeyCode(key);
|
result['code'] = _getWebKeyCode(key);
|
||||||
result['key'] = '';
|
result['key'] = '';
|
||||||
result['metaState'] = _getWebModifierFlags(key, isDown);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
@ -272,6 +288,59 @@ class KeyEventSimulator {
|
|||||||
return result;
|
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) {
|
static int _getFuchsiaModifierFlags(LogicalKeyboardKey newKey, bool isDown) {
|
||||||
int result = 0;
|
int result = 0;
|
||||||
final Set<LogicalKeyboardKey> pressed = RawKeyboard.instance.keysPressed;
|
final Set<LogicalKeyboardKey> pressed = RawKeyboard.instance.keysPressed;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user