Skip to content

Commit 7d08bc8

Browse files
feat: fullscreen mode
1 parent 5ce798b commit 7d08bc8

3 files changed

Lines changed: 71 additions & 5 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,5 +169,7 @@ Here is an example changing `MainLayout.razor`:
169169
}
170170
```
171171

172+
To support fullscreen mode, you should also hide your custom window chrome when in fullscreen. You can check the current fullscreen status using the `IsFullscreen` property on the window. You can also monitor for it changing using the `OnFullscreenChanged` event.
173+
172174
## Issues
173175
Under the hood, Blazor Desktop uses WebView2 which has limitations right now with composition. Due to this, if you disable the window border through the `Window.UseFrame(false)` API, the top edge of the window is unusable as a resizing zone for the window. However all the other corners and edges work.

src/BlazorDesktop/Services/BlazorDesktopService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Extension Contributors licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using BlazorDesktop.Wpf;
56
using System.Diagnostics.CodeAnalysis;
67
using System.Reflection;
78
using System.Windows;
@@ -68,7 +69,7 @@ public Task StopAsync(CancellationToken cancellationToken)
6869
private void ApplicationThread()
6970
{
7071
var app = _services.GetRequiredService<Application>();
71-
var mainWindow = _services.GetRequiredService<Window>();
72+
var mainWindow = _services.GetRequiredService<BlazorDesktopWindow>();
7273

7374
app.Startup += OnApplicationStartup;
7475
app.Exit += OnApplicationExit;

src/BlazorDesktop/Wpf/BlazorDesktopWindow.cs

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Runtime.InteropServices;
77
using System.Windows;
88
using System.Windows.Controls;
9+
using System.Windows.Input;
910
using System.Windows.Interop;
1011
using System.Windows.Media;
1112
using System.Windows.Media.Imaging;
@@ -32,6 +33,18 @@ public partial class BlazorDesktopWindow : Window
3233
/// </summary>
3334
public Border WebViewBorder { get; }
3435

36+
/// <summary>
37+
/// If the window is fullscreen.
38+
/// </summary>
39+
public bool IsFullscreen => _fullscreen && WindowState == WindowState.Normal;
40+
41+
/// <summary>
42+
/// Occurs when <see cref="IsFullscreen"/> changes.
43+
/// </summary>
44+
public event EventHandler<bool>? OnFullscreenChanged;
45+
46+
private bool _fullscreen;
47+
private WindowState _fullscreenStoredState = WindowState.Normal;
3548
private readonly IServiceProvider _services;
3649
private readonly IConfiguration _config;
3750
private readonly IWebHostEnvironment _environment;
@@ -73,6 +86,40 @@ public BlazorDesktopWindow(IServiceProvider services, IConfiguration config, IWe
7386
InitializeTheming();
7487
}
7588

89+
/// <summary>
90+
/// Toggles fullscreen mode.
91+
/// </summary>
92+
public void ToggleFullScreen()
93+
{
94+
if (WindowStyle == WindowStyle.SingleBorderWindow)
95+
{
96+
_fullscreen = true;
97+
_fullscreenStoredState = WindowState;
98+
99+
UseFrame(_config.GetValue<bool?>(WindowDefaults.Frame) ?? true, _fullscreen);
100+
WindowStyle = WindowStyle.None;
101+
102+
if (WindowState == WindowState.Maximized)
103+
{
104+
WindowState = WindowState.Normal;
105+
}
106+
107+
WindowState = WindowState.Maximized;
108+
109+
OnFullscreenChanged?.Invoke(this, IsFullscreen);
110+
}
111+
else
112+
{
113+
_fullscreen = false;
114+
115+
UseFrame(_config.GetValue<bool?>(WindowDefaults.Frame) ?? true, _fullscreen);
116+
WindowStyle = WindowStyle.SingleBorderWindow;
117+
WindowState = _fullscreenStoredState;
118+
119+
OnFullscreenChanged?.Invoke(this, IsFullscreen);
120+
}
121+
}
122+
76123
private void InitializeWindow()
77124
{
78125
var height = _config.GetValue<int?>(WindowDefaults.Height) ?? 768;
@@ -143,11 +190,12 @@ private void InitializeWindow()
143190
MinWidth = minWidth;
144191
MaxHeight = maxHeight;
145192
MaxWidth = maxWidth;
146-
UseFrame(useFrame);
193+
UseFrame(useFrame, _fullscreen);
147194
ResizeMode = (_config.GetValue<bool?>(WindowDefaults.Resizable) ?? true) ? ResizeMode.CanResize : ResizeMode.NoResize;
148195
UseIcon(_config.GetValue<string?>(WindowDefaults.Icon) ?? string.Empty);
149196
Content = WebViewBorder;
150197
StateChanged += WindowStateChanged;
198+
KeyDown += WindowKeyDown;
151199
}
152200

153201
private void InitializeWebViewBorder()
@@ -188,6 +236,14 @@ private void WindowStateChanged(object? sender, EventArgs e)
188236
UpdateWebViewBorderThickness();
189237
}
190238

239+
private void WindowKeyDown(object sender, KeyEventArgs e)
240+
{
241+
if (e.Key == Key.F11)
242+
{
243+
ToggleFullScreen();
244+
}
245+
}
246+
191247
private void WindowSourceInitialized(object? sender, EventArgs e)
192248
{
193249
UpdateTheme();
@@ -204,7 +260,7 @@ private void UpdateWebViewBorderThickness()
204260

205261
WebViewBorder.BorderThickness = new Thickness(20, 20, 20, 20);
206262

207-
if (WindowState == WindowState.Maximized && !useFrame)
263+
if (WindowState == WindowState.Maximized && !useFrame && !_fullscreen)
208264
{
209265
WebViewBorder.BorderThickness = new Thickness(8, 8, 8, 8);
210266
}
@@ -232,11 +288,18 @@ private void UpdateTheme()
232288
}
233289
}
234290

235-
private void UseFrame(bool frame)
291+
private void UseFrame(bool frame, bool fullscreen)
236292
{
237293
if (!frame)
238294
{
239-
WindowChrome.SetWindowChrome(this, new() { NonClientFrameEdges = NonClientFrameEdges.Bottom | NonClientFrameEdges.Left | NonClientFrameEdges.Right });
295+
if (fullscreen)
296+
{
297+
WindowChrome.SetWindowChrome(this, new() { NonClientFrameEdges = NonClientFrameEdges.None });
298+
}
299+
else
300+
{
301+
WindowChrome.SetWindowChrome(this, new() { NonClientFrameEdges = NonClientFrameEdges.Bottom | NonClientFrameEdges.Left | NonClientFrameEdges.Right });
302+
}
240303
}
241304
}
242305

0 commit comments

Comments
 (0)