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 1/2] 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) From 3d0d3cf8645ae58063997a93f34120c84a7d8ff1 Mon Sep 17 00:00:00 2001 From: Berry Wahlberg <40695099+BerryUIKI@users.noreply.github.com> Date: Sat, 10 Oct 2026 02:56:53 +0800 Subject: [PATCH 2/2] Fix maximized window drag crash, focus handling, and modifier keys in VideoViewer --- .../ViewerPanel.xaml.cs | 29 +++++++++++++++---- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs index ec4de6f56..44501512e 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs @@ -111,7 +111,6 @@ public ViewerPanel(ContextObject context) PreviewMouseWheel += (_, e) => ChangeVolume(e.Delta / 120d * 0.04d); Focusable = true; - Loaded += (_, _) => Focus(); PreviewKeyDown += ViewerPanel_PreviewKeyDown; } @@ -209,8 +208,8 @@ private void Panel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 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) + // Do not allow dragging when window is borderless (e.g. fullscreen) or maximized + if (wnd?.WindowStyle == WindowStyle.None || wnd?.WindowState == WindowState.Maximized) { TogglePlayPause(this, EventArgs.Empty); return; @@ -221,7 +220,14 @@ private void Panel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) var startLeft = wnd.Left; var startTop = wnd.Top; - wnd.DragMove(); + try + { + wnd.DragMove(); + } + catch (InvalidOperationException) + { + // Ignore exception if mouse state changed unexpectedly during drag + } // 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) @@ -234,25 +240,32 @@ private void Panel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) private void ViewerPanel_PreviewKeyDown(object sender, KeyEventArgs e) { + if (Keyboard.Modifiers != ModifierKeys.None) + return; + switch (e.Key) { case Key.Left: Seek(-TimeSpan.FromSeconds(5).Ticks); + ShowViedoControlContainer(null, null); e.Handled = true; break; case Key.Right: Seek(TimeSpan.FromSeconds(5).Ticks); + ShowViedoControlContainer(null, null); e.Handled = true; break; case Key.Up: ChangeVolume(0.05d); + ShowViedoControlContainer(null, null); e.Handled = true; break; case Key.Down: ChangeVolume(-0.05d); + ShowViedoControlContainer(null, null); e.Handled = true; break; } @@ -260,7 +273,7 @@ private void ViewerPanel_PreviewKeyDown(object sender, KeyEventArgs e) private void Seek(long deltaTicks) { - if (mediaElement == null) + if (mediaElement == null || mediaElement.MediaDuration <= 0) return; var target = Math.Max(0, Math.Min(mediaElement.MediaDuration, mediaElement.MediaPosition + deltaTicks)); @@ -458,11 +471,17 @@ public double LinearVolume private void ChangeVolume(double delta) { + if (mediaElement == null) + return; + LinearVolume = Math.Max(0d, Math.Min(1d, LinearVolume + delta)); } private void TogglePlayPause(object sender, EventArgs e) { + if (mediaElement == null) + return; + if (mediaElement.IsPlaying) mediaElement.Pause(); else