From c4a2719332cbdf4a453e970762d030b7defc7ea3 Mon Sep 17 00:00:00 2001 From: Berry Wahlberg <40695099+BerryUIKI@users.noreply.github.com> Date: Fri, 18 Sep 2026 09:38:20 +0800 Subject: [PATCH] Add keyboard navigation shortcuts and click to pause in VideoViewer (#47, #1979, #1753) --- .../ViewerPanel.xaml.cs | 60 ++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs index 6d7c5a489..ec4de6f56 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs @@ -1,4 +1,4 @@ -// Copyright © 2017-2026 QL-Win Contributors +// Copyright © 2017-2026 QL-Win Contributors // // This file is part of QuickLook program. // @@ -109,6 +109,10 @@ public ViewerPanel(ContextObject context) }; PreviewMouseWheel += (_, e) => ChangeVolume(e.Delta / 120d * 0.04d); + + Focusable = true; + Loaded += (_, _) => Focus(); + PreviewKeyDown += ViewerPanel_PreviewKeyDown; } private partial void LoadAndInsertGlassLayer(); @@ -200,17 +204,69 @@ public void Dispose() private void Panel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { + Focus(); + if (e.LeftButton == MouseButtonState.Pressed) { var wnd = Window.GetWindow(this); // Do not allow dragging when window is borderless (e.g. fullscreen) if (wnd?.WindowStyle == WindowStyle.None) + { + TogglePlayPause(this, EventArgs.Empty); return; + } + + if (wnd != null) + { + var startLeft = wnd.Left; + var startTop = wnd.Top; + + wnd.DragMove(); + + // If the window was not moved, treat this interaction as a click to toggle play/pause + if (Math.Abs(wnd.Left - startLeft) < 2 && Math.Abs(wnd.Top - startTop) < 2) + { + TogglePlayPause(this, EventArgs.Empty); + } + } + } + } + + private void ViewerPanel_PreviewKeyDown(object sender, KeyEventArgs e) + { + switch (e.Key) + { + case Key.Left: + Seek(-TimeSpan.FromSeconds(5).Ticks); + e.Handled = true; + break; + + case Key.Right: + Seek(TimeSpan.FromSeconds(5).Ticks); + e.Handled = true; + break; + + case Key.Up: + ChangeVolume(0.05d); + e.Handled = true; + break; - wnd?.DragMove(); + case Key.Down: + ChangeVolume(-0.05d); + e.Handled = true; + break; } } + private void Seek(long deltaTicks) + { + if (mediaElement == null) + return; + + var target = Math.Max(0, Math.Min(mediaElement.MediaDuration, mediaElement.MediaPosition + deltaTicks)); + mediaElement.MediaPosition = target; + } + public event PropertyChangedEventHandler PropertyChanged; private void MediaOpened(object o, RoutedEventArgs args)