use RawKeyEvent and Listener for input

This commit is contained in:
csf 2022-04-25 18:25:25 +08:00
parent b161b696b6
commit b30299cc12
7 changed files with 653 additions and 75 deletions

View File

@ -689,10 +689,15 @@ class FFI {
json.encode(modify({'type': type, 'buttons': button.value}))); json.encode(modify({'type': type, 'buttons': button.value})));
} }
static void inputKey(String name) { static void inputKey(String name, [bool? down]) {
if (!ffiModel.keyboard()) return; if (!ffiModel.keyboard()) return;
setByName( setByName(
'input_key', json.encode(modify({'name': name, 'press': 'true'}))); 'input_key',
json.encode(modify({
'name': name,
'down': (down ?? false).toString(),
'press': 'true'
})));
} }
static void moveMouse(double x, double y) { static void moveMouse(double x, double y) {
@ -807,8 +812,8 @@ class FFI {
x = 0; x = 0;
y = 0; y = 0;
} }
evt['x'] = '$x'; evt['x'] = '${x.round()}';
evt['y'] = '$y'; evt['y'] = '${y.round()}';
var buttons = ''; var buttons = '';
switch (evt['buttons']) { switch (evt['buttons']) {
case 1: case 1:
@ -827,7 +832,7 @@ class FFI {
static listenToMouse(bool yesOrNo) { static listenToMouse(bool yesOrNo) {
if (yesOrNo) { if (yesOrNo) {
PlatformFFI.startDesktopWebListener(handleMouse); PlatformFFI.startDesktopWebListener();
} else { } else {
PlatformFFI.stopDesktopWebListener(); PlatformFFI.stopDesktopWebListener();
} }

View File

@ -115,8 +115,7 @@ class PlatformFFI {
version = await getVersion(); version = await getVersion();
} }
static void startDesktopWebListener( static void startDesktopWebListener() {}
Function(Map<String, dynamic>) handleMouse) {}
static void stopDesktopWebListener() {} static void stopDesktopWebListener() {}

View File

@ -1,6 +1,5 @@
import 'dart:typed_data'; import 'dart:typed_data';
import 'dart:js' as js; import 'dart:js' as js;
import 'package:flutter/cupertino.dart';
import 'dart:convert'; import 'dart:convert';
import '../common.dart'; import '../common.dart';
@ -35,38 +34,37 @@ class PlatformFFI {
} }
// MouseRegion onHover not work for mouse move when right button down // MouseRegion onHover not work for mouse move when right button down
static void startDesktopWebListener( static void startDesktopWebListener() {
Function(Map<String, dynamic>) handleMouse) {
mouseIn = true; mouseIn = true;
lastMouseDownButtons = 0; // lastMouseDownButtons = 0;
// document.body.getElementsByTagName('flt-glass-pane')[0].style.cursor = 'none'; // // document.body.getElementsByTagName('flt-glass-pane')[0].style.cursor = 'none';
mouseListeners // mouseListeners
.add(window.document.onMouseEnter.listen((evt) => mouseIn = true)); // .add(window.document.onMouseEnter.listen((evt) => mouseIn = true));
mouseListeners // mouseListeners
.add(window.document.onMouseLeave.listen((evt) => mouseIn = false)); // .add(window.document.onMouseLeave.listen((evt) => mouseIn = false));
mouseListeners.add(window.document.onMouseMove // mouseListeners.add(window.document.onMouseMove
.listen((evt) => handleMouse(getEvent(evt)))); // .listen((evt) => handleMouse(getEvent(evt))));
mouseListeners.add(window.document.onMouseDown // mouseListeners.add(window.document.onMouseDown
.listen((evt) => handleMouse(getEvent(evt)))); // .listen((evt) => handleMouse(getEvent(evt))));
mouseListeners.add( // mouseListeners.add(
window.document.onMouseUp.listen((evt) => handleMouse(getEvent(evt)))); // window.document.onMouseUp.listen((evt) => handleMouse(getEvent(evt))));
mouseListeners.add(window.document.onMouseWheel.listen((evt) { // mouseListeners.add(window.document.onMouseWheel.listen((evt) {
var dx = evt.deltaX; // var dx = evt.deltaX;
var dy = evt.deltaY; // var dy = evt.deltaY;
if (dx > 0) // if (dx > 0)
dx = -1; // dx = -1;
else if (dx < 0) dx = 1; // else if (dx < 0) dx = 1;
if (dy > 0) // if (dy > 0)
dy = -1; // dy = -1;
else if (dy < 0) dy = 1; // else if (dy < 0) dy = 1;
setByName('send_mouse', '{"type": "wheel", "x": "$dx", "y": "$dy"}'); // setByName('send_mouse', '{"type": "wheel", "x": "$dx", "y": "$dy"}');
})); // }));
mouseListeners.add( mouseListeners.add(
window.document.onContextMenu.listen((evt) => evt.preventDefault())); window.document.onContextMenu.listen((evt) => evt.preventDefault()));
keyListeners // keyListeners
.add(window.document.onKeyDown.listen((evt) => handleKey(evt, true))); // .add(window.document.onKeyDown.listen((evt) => handleKey(evt, true)));
keyListeners // keyListeners
.add(window.document.onKeyUp.listen((evt) => handleKey(evt, false))); // .add(window.document.onKeyUp.listen((evt) => handleKey(evt, false)));
} }
static void stopDesktopWebListener() { static void stopDesktopWebListener() {

View File

@ -1,3 +1,4 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_hbb/models/chat_model.dart'; import 'package:flutter_hbb/models/chat_model.dart';
import 'package:flutter_hbb/widgets/gesture_help.dart'; import 'package:flutter_hbb/widgets/gesture_help.dart';
@ -34,9 +35,11 @@ class _RemotePageState extends State<RemotePage> {
var _more = true; var _more = true;
var _fn = false; var _fn = false;
final FocusNode _focusNode = FocusNode(); final FocusNode _mobileFocusNode = FocusNode();
final FocusNode _physicalFocusNode = FocusNode();
var _showEdit = false; var _showEdit = false;
var _touchMode = false; var _touchMode = false;
var _isPhysicalKeyboard = false;
@override @override
void initState() { void initState() {
@ -50,11 +53,15 @@ class _RemotePageState extends State<RemotePage> {
}); });
Wakelock.enable(); Wakelock.enable();
_touchMode = FFI.getByName('peer_option', "touch-mode") != ''; _touchMode = FFI.getByName('peer_option', "touch-mode") != '';
_physicalFocusNode.requestFocus();
FFI.listenToMouse(true);
} }
@override @override
void dispose() { void dispose() {
_focusNode.dispose(); FFI.listenToMouse(false);
_mobileFocusNode.dispose();
_physicalFocusNode.dispose();
FFI.close(); FFI.close();
_interval?.cancel(); _interval?.cancel();
_timer?.cancel(); _timer?.cancel();
@ -95,6 +102,7 @@ class _RemotePageState extends State<RemotePage> {
} catch (e) {} } catch (e) {}
} }
// handle mobile virtual keyboard
void handleInput(String newValue) { void handleInput(String newValue) {
var oldValue = _value; var oldValue = _value;
_value = newValue; _value = newValue;
@ -186,11 +194,18 @@ class _RemotePageState extends State<RemotePage> {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
overlays: SystemUiOverlay.values); overlays: SystemUiOverlay.values);
SystemChannels.textInput.invokeMethod('TextInput.show'); SystemChannels.textInput.invokeMethod('TextInput.show');
_focusNode.requestFocus(); _mobileFocusNode.requestFocus();
}); });
}); });
} }
void sendRawKey(RawKeyEvent e, [bool? down]) {
final label = _keyLabels[e.logicalKey.keyId];
if (label != null) {
FFI.inputKey(label, down);
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final pi = Provider.of<FfiModel>(context).pi; final pi = Provider.of<FfiModel>(context).pi;
@ -214,6 +229,9 @@ class _RemotePageState extends State<RemotePage> {
setState(() { setState(() {
if (hideKeyboard) { if (hideKeyboard) {
_showEdit = false; _showEdit = false;
_mobileFocusNode.unfocus();
SystemChannels.textInput.invokeMethod('TextInput.hide');
_physicalFocusNode.requestFocus();
} else { } else {
_showBar = !_showBar; _showBar = !_showBar;
} }
@ -224,17 +242,125 @@ class _RemotePageState extends State<RemotePage> {
body: Overlay( body: Overlay(
initialEntries: [ initialEntries: [
OverlayEntry(builder: (context) { OverlayEntry(builder: (context) {
final keyboard = FFI.ffiModel.permissions['keyboard'] != false;
return Container( return Container(
color: Colors.black, color: Colors.black,
child: isDesktop child: getRawPointerAndKeyBody(keyboard));
? getBodyForDesktopWithListener()
: SafeArea(child: getBodyForMobileWithGesture()));
}) })
], ],
)), )),
); );
} }
Widget getRawPointerAndKeyBody(bool keyboard) {
return Listener(
onPointerHover: (e) {
if (e.kind != ui.PointerDeviceKind.mouse) return;
if (!_isPhysicalKeyboard) {
setState(() {
_isPhysicalKeyboard = true;
});
}
if (_isPhysicalKeyboard) {
FFI.handleMouse(getEvent(e, 'mousemove'));
}
},
onPointerDown: (e) {
if (e.kind != ui.PointerDeviceKind.mouse) {
if (_isPhysicalKeyboard) {
setState(() {
_isPhysicalKeyboard = false;
});
}
}
if (_isPhysicalKeyboard) {
FFI.handleMouse(getEvent(e, 'mousedown'));
}
},
onPointerUp: (e) {
if (e.kind != ui.PointerDeviceKind.mouse) return;
if (_isPhysicalKeyboard) {
FFI.handleMouse(getEvent(e, 'mouseup'));
}
},
onPointerMove: (e) {
if (e.kind != ui.PointerDeviceKind.mouse) return;
if (_isPhysicalKeyboard) {
FFI.handleMouse(getEvent(e, 'mousemove'));
}
},
onPointerSignal: (e) {
if (e is PointerScrollEvent) {
var dx = e.scrollDelta.dx;
var dy = e.scrollDelta.dy;
if (dx > 0)
dx = -1;
else if (dx < 0) dx = 1;
if (dy > 0)
dy = -1;
else if (dy < 0) dy = 1;
FFI.setByName(
'send_mouse', '{"type": "wheel", "x": "$dx", "y": "$dy"}');
}
},
child: MouseRegion(
cursor: keyboard ? SystemMouseCursors.none : MouseCursor.defer,
child: FocusScope(
autofocus: true,
child: Focus(
autofocus: true,
canRequestFocus: true,
focusNode: _physicalFocusNode,
onKey: (data, e) {
final key = e.logicalKey;
if (e is RawKeyDownEvent) {
if (e.isAltPressed && !FFI.alt) {
FFI.alt = true;
sendRawKey(e, true);
} else if (e.isControlPressed && !FFI.ctrl) {
FFI.ctrl = true;
sendRawKey(e, true);
} else if (e.isShiftPressed && !FFI.shift) {
FFI.shift = true;
sendRawKey(e, true);
} else if (e.isMetaPressed && !FFI.command) {
FFI.command = true;
sendRawKey(e, true);
} else if (e.repeat) {
sendRawKey(e);
}
}
if (e is RawKeyUpEvent) {
if (key == LogicalKeyboardKey.altLeft ||
key == LogicalKeyboardKey.altRight) {
FFI.alt = false;
}
if (key == LogicalKeyboardKey.controlLeft ||
key == LogicalKeyboardKey.controlRight) {
FFI.ctrl = false;
}
if (key == LogicalKeyboardKey.shiftRight ||
key == LogicalKeyboardKey.shiftLeft) {
FFI.shift = false;
}
if (key == LogicalKeyboardKey.metaLeft ||
key == LogicalKeyboardKey.metaRight) {
FFI.command = false;
}
sendRawKey(e);
}
return KeyEventResult.handled;
},
child: isDesktop
? getBodyForDesktopWithListener(keyboard)
: SafeArea(
child: Container(
color: MyTheme.canvasColor,
child: _isPhysicalKeyboard
? getBodyForMobile()
: getBodyForMobileWithGesture()))))));
}
Widget getBottomAppBar() { Widget getBottomAppBar() {
return BottomAppBar( return BottomAppBar(
elevation: 10, elevation: 10,
@ -347,9 +473,7 @@ class _RemotePageState extends State<RemotePage> {
} }
}, },
onLongPress: () { onLongPress: () {
if (_touchMode) {
FFI.tap(MouseButtons.right); FFI.tap(MouseButtons.right);
}
}, },
onDoubleFinerTap: (d) { onDoubleFinerTap: (d) {
if (!_touchMode) { if (!_touchMode) {
@ -373,7 +497,6 @@ class _RemotePageState extends State<RemotePage> {
}, },
onOneFingerPanStart: (d) { onOneFingerPanStart: (d) {
if (_touchMode) { if (_touchMode) {
debugPrint("_touchMode , onOneFingerPanStart");
FFI.cursorModel.move(d.localPosition.dx, d.localPosition.dy); FFI.cursorModel.move(d.localPosition.dx, d.localPosition.dy);
FFI.sendMouse('down', MouseButtons.left); FFI.sendMouse('down', MouseButtons.left);
} else { } else {
@ -420,7 +543,7 @@ class _RemotePageState extends State<RemotePage> {
textInputAction: TextInputAction.newline, textInputAction: TextInputAction.newline,
autocorrect: false, autocorrect: false,
enableSuggestions: false, enableSuggestions: false,
focusNode: _focusNode, focusNode: _mobileFocusNode,
maxLines: null, maxLines: null,
initialValue: _value, initialValue: _value,
// trick way to make backspace work always // trick way to make backspace work always
@ -431,26 +554,34 @@ class _RemotePageState extends State<RemotePage> {
])); ]));
} }
Widget getBodyForDesktopWithListener() { Widget getBodyForDesktopWithListener(bool keyboard) {
final keyboard = FFI.ffiModel.permissions['keyboard'] != false;
var paints = <Widget>[ImagePaint()]; var paints = <Widget>[ImagePaint()];
if (keyboard || if (keyboard ||
FFI.getByName('toggle_option', 'show-remote-cursor') == 'true') { FFI.getByName('toggle_option', 'show-remote-cursor') == 'true') {
paints.add(CursorPaint()); paints.add(CursorPaint());
} }
return MouseRegion( return Container(
cursor: keyboard ? SystemMouseCursors.none : MouseCursor.defer, color: MyTheme.canvasColor, child: Stack(children: paints));
// TODO old null // still laggy, set cursor directly for web is better }
onEnter: (event) {
print('enter'); int lastMouseDownButtons = 0;
FFI.listenToMouse(true); Map<String, dynamic> getEvent(PointerEvent evt, String type) {
}, final Map<String, dynamic> out = {};
onExit: (event) { out['type'] = type;
print('exit'); out['x'] = evt.position.dx;
FFI.listenToMouse(false); out['y'] = evt.position.dy;
}, if (FFI.alt) out['alt'] = 'true';
child: Container( if (FFI.shift) out['shift'] = 'true';
color: MyTheme.canvasColor, child: Stack(children: paints))); if (FFI.ctrl) out['ctrl'] = 'true';
if (FFI.command) out['command'] = 'true';
out['buttons'] = evt
.buttons; // left button: 1, right button: 2, middle button: 4, 1 | 2 = 3 (left + right)
if (evt.buttons != 0) {
lastMouseDownButtons = evt.buttons;
} else {
out['buttons'] = lastMouseDownButtons;
}
return out;
} }
void showActions() { void showActions() {
@ -860,15 +991,11 @@ void showOptions() {
content: Column( content: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: displays + children: displays +
(isDesktop <Widget>[
? <Widget>[
getRadio('Original', 'original', viewStyle, setViewStyle), getRadio('Original', 'original', viewStyle, setViewStyle),
getRadio('Shrink', 'shrink', viewStyle, setViewStyle), getRadio('Shrink', 'shrink', viewStyle, setViewStyle),
getRadio('Stretch', 'stretch', viewStyle, setViewStyle), getRadio('Stretch', 'stretch', viewStyle, setViewStyle),
Divider(color: MyTheme.border), Divider(color: MyTheme.border),
]
: []) +
<Widget>[
getRadio('Good image quality', 'best', quality, setQuality), getRadio('Good image quality', 'best', quality, setQuality),
getRadio('Balanced', 'balanced', quality, setQuality), getRadio('Balanced', 'balanced', quality, setQuality),
getRadio('Optimize reaction time', 'low', quality, setQuality), getRadio('Optimize reaction time', 'low', quality, setQuality),
@ -947,3 +1074,452 @@ void sendPrompt(bool isMac, String key) {
FFI.ctrl = old; FFI.ctrl = old;
} }
} }
/// flutter/packages/flutter/lib/src/services/keyboard_key.dart -> _keyLabels
/// see [LogicalKeyboardKey.keyLabel]
const Map<int, String> _keyLabels = <int, String>{
0x00000000020: 'VK_SPACE',
0x00000000021: 'Exclamation',
0x00000000022: 'VK_QUOTE',
0x00000000023: 'Number Sign',
0x00000000024: 'Dollar',
0x00000000025: 'Percent',
0x00000000026: 'Ampersand',
0x00000000027: 'Quote Single',
0x00000000028: 'Parenthesis Left',
0x00000000029: 'Parenthesis Right',
0x0000000002a: 'Asterisk',
0x0000000002b: 'Add',
0x0000000002c: 'VK_COMMA',
0x0000000002d: 'VK_MINUS',
0x0000000002e: 'Period',
0x0000000002f: 'VK_SLASH',
0x00000000030: 'VK_0',
0x00000000031: 'VK_1',
0x00000000032: 'VK_2',
0x00000000033: 'VK_3',
0x00000000034: 'VK_4',
0x00000000035: 'VK_5',
0x00000000036: 'VK_6',
0x00000000037: 'VK_7',
0x00000000038: 'VK_8',
0x00000000039: 'VK_9',
0x0000000003a: 'Colon',
0x0000000003b: 'VK_SEMICOLON',
0x0000000003c: 'Less',
0x0000000003d: 'VK_PLUS', // it is =
0x0000000003e: 'Greater',
0x0000000003f: 'Question',
0x00000000040: 'At',
0x0000000005b: 'VK_LBRACKET',
0x0000000005c: 'VK_BACKSLASH',
0x0000000005d: 'VK_RBRACKET',
0x0000000005e: 'Caret',
0x0000000005f: 'Underscore',
0x00000000060: 'Backquote',
0x00000000061: 'VK_A',
0x00000000062: 'VK_B',
0x00000000063: 'VK_C',
0x00000000064: 'VK_D',
0x00000000065: 'VK_E',
0x00000000066: 'VK_F',
0x00000000067: 'VK_G',
0x00000000068: 'VK_H',
0x00000000069: 'VK_I',
0x0000000006a: 'VK_J',
0x0000000006b: 'VK_K',
0x0000000006c: 'VK_L',
0x0000000006d: 'VK_M',
0x0000000006e: 'VK_N',
0x0000000006f: 'VK_O',
0x00000000070: 'VK_P',
0x00000000071: 'VK_Q',
0x00000000072: 'VK_R',
0x00000000073: 'VK_S',
0x00000000074: 'VK_T',
0x00000000075: 'VK_U',
0x00000000076: 'VK_V',
0x00000000077: 'VK_W',
0x00000000078: 'VK_X',
0x00000000079: 'VK_Y',
0x0000000007a: 'VK_Z',
0x0000000007b: 'Brace Left',
0x0000000007c: 'Bar',
0x0000000007d: 'Brace Right',
0x0000000007e: 'Tilde',
0x00100000001: 'Unidentified',
0x00100000008: 'VK_BACK',
0x00100000009: 'VK_TAB',
0x0010000000d: 'VK_ENTER',
0x0010000001b: 'VK_ESCAPE',
0x0010000007f: 'VK_DELETE',
0x00100000101: 'Accel',
0x00100000103: 'Alt Graph',
0x00100000104: 'VK_CAPITAL',
0x00100000106: 'Fn',
0x00100000107: 'Fn Lock',
0x00100000108: 'Hyper',
0x0010000010a: 'Num Lock',
0x0010000010c: 'Scroll Lock',
0x0010000010e: 'Super',
0x0010000010f: 'Symbol',
0x00100000110: 'Symbol Lock',
0x00100000111: 'Shift Level 5',
0x00100000301: 'VK_DOWN',
0x00100000302: 'VK_LEFT',
0x00100000303: 'VK_RIGHT',
0x00100000304: 'VK_UP',
0x00100000305: 'VK_END',
0x00100000306: 'VK_HOME',
0x00100000307: 'VK_NEXT',
0x00100000308: 'VK_PRIOR',
0x00100000401: 'VK_CLEAR',
0x00100000402: 'Copy',
0x00100000403: 'Cr Sel',
0x00100000404: 'Cut',
0x00100000405: 'Erase Eof',
0x00100000406: 'Ex Sel',
0x00100000407: 'VK_INSERT',
0x00100000408: 'Paste',
0x00100000409: 'Redo',
0x0010000040a: 'Undo',
0x00100000501: 'Accept',
0x00100000502: 'Again',
0x00100000503: 'Attn',
0x00100000504: 'VK_CANCEL',
0x00100000505: 'Context Menu',
0x00100000506: 'VK_EXECUTE',
0x00100000507: 'Find',
0x00100000508: 'VK_HELP',
0x00100000509: 'VK_PAUSE',
0x0010000050a: 'Play',
0x0010000050b: 'Props',
0x0010000050c: 'VK_SELECT',
0x0010000050d: 'Zoom In',
0x0010000050e: 'Zoom Out',
0x00100000601: 'Brightness Down',
0x00100000602: 'Brightness Up',
0x00100000603: 'Camera',
0x00100000604: 'Eject',
0x00100000605: 'Log Off',
0x00100000606: 'Power',
0x00100000607: 'Power Off',
0x00100000608: 'VK_PRINT',
0x00100000609: 'Hibernate',
0x0010000060a: 'Standby',
0x0010000060b: 'Wake Up',
0x00100000701: 'All Candidates',
0x00100000702: 'Alphanumeric',
0x00100000703: 'Code Input',
0x00100000704: 'Compose',
0x00100000705: 'VK_CONVERT',
0x00100000706: 'VK_FINAL',
0x00100000707: 'Group First',
0x00100000708: 'Group Last',
0x00100000709: 'Group Next',
0x0010000070a: 'Group Previous',
0x0010000070b: 'Mode Change',
0x0010000070c: 'Next Candidate',
0x0010000070d: 'Non Convert',
0x0010000070e: 'Previous Candidate',
0x0010000070f: 'Process',
0x00100000710: 'Single Candidate',
0x00100000711: 'VK_HANGUL',
0x00100000712: 'VK_HANJA',
0x00100000713: 'VK_JUNJA',
0x00100000714: 'Eisu',
0x00100000715: 'Hankaku',
0x00100000716: 'Hiragana',
0x00100000717: 'Hiragana Katakana',
0x00100000718: 'VK_KANA',
0x00100000719: 'VK_KANJI',
0x0010000071a: 'Katakana',
0x0010000071b: 'Romaji',
0x0010000071c: 'Zenkaku',
0x0010000071d: 'Zenkaku Hankaku',
0x00100000801: 'VK_F1',
0x00100000802: 'VK_F2',
0x00100000803: 'VK_F3',
0x00100000804: 'VK_F4',
0x00100000805: 'VK_F5',
0x00100000806: 'VK_F6',
0x00100000807: 'VK_F7',
0x00100000808: 'VK_F8',
0x00100000809: 'VK_F9',
0x0010000080a: 'VK_F10',
0x0010000080b: 'VK_F11',
0x0010000080c: 'VK_F12',
0x0010000080d: 'VK_F13',
0x0010000080e: 'VK_F14',
0x0010000080f: 'VK_F15',
0x00100000810: 'VK_F16',
0x00100000811: 'VK_F17',
0x00100000812: 'VK_F18',
0x00100000813: 'VK_F19',
0x00100000814: 'VK_F20',
0x00100000815: 'VK_F21',
0x00100000816: 'VK_F22',
0x00100000817: 'VK_F23',
0x00100000818: 'VK_F24',
0x00100000901: 'Soft 1',
0x00100000902: 'Soft 2',
0x00100000903: 'Soft 3',
0x00100000904: 'Soft 4',
0x00100000905: 'Soft 5',
0x00100000906: 'Soft 6',
0x00100000907: 'Soft 7',
0x00100000908: 'Soft 8',
0x00100000a01: 'Close',
0x00100000a02: 'Mail Forward',
0x00100000a03: 'Mail Reply',
0x00100000a04: 'Mail Send',
0x00100000a05: 'Media Play Pause',
0x00100000a07: 'Media Stop',
0x00100000a08: 'Media Track Next',
0x00100000a09: 'Media Track Previous',
0x00100000a0a: 'New',
0x00100000a0b: 'Open',
0x00100000a0c: 'Print',
0x00100000a0d: 'Save',
0x00100000a0e: 'Spell Check',
0x00100000a0f: 'Audio Volume Down',
0x00100000a10: 'Audio Volume Up',
0x00100000a11: 'Audio Volume Mute',
0x00100000b01: 'Launch Application 2',
0x00100000b02: 'Launch Calendar',
0x00100000b03: 'Launch Mail',
0x00100000b04: 'Launch Media Player',
0x00100000b05: 'Launch Music Player',
0x00100000b06: 'Launch Application 1',
0x00100000b07: 'Launch Screen Saver',
0x00100000b08: 'Launch Spreadsheet',
0x00100000b09: 'Launch Web Browser',
0x00100000b0a: 'Launch Web Cam',
0x00100000b0b: 'Launch Word Processor',
0x00100000b0c: 'Launch Contacts',
0x00100000b0d: 'Launch Phone',
0x00100000b0e: 'Launch Assistant',
0x00100000b0f: 'Launch Control Panel',
0x00100000c01: 'Browser Back',
0x00100000c02: 'Browser Favorites',
0x00100000c03: 'Browser Forward',
0x00100000c04: 'Browser Home',
0x00100000c05: 'Browser Refresh',
0x00100000c06: 'Browser Search',
0x00100000c07: 'Browser Stop',
0x00100000d01: 'Audio Balance Left',
0x00100000d02: 'Audio Balance Right',
0x00100000d03: 'Audio Bass Boost Down',
0x00100000d04: 'Audio Bass Boost Up',
0x00100000d05: 'Audio Fader Front',
0x00100000d06: 'Audio Fader Rear',
0x00100000d07: 'Audio Surround Mode Next',
0x00100000d08: 'AVR Input',
0x00100000d09: 'AVR Power',
0x00100000d0a: 'Channel Down',
0x00100000d0b: 'Channel Up',
0x00100000d0c: 'Color F0 Red',
0x00100000d0d: 'Color F1 Green',
0x00100000d0e: 'Color F2 Yellow',
0x00100000d0f: 'Color F3 Blue',
0x00100000d10: 'Color F4 Grey',
0x00100000d11: 'Color F5 Brown',
0x00100000d12: 'Closed Caption Toggle',
0x00100000d13: 'Dimmer',
0x00100000d14: 'Display Swap',
0x00100000d15: 'Exit',
0x00100000d16: 'Favorite Clear 0',
0x00100000d17: 'Favorite Clear 1',
0x00100000d18: 'Favorite Clear 2',
0x00100000d19: 'Favorite Clear 3',
0x00100000d1a: 'Favorite Recall 0',
0x00100000d1b: 'Favorite Recall 1',
0x00100000d1c: 'Favorite Recall 2',
0x00100000d1d: 'Favorite Recall 3',
0x00100000d1e: 'Favorite Store 0',
0x00100000d1f: 'Favorite Store 1',
0x00100000d20: 'Favorite Store 2',
0x00100000d21: 'Favorite Store 3',
0x00100000d22: 'Guide',
0x00100000d23: 'Guide Next Day',
0x00100000d24: 'Guide Previous Day',
0x00100000d25: 'Info',
0x00100000d26: 'Instant Replay',
0x00100000d27: 'Link',
0x00100000d28: 'List Program',
0x00100000d29: 'Live Content',
0x00100000d2a: 'Lock',
0x00100000d2b: 'Apps',
0x00100000d2c: 'Media Fast Forward',
0x00100000d2d: 'Media Last',
0x00100000d2e: 'Media Pause',
0x00100000d2f: 'Media Play',
0x00100000d30: 'Media Record',
0x00100000d31: 'Media Rewind',
0x00100000d32: 'Media Skip',
0x00100000d33: 'Next Favorite Channel',
0x00100000d34: 'Next User Profile',
0x00100000d35: 'On Demand',
0x00100000d36: 'P In P Down',
0x00100000d37: 'P In P Move',
0x00100000d38: 'P In P Toggle',
0x00100000d39: 'P In P Up',
0x00100000d3a: 'Play Speed Down',
0x00100000d3b: 'Play Speed Reset',
0x00100000d3c: 'Play Speed Up',
0x00100000d3d: 'Random Toggle',
0x00100000d3e: 'Rc Low Battery',
0x00100000d3f: 'Record Speed Next',
0x00100000d40: 'Rf Bypass',
0x00100000d41: 'Scan Channels Toggle',
0x00100000d42: 'Screen Mode Next',
0x00100000d43: 'Settings',
0x00100000d44: 'Split Screen Toggle',
0x00100000d45: 'STB Input',
0x00100000d46: 'STB Power',
0x00100000d47: 'Subtitle',
0x00100000d48: 'Teletext',
0x00100000d49: 'TV',
0x00100000d4a: 'TV Input',
0x00100000d4b: 'TV Power',
0x00100000d4c: 'Video Mode Next',
0x00100000d4d: 'Wink',
0x00100000d4e: 'Zoom Toggle',
0x00100000d4f: 'DVR',
0x00100000d50: 'Media Audio Track',
0x00100000d51: 'Media Skip Backward',
0x00100000d52: 'Media Skip Forward',
0x00100000d53: 'Media Step Backward',
0x00100000d54: 'Media Step Forward',
0x00100000d55: 'Media Top Menu',
0x00100000d56: 'Navigate In',
0x00100000d57: 'Navigate Next',
0x00100000d58: 'Navigate Out',
0x00100000d59: 'Navigate Previous',
0x00100000d5a: 'Pairing',
0x00100000d5b: 'Media Close',
0x00100000e02: 'Audio Bass Boost Toggle',
0x00100000e04: 'Audio Treble Down',
0x00100000e05: 'Audio Treble Up',
0x00100000e06: 'Microphone Toggle',
0x00100000e07: 'Microphone Volume Down',
0x00100000e08: 'Microphone Volume Up',
0x00100000e09: 'Microphone Volume Mute',
0x00100000f01: 'Speech Correction List',
0x00100000f02: 'Speech Input Toggle',
0x00100001001: 'App Switch',
0x00100001002: 'Call',
0x00100001003: 'Camera Focus',
0x00100001004: 'End Call',
0x00100001005: 'Go Back',
0x00100001006: 'Go Home',
0x00100001007: 'Headset Hook',
0x00100001008: 'Last Number Redial',
0x00100001009: 'Notification',
0x0010000100a: 'Manner Mode',
0x0010000100b: 'Voice Dial',
0x00100001101: 'TV 3 D Mode',
0x00100001102: 'TV Antenna Cable',
0x00100001103: 'TV Audio Description',
0x00100001104: 'TV Audio Description Mix Down',
0x00100001105: 'TV Audio Description Mix Up',
0x00100001106: 'TV Contents Menu',
0x00100001107: 'TV Data Service',
0x00100001108: 'TV Input Component 1',
0x00100001109: 'TV Input Component 2',
0x0010000110a: 'TV Input Composite 1',
0x0010000110b: 'TV Input Composite 2',
0x0010000110c: 'TV Input HDMI 1',
0x0010000110d: 'TV Input HDMI 2',
0x0010000110e: 'TV Input HDMI 3',
0x0010000110f: 'TV Input HDMI 4',
0x00100001110: 'TV Input VGA 1',
0x00100001111: 'TV Media Context',
0x00100001112: 'TV Network',
0x00100001113: 'TV Number Entry',
0x00100001114: 'TV Radio Service',
0x00100001115: 'TV Satellite',
0x00100001116: 'TV Satellite BS',
0x00100001117: 'TV Satellite CS',
0x00100001118: 'TV Satellite Toggle',
0x00100001119: 'TV Terrestrial Analog',
0x0010000111a: 'TV Terrestrial Digital',
0x0010000111b: 'TV Timer',
0x00100001201: 'Key 11',
0x00100001202: 'Key 12',
0x00200000000: 'Suspend',
0x00200000001: 'Resume',
0x00200000002: 'VK_SLEEP',
0x00200000003: 'Abort',
0x00200000010: 'Lang 1',
0x00200000011: 'Lang 2',
0x00200000012: 'Lang 3',
0x00200000013: 'Lang 4',
0x00200000014: 'Lang 5',
0x00200000020: 'Intl Backslash',
0x00200000021: 'Intl Ro',
0x00200000022: 'Intl Yen',
0x00200000100: 'VK_CONTROL',
0x00200000101: 'RControl',
0x00200000102: 'VK_SHIFT',
0x00200000103: 'RShift',
0x00200000104: 'VK_MENU',
0x00200000105: 'RAlt',
0x00200000106: 'Meta Left',
0x00200000107: 'Meta Right',
0x002000001f0: 'VK_CONTROL',
0x002000001f2: 'VK_SHIFT',
0x002000001f4: 'VK_MENU',
0x002000001f6: 'Meta',
0x0020000020d: 'Numpad Enter',
0x00200000228: 'Numpad Paren Left',
0x00200000229: 'Numpad Paren Right',
0x0020000022a: 'VK_MULTIPLY',
0x0020000022b: 'VK_ADD',
0x0020000022c: 'Numpad Comma',
0x0020000022d: 'VK_SUBTRACT',
0x0020000022e: 'VK_DECIMAL',
0x0020000022f: 'VK_DIVIDE',
0x00200000230: 'VK_NUMPAD0',
0x00200000231: 'VK_NUMPAD1',
0x00200000232: 'VK_NUMPAD2',
0x00200000233: 'VK_NUMPAD3',
0x00200000234: 'VK_NUMPAD4',
0x00200000235: 'VK_NUMPAD5',
0x00200000236: 'VK_NUMPAD6',
0x00200000237: 'VK_NUMPAD7',
0x00200000238: 'VK_NUMPAD8',
0x00200000239: 'VK_NUMPAD9',
0x0020000023d: 'Numpad Equal',
0x00200000301: 'Game Button 1',
0x00200000302: 'Game Button 2',
0x00200000303: 'Game Button 3',
0x00200000304: 'Game Button 4',
0x00200000305: 'Game Button 5',
0x00200000306: 'Game Button 6',
0x00200000307: 'Game Button 7',
0x00200000308: 'Game Button 8',
0x00200000309: 'Game Button 9',
0x0020000030a: 'Game Button 10',
0x0020000030b: 'Game Button 11',
0x0020000030c: 'Game Button 12',
0x0020000030d: 'Game Button 13',
0x0020000030e: 'Game Button 14',
0x0020000030f: 'Game Button 15',
0x00200000310: 'Game Button 16',
0x00200000311: 'Game Button A',
0x00200000312: 'Game Button B',
0x00200000313: 'Game Button C',
0x00200000314: 'Game Button Left 1',
0x00200000315: 'Game Button Left 2',
0x00200000316: 'Game Button Mode',
0x00200000317: 'Game Button Right 1',
0x00200000318: 'Game Button Right 2',
0x00200000319: 'Game Button Select',
0x0020000031a: 'Game Button Start',
0x0020000031b: 'Game Button Thumb Left',
0x0020000031c: 'Game Button Thumb Right',
0x0020000031d: 'Game Button X',
0x0020000031e: 'Game Button Y',
0x0020000031f: 'Game Button Z',
};

File diff suppressed because one or more lines are too long

View File

@ -33,8 +33,8 @@
<link rel="manifest" href="manifest.json"> <link rel="manifest" href="manifest.json">
<script src="ogvjs-1.8.6/ogv.js"></script> <script src="ogvjs-1.8.6/ogv.js"></script>
<script src="yuv.js"></script> <script src="yuv.js"></script>
<script type="module" crossorigin src="assets/index.67fa1f1d.js"></script> <script type="module" crossorigin src="assets/index.a0538fcc.js"></script>
<link rel="modulepreload" href="assets/vendor.b7bb6fa2.js"> <link rel="modulepreload" href="assets/vendor.32e42528.js">
<script src="yuv-canvas-1.2.6.js"></script> <script src="yuv-canvas-1.2.6.js"></script>
<style> <style>
.loading { .loading {