diff --git a/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.VideoViewer/ViewerPanel.xaml.cs index 6d7c5a489..44501512e 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,9 @@ public ViewerPanel(ContextObject context) }; PreviewMouseWheel += (_, e) => ChangeVolume(e.Delta / 120d * 0.04d); + + Focusable = true; + PreviewKeyDown += ViewerPanel_PreviewKeyDown; } private partial void LoadAndInsertGlassLayer(); @@ -200,17 +203,83 @@ 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) + // 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; + } + + if (wnd != null) + { + var startLeft = wnd.Left; + var startTop = wnd.Top; + + try + { + wnd.DragMove(); + } + catch (InvalidOperationException) + { + // Ignore exception if mouse state changed unexpectedly during drag + } - 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) + { + 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; + } + } + + private void Seek(long deltaTicks) + { + if (mediaElement == null || mediaElement.MediaDuration <= 0) + 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) @@ -402,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