77 lines
3.3 KiB
Dart
77 lines
3.3 KiB
Dart
import 'package:flutter/scheduler.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:flutter/widgets.dart';
|
|
|
|
/// Shared utility for simulating key press events through the focus tree.
|
|
///
|
|
/// Used by both [CompanionRemoteReceiver] and [GamepadService] to translate
|
|
/// external input (remote commands, gamepad buttons) into focus-tree key events.
|
|
void simulateKeyPress(LogicalKeyboardKey logicalKey) {
|
|
SchedulerBinding.instance.addPostFrameCallback((_) {
|
|
final focusNode = FocusManager.instance.primaryFocus;
|
|
if (focusNode == null) return;
|
|
|
|
final physicalKey = _getPhysicalKey(logicalKey);
|
|
|
|
final keyDownEvent = KeyDownEvent(
|
|
physicalKey: physicalKey,
|
|
logicalKey: logicalKey,
|
|
timeStamp: Duration(milliseconds: DateTime.now().millisecondsSinceEpoch),
|
|
);
|
|
|
|
// Walk up the focus tree dispatching the key event
|
|
FocusNode? node = focusNode;
|
|
KeyEventResult result = KeyEventResult.ignored;
|
|
|
|
while (node != null && result != KeyEventResult.handled) {
|
|
if (node.onKeyEvent != null) {
|
|
result = node.onKeyEvent!(node, keyDownEvent);
|
|
}
|
|
node = node.parent;
|
|
}
|
|
|
|
// Send key up event
|
|
final keyUpEvent = KeyUpEvent(
|
|
physicalKey: physicalKey,
|
|
logicalKey: logicalKey,
|
|
timeStamp: Duration(milliseconds: DateTime.now().millisecondsSinceEpoch),
|
|
);
|
|
|
|
node = focusNode;
|
|
while (node != null) {
|
|
if (node.onKeyEvent != null) {
|
|
final upResult = node.onKeyEvent!(node, keyUpEvent);
|
|
if (upResult == KeyEventResult.handled) break;
|
|
}
|
|
node = node.parent;
|
|
}
|
|
});
|
|
}
|
|
|
|
/// Force a frame when the engine is idle so focus visuals update immediately
|
|
/// on external input (desktop may not wake up without mouse/keyboard activity).
|
|
void scheduleFrameIfIdle() {
|
|
if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.idle) {
|
|
SchedulerBinding.instance.scheduleFrame();
|
|
}
|
|
}
|
|
|
|
PhysicalKeyboardKey _getPhysicalKey(LogicalKeyboardKey logicalKey) {
|
|
if (logicalKey == LogicalKeyboardKey.arrowUp) return PhysicalKeyboardKey.arrowUp;
|
|
if (logicalKey == LogicalKeyboardKey.arrowDown) return PhysicalKeyboardKey.arrowDown;
|
|
if (logicalKey == LogicalKeyboardKey.arrowLeft) return PhysicalKeyboardKey.arrowLeft;
|
|
if (logicalKey == LogicalKeyboardKey.arrowRight) return PhysicalKeyboardKey.arrowRight;
|
|
if (logicalKey == LogicalKeyboardKey.enter) return PhysicalKeyboardKey.enter;
|
|
if (logicalKey == LogicalKeyboardKey.escape) return PhysicalKeyboardKey.escape;
|
|
if (logicalKey == LogicalKeyboardKey.space) return PhysicalKeyboardKey.space;
|
|
if (logicalKey == LogicalKeyboardKey.contextMenu) return PhysicalKeyboardKey.contextMenu;
|
|
if (logicalKey == LogicalKeyboardKey.audioVolumeUp) return PhysicalKeyboardKey.audioVolumeUp;
|
|
if (logicalKey == LogicalKeyboardKey.audioVolumeDown) return PhysicalKeyboardKey.audioVolumeDown;
|
|
if (logicalKey == LogicalKeyboardKey.audioVolumeMute) return PhysicalKeyboardKey.audioVolumeMute;
|
|
if (logicalKey == LogicalKeyboardKey.keyF) return PhysicalKeyboardKey.keyF;
|
|
if (logicalKey == LogicalKeyboardKey.gameButtonA) return PhysicalKeyboardKey.gameButtonA;
|
|
if (logicalKey == LogicalKeyboardKey.gameButtonB) return PhysicalKeyboardKey.gameButtonB;
|
|
if (logicalKey == LogicalKeyboardKey.gameButtonX) return PhysicalKeyboardKey.gameButtonX;
|
|
return PhysicalKeyboardKey.enter;
|
|
}
|