fix(tv): back button Menu on Siri Remote

This commit is contained in:
edde746
2026-05-12 22:46:38 +02:00
parent de62c8530f
commit b0f1a5d4f1
3 changed files with 25 additions and 6 deletions
+18 -4
View File
@@ -62,10 +62,18 @@ KeyEventResult handleBackKeyAction(KeyEvent event, VoidCallback onBack) {
return KeyEventResult.handled;
}
if (PlatformDetector.isAppleTV() && event.isPhysicalKeyboardEvent && event is KeyDownEvent) {
BackKeyCoordinator.markHandled();
BackKeyUpSuppressor.suppressBackUntilKeyUp();
onBack();
// AppleTV physical-keyboard back (Siri Remote Menu via engine-synthesized
// escape): run onBack on KeyDown only; consume KeyUp silently. The
// suppressor-based "arm-on-KeyDown, clear-on-KeyUp" pattern leaks here
// because onBack typically calls Navigator.pop, swapping the focus tree
// before the matching KeyUp is dispatched — the orphaned KeyUp then never
// reaches a consumeIfSuppressed call, pinning the suppressor armed and
// silently swallowing the next press's KeyDown.
if (PlatformDetector.isAppleTV() && event.isPhysicalKeyboardEvent) {
if (event is KeyDownEvent) {
BackKeyCoordinator.markHandled();
onBack();
}
return KeyEventResult.handled;
}
@@ -174,6 +182,12 @@ FocusOnKeyEventCallback dpadKeyHandler({
class BackKeySuppressorObserver extends NavigatorObserver {
@override
void didPop(Route route, Route? previousRoute) {
// On AppleTV, handleBackKeyAction consumes the KeyUp silently regardless,
// so the suppressor isn't needed and arming it would pin state across the
// pop's focus-tree swap. (The atomic engine fix delivers KeyDown+KeyUp in
// a single recognizer Began callback, so didPop fires squarely inside the
// window where BackKeyPressTracker.isBackKeyDown is true.)
if (PlatformDetector.isAppleTV()) return;
if (BackKeyPressTracker.isBackKeyDown) {
BackKeyUpSuppressor.suppressBackUntilKeyUp();
}
+6 -1
View File
@@ -954,14 +954,19 @@ class _MainScreenState extends State<MainScreen>
return KeyEventResult.handled;
}
// AppleTV: KeyDown does the work, KeyUp is consumed silently. See the
// matching comment in handleBackKeyAction for why the suppressor pattern
// doesn't fit here.
if (PlatformDetector.isAppleTV() && event is KeyDownEvent) {
final result = _handleMainBack(allowTvSystemExit: true);
if (result == KeyEventResult.handled) {
BackKeyCoordinator.markHandled();
BackKeyUpSuppressor.suppressBackUntilKeyUp();
}
return result;
}
if (PlatformDetector.isAppleTV() && event is KeyUpEvent) {
return KeyEventResult.handled;
}
if (event is KeyUpEvent) {
final result = _handleMainBack(allowTvSystemExit: PlatformDetector.isAppleTV());