Skip to content

Commit acbde61

Browse files
authored
Add F11 fullscreen toggle support (#1879)
1 parent ae67d52 commit acbde61

5 files changed

Lines changed: 91 additions & 1 deletion

File tree

QuickLook/KeystrokeDispatcher.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected KeystrokeDispatcher()
4646
_validKeys =
4747
[
4848
Keys.Up, Keys.Down, Keys.Left, Keys.Right,
49-
Keys.Enter, Keys.Space, Keys.Escape
49+
Keys.Enter, Keys.Space, Keys.Escape, Keys.F11
5050
];
5151
}
5252

@@ -135,6 +135,10 @@ private void InvokeRoutine(Keys key, bool isKeyDown)
135135
case Keys.Space:
136136
PipeServerManager.SendMessage(PipeMessages.Toggle);
137137
break;
138+
139+
case Keys.F11:
140+
PipeServerManager.SendMessage(PipeMessages.Fullscreen);
141+
break;
138142
}
139143
}
140144
else

QuickLook/PipeServerManager.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public static class PipeMessages
3636
public const string Forget = "QuickLook.App.PipeMessages.Forget";
3737
public const string Close = "QuickLook.App.PipeMessages.Close";
3838
public const string Quit = "QuickLook.App.PipeMessages.Quit";
39+
public const string Fullscreen = "QuickLook.App.PipeMessages.Fullscreen";
3940
}
4041

4142
public class PipeServerManager : IDisposable
@@ -161,6 +162,12 @@ private bool MessageReceived(string msg)
161162
DispatcherPriority.ApplicationIdle);
162163
return false;
163164

165+
case PipeMessages.Fullscreen:
166+
Application.Current.Dispatcher.BeginInvoke(
167+
new Action(() => ViewWindowManager.GetInstance().ToggleFullscreen()),
168+
DispatcherPriority.ApplicationIdle);
169+
return false;
170+
164171
case PipeMessages.Quit:
165172
return true;
166173

QuickLook/ViewWindowManager.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,14 @@ public void ReloadPreview()
198198
BeginShowNewWindow(_invokedPath, matchedPlugin);
199199
}
200200

201+
public void ToggleFullscreen()
202+
{
203+
if (!_viewerWindow.IsVisible)
204+
return;
205+
206+
_viewerWindow.ToggleFullscreen();
207+
}
208+
201209
private void BeginShowNewWindow(string path, IViewer matchedPlugin)
202210
{
203211
_viewerWindow.UnloadPlugin();

QuickLook/ViewerWindow.Actions.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,11 @@
2929
using System.Windows;
3030
using System.Windows.Controls;
3131
using System.Windows.Input;
32+
using System.Windows.Interop;
3233
using System.Windows.Media;
3334
using System.Windows.Threading;
3435
using Wpf.Ui.Controls;
36+
using WinForms = System.Windows.Forms;
3537
using MenuItem = System.Windows.Controls.MenuItem;
3638

3739
namespace QuickLook;
@@ -62,6 +64,70 @@ internal void RunAndClose()
6264
Close();
6365
}
6466

67+
internal void ToggleFullscreen()
68+
{
69+
if (_isFullscreen)
70+
{
71+
// Exit fullscreen
72+
_isFullscreen = false;
73+
74+
// Restore window properties
75+
WindowStyle = _preFullscreenWindowStyle;
76+
ResizeMode = _preFullscreenResizeMode;
77+
78+
// Restore position and size
79+
Left = _preFullscreenBounds.Left;
80+
Top = _preFullscreenBounds.Top;
81+
Width = _preFullscreenBounds.Width;
82+
Height = _preFullscreenBounds.Height;
83+
84+
// Restore window state last to avoid flicker
85+
WindowState = _preFullscreenWindowState;
86+
}
87+
else
88+
{
89+
// Enter fullscreen
90+
_isFullscreen = true;
91+
92+
// Save current window properties before any changes
93+
_preFullscreenWindowState = WindowState;
94+
_preFullscreenWindowStyle = WindowStyle;
95+
_preFullscreenResizeMode = ResizeMode;
96+
97+
// Get current bounds (account for maximized state)
98+
if (WindowState == WindowState.Maximized)
99+
{
100+
_preFullscreenBounds = RestoreBounds;
101+
}
102+
else
103+
{
104+
_preFullscreenBounds = new Rect(Left, Top, Width, Height);
105+
}
106+
107+
// Get the screen bounds where the window is currently located
108+
var screen = WinForms.Screen.FromHandle(new WindowInteropHelper(this).Handle);
109+
var screenBounds = screen.Bounds;
110+
111+
// Get DPI scale factor for proper coordinate conversion
112+
// scale.Horizontal and scale.Vertical contain the DPI scaling ratios (e.g., 1.5 for 150%)
113+
var scale = DisplayDeviceHelper.GetScaleFactorFromWindow(this);
114+
115+
// Set to normal state first to allow manual positioning
116+
WindowState = WindowState.Normal;
117+
118+
// Hide window chrome for true fullscreen
119+
WindowStyle = WindowStyle.None;
120+
ResizeMode = ResizeMode.NoResize;
121+
122+
// Convert screen bounds from physical pixels to DIPs for WPF
123+
var dipWidth = screenBounds.Width / scale.Horizontal;
124+
var dipHeight = screenBounds.Height / scale.Vertical;
125+
126+
// Use MoveWindow to set position and size with proper DPI handling
127+
this.MoveWindow(screenBounds.Left, screenBounds.Top, dipWidth, dipHeight);
128+
}
129+
}
130+
65131
private void PositionWindow(Size size)
66132
{
67133
// If the window is now maximized, do not move it

QuickLook/ViewerWindow.Properties.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ public partial class ViewerWindow : INotifyPropertyChanged
3737

3838
private bool _canOldPluginResize;
3939
private bool _pinned;
40+
private bool _isFullscreen;
41+
private WindowState _preFullscreenWindowState;
42+
private WindowStyle _preFullscreenWindowStyle;
43+
private ResizeMode _preFullscreenResizeMode;
44+
private Rect _preFullscreenBounds;
4045

4146
public bool Pinned
4247
{

0 commit comments

Comments
 (0)