Skip to content
6 changes: 5 additions & 1 deletion QuickLook/KeystrokeDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected KeystrokeDispatcher()
_validKeys =
[
Keys.Up, Keys.Down, Keys.Left, Keys.Right,
Keys.Enter, Keys.Space, Keys.Escape
Keys.Enter, Keys.Space, Keys.Escape, Keys.F11
];
}

Expand Down Expand Up @@ -135,6 +135,10 @@ private void InvokeRoutine(Keys key, bool isKeyDown)
case Keys.Space:
PipeServerManager.SendMessage(PipeMessages.Toggle);
break;

case Keys.F11:
PipeServerManager.SendMessage(PipeMessages.Fullscreen);
break;
}
}
else
Expand Down
7 changes: 7 additions & 0 deletions QuickLook/PipeServerManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public static class PipeMessages
public const string Forget = "QuickLook.App.PipeMessages.Forget";
public const string Close = "QuickLook.App.PipeMessages.Close";
public const string Quit = "QuickLook.App.PipeMessages.Quit";
public const string Fullscreen = "QuickLook.App.PipeMessages.Fullscreen";
}

public class PipeServerManager : IDisposable
Expand Down Expand Up @@ -161,6 +162,12 @@ private bool MessageReceived(string msg)
DispatcherPriority.ApplicationIdle);
return false;

case PipeMessages.Fullscreen:
Application.Current.Dispatcher.BeginInvoke(
new Action(() => ViewWindowManager.GetInstance().ToggleFullscreen()),
DispatcherPriority.ApplicationIdle);
return false;

case PipeMessages.Quit:
return true;

Expand Down
8 changes: 8 additions & 0 deletions QuickLook/ViewWindowManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,14 @@ public void ReloadPreview()
BeginShowNewWindow(_invokedPath, matchedPlugin);
}

public void ToggleFullscreen()
{
if (!_viewerWindow.IsVisible)
return;

_viewerWindow.ToggleFullscreen();
}

private void BeginShowNewWindow(string path, IViewer matchedPlugin)
{
_viewerWindow.UnloadPlugin();
Expand Down
66 changes: 66 additions & 0 deletions QuickLook/ViewerWindow.Actions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
using Wpf.Ui.Controls;
using WinForms = System.Windows.Forms;
using MenuItem = System.Windows.Controls.MenuItem;

namespace QuickLook;
Expand Down Expand Up @@ -62,6 +64,70 @@ internal void RunAndClose()
Close();
}

internal void ToggleFullscreen()
{
if (_isFullscreen)
{
// Exit fullscreen
_isFullscreen = false;

// Restore window properties
WindowStyle = _preFullscreenWindowStyle;
ResizeMode = _preFullscreenResizeMode;

// Restore position and size
Left = _preFullscreenBounds.Left;
Top = _preFullscreenBounds.Top;
Width = _preFullscreenBounds.Width;
Height = _preFullscreenBounds.Height;

// Restore window state last to avoid flicker
WindowState = _preFullscreenWindowState;
}
else
{
// Enter fullscreen
_isFullscreen = true;

// Save current window properties before any changes
_preFullscreenWindowState = WindowState;
_preFullscreenWindowStyle = WindowStyle;
_preFullscreenResizeMode = ResizeMode;

// Get current bounds (account for maximized state)
if (WindowState == WindowState.Maximized)
{
_preFullscreenBounds = RestoreBounds;
}
else
{
_preFullscreenBounds = new Rect(Left, Top, Width, Height);
}

// Get the screen bounds where the window is currently located
var screen = WinForms.Screen.FromHandle(new WindowInteropHelper(this).Handle);
var screenBounds = screen.Bounds;

// Get DPI scale factor for proper coordinate conversion
// scale.Horizontal and scale.Vertical contain the DPI scaling ratios (e.g., 1.5 for 150%)
var scale = DisplayDeviceHelper.GetScaleFactorFromWindow(this);

// Set to normal state first to allow manual positioning
WindowState = WindowState.Normal;

// Hide window chrome for true fullscreen
WindowStyle = WindowStyle.None;
ResizeMode = ResizeMode.NoResize;

// Convert screen bounds from physical pixels to DIPs for WPF
var dipWidth = screenBounds.Width / scale.Horizontal;
var dipHeight = screenBounds.Height / scale.Vertical;

// Use MoveWindow to set position and size with proper DPI handling
this.MoveWindow(screenBounds.Left, screenBounds.Top, dipWidth, dipHeight);
}
}

private void PositionWindow(Size size)
{
// If the window is now maximized, do not move it
Expand Down
5 changes: 5 additions & 0 deletions QuickLook/ViewerWindow.Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,11 @@ public partial class ViewerWindow : INotifyPropertyChanged

private bool _canOldPluginResize;
private bool _pinned;
private bool _isFullscreen;
private WindowState _preFullscreenWindowState;
private WindowStyle _preFullscreenWindowStyle;
private ResizeMode _preFullscreenResizeMode;
private Rect _preFullscreenBounds;

public bool Pinned
{
Expand Down