From a4a0475fdb9f3ae173444bae7c61c9e83062cbd3 Mon Sep 17 00:00:00 2001 From: edde746 <86283021+edde746@users.noreply.github.com> Date: Sun, 31 May 2026 03:01:14 +0200 Subject: [PATCH] fix(player): let macOS shortcuts pass through close #1206 --- .../video_controls/parts/key_events.dart | 7 ++- .../keyboard_shortcuts_service_test.dart | 57 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/lib/widgets/video_controls/parts/key_events.dart b/lib/widgets/video_controls/parts/key_events.dart index be637b47..c9238b45 100644 --- a/lib/widgets/video_controls/parts/key_events.dart +++ b/lib/widgets/video_controls/parts/key_events.dart @@ -64,6 +64,7 @@ extension _PlexVideoControlsKeyEventMethods on _PlexVideoControlsState { /// Global key event handler for focus-independent shortcuts (desktop only) bool _handleGlobalKeyEvent(KeyEvent event) { if (!mounted) return false; + if (ModalRoute.of(context)?.isCurrent != true) return false; // When an overlay sheet is open (e.g. subtitle search with text fields), // don't consume key events — let text input work normally. @@ -168,7 +169,7 @@ extension _PlexVideoControlsKeyEventMethods on _PlexVideoControlsState { } } - return true; // Consume all events while video player is active + return false; } KeyEventResult _handleControlsKeyEvent(KeyEvent event, bool isMobile) { @@ -290,7 +291,9 @@ extension _PlexVideoControlsKeyEventMethods on _PlexVideoControlsState { } // Pass other events to the keyboard shortcuts service. - if (_keyboardService == null) return KeyEventResult.handled; + if (_keyboardService == null) { + return event.logicalKey.isNavigationKey ? KeyEventResult.handled : KeyEventResult.ignored; + } final result = _keyboardService!.handleVideoPlayerKeyEvent( event, diff --git a/test/services/keyboard_shortcuts_service_test.dart b/test/services/keyboard_shortcuts_service_test.dart index fe36d279..e1edf33e 100644 --- a/test/services/keyboard_shortcuts_service_test.dart +++ b/test/services/keyboard_shortcuts_service_test.dart @@ -222,6 +222,63 @@ void main() { expect(resetCount, 1); }); + testWidgets('command-modified keys are not treated as video hotkeys', (tester) async { + final service = await KeyboardShortcutsService.getInstance(); + addTearDown(service.dispose); + final player = _FakePlayer(); + + await tester.sendKeyDownEvent(LogicalKeyboardKey.metaLeft); + + final commandMResult = service.handleVideoPlayerKeyEvent( + const KeyDownEvent( + physicalKey: PhysicalKeyboardKey.keyM, + logicalKey: LogicalKeyboardKey.keyM, + timeStamp: Duration.zero, + ), + player, + null, + null, + null, + null, + null, + null, + ); + final commandQResult = service.handleVideoPlayerKeyEvent( + const KeyDownEvent( + physicalKey: PhysicalKeyboardKey.keyQ, + logicalKey: LogicalKeyboardKey.keyQ, + timeStamp: Duration(milliseconds: 1), + ), + player, + null, + null, + null, + null, + null, + null, + ); + final commandCommaResult = service.handleVideoPlayerKeyEvent( + const KeyDownEvent( + physicalKey: PhysicalKeyboardKey.comma, + logicalKey: LogicalKeyboardKey.comma, + timeStamp: Duration(milliseconds: 2), + ), + player, + null, + null, + null, + null, + null, + null, + ); + + await tester.sendKeyUpEvent(LogicalKeyboardKey.metaLeft); + + expect(commandMResult, KeyEventResult.ignored); + expect(commandQResult, KeyEventResult.ignored); + expect(commandCommaResult, KeyEventResult.ignored); + }); + test('video zoom scale maps to mpv logarithmic property', () { expect(VideoFilterManager.videoZoomPropertyForScale(1.0), closeTo(0.0, 0.0001)); expect(VideoFilterManager.videoZoomPropertyForScale(2.0), closeTo(1.0, 0.0001));