add propagateEvents arg to ThermionListenerWidget

expose physical/logical key maps
dont await InputHandler.handle - this no longer returns a future
This commit is contained in:
Nick Fisher
2025-06-20 18:36:31 +08:00
parent 355999562f
commit 37c35906d6

View File

@@ -14,12 +14,46 @@ extension OffsetExtension on Offset {
} }
} }
final physicalKeyMap = {
PhysicalKeyboardKey.keyW: PhysicalKey.w,
PhysicalKeyboardKey.keyA: PhysicalKey.a,
PhysicalKeyboardKey.keyS: PhysicalKey.s,
PhysicalKeyboardKey.keyD: PhysicalKey.d,
PhysicalKeyboardKey.escape: PhysicalKey.esc,
PhysicalKeyboardKey.delete: PhysicalKey.del,
PhysicalKeyboardKey.keyG: PhysicalKey.g,
PhysicalKeyboardKey.keyR: PhysicalKey.r,
PhysicalKeyboardKey.keyX: PhysicalKey.x,
PhysicalKeyboardKey.keyY: PhysicalKey.y,
PhysicalKeyboardKey.keyZ: PhysicalKey.z,
PhysicalKeyboardKey.shiftLeft: PhysicalKey.shift,
PhysicalKeyboardKey.space: PhysicalKey.space,
PhysicalKeyboardKey.backquote: PhysicalKey.backtick
};
final logicalKeyMap = {
LogicalKeyboardKey.keyW: LogicalKey.w,
LogicalKeyboardKey.keyA: LogicalKey.a,
LogicalKeyboardKey.keyS: LogicalKey.s,
LogicalKeyboardKey.keyD: LogicalKey.d,
LogicalKeyboardKey.escape: LogicalKey.esc,
LogicalKeyboardKey.delete: LogicalKey.del,
LogicalKeyboardKey.keyG: LogicalKey.g,
LogicalKeyboardKey.keyR: LogicalKey.r,
LogicalKeyboardKey.keyX: LogicalKey.x,
LogicalKeyboardKey.keyY: LogicalKey.y,
LogicalKeyboardKey.keyZ: LogicalKey.z,
LogicalKeyboardKey.shift: LogicalKey.shift,
LogicalKeyboardKey.shiftLeft: LogicalKey.shift,
LogicalKeyboardKey.space: LogicalKey.space,
LogicalKeyboardKey.backquote: LogicalKey.backtick
};
/// ///
/// Forwards cross-platform touch/mouse events to an /// Forwards cross-platform touch/mouse events to an
/// [InputHandler]. /// [InputHandler].
/// ///
class ThermionListenerWidget extends StatefulWidget { class ThermionListenerWidget extends StatefulWidget {
/// The content to display below the gesture detector/listener widget. /// The content to display below the gesture detector/listener widget.
/// This will usually be a ThermionWidget (so you can navigate by directly /// This will usually be a ThermionWidget (so you can navigate by directly
/// interacting with the viewport), but this is not necessary. It is equally /// interacting with the viewport), but this is not necessary. It is equally
@@ -40,12 +74,24 @@ class ThermionListenerWidget extends StatefulWidget {
/// ///
/// ///
/// ///
const ThermionListenerWidget({ final bool addKeyboardListener;
Key? key,
required this.inputHandler, ///
this.focusNode, ///
this.child, ///
}) : super(key: key); final bool propagateEvents;
///
///
///
const ThermionListenerWidget(
{Key? key,
required this.inputHandler,
this.focusNode,
this.child,
this.addKeyboardListener = true,
this.propagateEvents = true})
: super(key: key);
@override @override
State<ThermionListenerWidget> createState() => _ThermionListenerWidgetState(); State<ThermionListenerWidget> createState() => _ThermionListenerWidgetState();
@@ -58,52 +104,37 @@ class _ThermionListenerWidgetState extends State<ThermionListenerWidget> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
HardwareKeyboard.instance.addHandler(_handleKeyEvent); if (widget.addKeyboardListener) {
HardwareKeyboard.instance.addHandler(_handleKeyEvent);
}
} }
final _physicalKeyMap = {
PhysicalKeyboardKey.keyW: PhysicalKey.w,
PhysicalKeyboardKey.keyA: PhysicalKey.a,
PhysicalKeyboardKey.keyS: PhysicalKey.s,
PhysicalKeyboardKey.keyD: PhysicalKey.d,
PhysicalKeyboardKey.escape: PhysicalKey.esc,
PhysicalKeyboardKey.delete: PhysicalKey.del,
PhysicalKeyboardKey.keyG: PhysicalKey.g,
PhysicalKeyboardKey.keyR: PhysicalKey.r,
};
final _logicalKeyMap = {
LogicalKeyboardKey.keyW: LogicalKey.w,
LogicalKeyboardKey.keyA: LogicalKey.a,
LogicalKeyboardKey.keyS: LogicalKey.s,
LogicalKeyboardKey.keyD: LogicalKey.d,
LogicalKeyboardKey.escape: LogicalKey.esc,
LogicalKeyboardKey.delete: LogicalKey.del,
LogicalKeyboardKey.keyG: LogicalKey.g,
LogicalKeyboardKey.keyR: LogicalKey.r,
};
bool _handleKeyEvent(KeyEvent event) { bool _handleKeyEvent(KeyEvent event) {
final physicalKey = _physicalKeyMap[event.physicalKey]; final physicalKey = physicalKeyMap[event.physicalKey];
final logicalKey = _logicalKeyMap[event.logicalKey]; final logicalKey = logicalKeyMap[event.logicalKey];
if (physicalKey == null || logicalKey == null) { if (physicalKey == null || logicalKey == null) {
return false; return false;
} }
if (event is KeyDownEvent || event is KeyRepeatEvent) { if (event is KeyDownEvent || event is KeyRepeatEvent) {
widget.inputHandler.handle(t.KeyEvent(KeyEventType.down, logicalKey, physicalKey)); widget.inputHandler.handle(t.KeyEvent(
KeyEventType.down, logicalKey, physicalKey,
synthesized: event.synthesized));
} else if (event is KeyUpEvent) { } else if (event is KeyUpEvent) {
widget.inputHandler.handle(t.KeyEvent(KeyEventType.up, logicalKey, physicalKey)); widget.inputHandler.handle(t.KeyEvent(
return true; KeyEventType.up, logicalKey, physicalKey,
synthesized: event.synthesized));
} }
return false; return !widget.propagateEvents;
} }
@override @override
void dispose() { void dispose() {
super.dispose(); super.dispose();
HardwareKeyboard.instance.removeHandler(_handleKeyEvent); if (widget.addKeyboardListener) {
HardwareKeyboard.instance.removeHandler(_handleKeyEvent);
}
} }
t.MouseButton? _mouseButtonFromEvent(PointerEvent event) { t.MouseButton? _mouseButtonFromEvent(PointerEvent event) {
@@ -124,7 +155,7 @@ class _ThermionListenerWidgetState extends State<ThermionListenerWidget> {
focusNode: widget.focusNode, focusNode: widget.focusNode,
child: Listener( child: Listener(
onPointerHover: (event) async { onPointerHover: (event) async {
await widget.inputHandler.handle(MouseEvent( widget.inputHandler.handle(MouseEvent(
MouseEventType.hover, MouseEventType.hover,
_mouseButtonFromEvent(event), _mouseButtonFromEvent(event),
event.localPosition.toVector2() * pixelRatio, event.localPosition.toVector2() * pixelRatio,
@@ -132,7 +163,7 @@ class _ThermionListenerWidgetState extends State<ThermionListenerWidget> {
}, },
onPointerSignal: (PointerSignalEvent pointerSignal) async { onPointerSignal: (PointerSignalEvent pointerSignal) async {
if (pointerSignal is PointerScrollEvent) { if (pointerSignal is PointerScrollEvent) {
await widget.inputHandler.handle(ScrollEvent( widget.inputHandler.handle(ScrollEvent(
localPosition: localPosition:
pointerSignal.localPosition.toVector2() * pixelRatio, pointerSignal.localPosition.toVector2() * pixelRatio,
delta: pointerSignal.scrollDelta.dy * pixelRatio)); delta: pointerSignal.scrollDelta.dy * pixelRatio));
@@ -144,7 +175,7 @@ class _ThermionListenerWidgetState extends State<ThermionListenerWidget> {
onPointerDown: (event) async { onPointerDown: (event) async {
widget.focusNode?.requestFocus(); widget.focusNode?.requestFocus();
await widget.inputHandler.handle(MouseEvent( widget.inputHandler.handle(MouseEvent(
MouseEventType.buttonDown, MouseEventType.buttonDown,
_mouseButtonFromEvent(event), _mouseButtonFromEvent(event),
event.localPosition.toVector2() * pixelRatio, event.localPosition.toVector2() * pixelRatio,
@@ -239,7 +270,7 @@ class _MobileListenerWidgetState extends State<_MobileListenerWidget> {
)); ));
}, },
onScaleEnd: (details) async { onScaleEnd: (details) async {
await widget.inputHandler widget.inputHandler
.handle(ScaleEndEvent(numPointers: details.pointerCount)); .handle(ScaleEndEvent(numPointers: details.pointerCount));
}, },
child: widget.child); child: widget.child);