master
cs 170 lines 5.78 KB
Raw
1 // Copyright (C) Microsoft Corporation. All rights reserved.
2
3 using Microsoft.UI.Windowing;
4 using Microsoft.UI.Xaml;
5 using Microsoft.UI.Xaml.Input;
6 using System.Runtime.InteropServices;
7 using Windows.Graphics;
8 using Windows.System;
9 using WinUIEx.Messaging;
10 using Windows.UI.ViewManagement;
11 using Windows.UI.WindowManagement;
12 using System.Runtime.Intrinsics.Arm;
13
14 namespace WslSettings;
15
16 /// <summary>
17 /// An empty window that can be used on its own or navigated to within a Frame.
18 /// </summary>
19 public sealed partial class OOBEWindow : WindowEx, IDisposable
20 {
21 [DllImport("User32.dll")]
22 internal static extern int GetDpiForWindow(IntPtr hwnd);
23
24 private const int ExpectedWidth = 1100;
25 private const int ExpectedHeight = 700;
26 private const int DefaultDPI = 96;
27 private int currentDPI;
28 private IntPtr hWnd;
29 private Microsoft.UI.Dispatching.DispatcherQueue dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
30 private UISettings settings = new UISettings();
31 private WindowMessageMonitor msgMonitor;
32 private bool disposedValue;
33
34 public OOBEWindow()
35 {
36 InitializeComponent();
37
38 AppWindow.SetIcon(Path.Combine(AppContext.BaseDirectory, "Assets/wsl.ico"));
39 Content = null;
40 Title = "Settings_OOBEDisplayName".GetLocalized();
41
42 // Theme change code picked from https://github.com/microsoft/WinUI-Gallery/pull/1239
43 settings.ColorValuesChanged += Settings_ColorValuesChanged; // cannot use FrameworkElement.ActualThemeChanged event
44 settings.TextScaleFactorChanged += Settings_TextScaleFactorChanged;
45
46 WindowManager.Get(this).IsMinimizable = false;
47 WindowManager.Get(this).IsMaximizable = false;
48
49 hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
50 currentDPI = GetDpiForWindow(hWnd);
51 ResizeWindow();
52
53 SizeChanged += Window_SizeChanged;
54
55 msgMonitor = new WindowMessageMonitor(this);
56 msgMonitor.WindowMessageReceived += (_, e) =>
57 {
58 const int WM_NCLBUTTONDBLCLK = 0x00A3;
59 if (e.Message.MessageId == WM_NCLBUTTONDBLCLK)
60 {
61 // Disable double click on title bar to maximize window
62 e.Result = 0;
63 e.Handled = true;
64 }
65 };
66
67 this.Activated += OnWindowActivated;
68 }
69
70 // this handles updating the caption button colors correctly when windows system theme is changed
71 // while the app is open
72 private void Settings_ColorValuesChanged(UISettings sender, object args)
73 {
74 // This calls comes off-thread, hence we will need to dispatch it to current app's thread
75 dispatcherQueue.TryEnqueue(() =>
76 {
77 TitleBarHelper.ApplySystemThemeToCaptionButtons(this);
78 });
79 }
80
81 // This handles text scaling changes for accessibility
82 private void Settings_TextScaleFactorChanged(UISettings sender, object args)
83 {
84 // This calls comes off-thread, hence we will need to dispatch it to current app's thread
85 dispatcherQueue.TryEnqueue(() =>
86 {
87 ResizeWindow();
88 });
89 }
90
91 private void Window_SizeChanged(object sender, WindowSizeChangedEventArgs args)
92 {
93 var dpi = GetDpiForWindow(hWnd);
94 if (currentDPI != dpi)
95 {
96 // Reacting to a DPI change. Should not cause a resize -> sizeChanged loop.
97 currentDPI = dpi;
98 ResizeWindow();
99 }
100 }
101
102 private void Window_Closed(object sender, WindowEventArgs args)
103 {
104 App.OOBEWindow = null;
105 App.MainWindow?.CloseHiddenWindow();
106 Dispose();
107 }
108
109 private void ResizeWindow()
110 {
111 float dpiScalingFactor = (float)currentDPI / DefaultDPI;
112 float textScalingFactor = (float)settings.TextScaleFactor;
113
114 // Combine DPI scaling and text scaling for accessibility
115 float combinedScalingFactor = dpiScalingFactor * textScalingFactor;
116
117 int width = (int)(ExpectedWidth * combinedScalingFactor);
118 int height = (int)(ExpectedHeight * combinedScalingFactor);
119
120 SizeInt32 size;
121 size.Width = width;
122 size.Height = height;
123 AppWindow.Resize(size);
124 }
125
126 private void Dispose(bool disposing)
127 {
128 if (!disposedValue)
129 {
130 msgMonitor?.Dispose();
131 settings.ColorValuesChanged -= Settings_ColorValuesChanged;
132 settings.TextScaleFactorChanged -= Settings_TextScaleFactorChanged;
133 this.Activated -= OnWindowActivated;
134 if (this.Content is Microsoft.UI.Xaml.Controls.Page page)
135 {
136 page.KeyboardAccelerators.Clear();
137 }
138
139 disposedValue = true;
140 }
141 }
142
143 public void Dispose()
144 {
145 // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
146 Dispose(disposing: true);
147 GC.SuppressFinalize(this);
148 }
149
150 private void OnWindowActivated(object sender, WindowActivatedEventArgs args)
151 {
152 if (args.WindowActivationState != WindowActivationState.Deactivated && this.Content != null)
153 {
154 this.Activated -= OnWindowActivated;
155
156 if (this.Content is Microsoft.UI.Xaml.Controls.Page page)
157 {
158 var escapeAccelerator = new KeyboardAccelerator() { Key = VirtualKey.Escape };
159 escapeAccelerator.Invoked += OnCloseKeyboardAcceleratorInvoked;
160 page.KeyboardAccelerators.Add(escapeAccelerator);
161 }
162 }
163 }
164
165 private void OnCloseKeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
166 {
167 Close();
168 args.Handled = true;
169 }
170 }