/ src / settings-ui / Settings.UI / SettingsXAML / MainWindow.xaml.cs
MainWindow.xaml.cs
  1  // Copyright (c) Microsoft Corporation
  2  // The Microsoft Corporation licenses this file to you under the MIT license.
  3  // See the LICENSE file in the project root for more information.
  4  
  5  using System;
  6  using System.Threading.Tasks;
  7  using ManagedCommon;
  8  using Microsoft.PowerLauncher.Telemetry;
  9  using Microsoft.PowerToys.Settings.UI.Helpers;
 10  using Microsoft.PowerToys.Settings.UI.Library;
 11  using Microsoft.PowerToys.Settings.UI.Library.Helpers;
 12  using Microsoft.PowerToys.Settings.UI.Views;
 13  using Microsoft.PowerToys.Telemetry;
 14  using Microsoft.UI;
 15  using Microsoft.UI.Windowing;
 16  using Microsoft.UI.Xaml;
 17  using Windows.Data.Json;
 18  using WinRT.Interop;
 19  using WinUIEx;
 20  
 21  namespace Microsoft.PowerToys.Settings.UI
 22  {
 23      public sealed partial class MainWindow : WindowEx
 24      {
 25          public MainWindow(bool createHidden = false)
 26          {
 27              var bootTime = new System.Diagnostics.Stopwatch();
 28              bootTime.Start();
 29  
 30              this.Activated += Window_Activated_SetIcon;
 31  
 32              App.ThemeService.ThemeChanged += OnThemeChanged;
 33              App.ThemeService.ApplyTheme();
 34  
 35              this.ExtendsContentIntoTitleBar = true;
 36  
 37              ShellPage.SetElevationStatus(App.IsElevated);
 38              ShellPage.SetIsUserAnAdmin(App.IsUserAnAdmin);
 39  
 40              var hWnd = WindowNative.GetWindowHandle(this);
 41              var placement = WindowHelper.DeserializePlacementOrDefault(hWnd);
 42              if (createHidden)
 43              {
 44                  placement.ShowCmd = NativeMethods.SW_HIDE;
 45  
 46                  // Restore the last known placement on the first activation
 47                  this.Activated += Window_Activated;
 48              }
 49  
 50              NativeMethods.SetWindowPlacement(hWnd, ref placement);
 51  
 52              var loader = ResourceLoaderInstance.ResourceLoader;
 53              Title = App.IsElevated ? loader.GetString("SettingsWindow_AdminTitle") : loader.GetString("SettingsWindow_Title");
 54  
 55              // send IPC Message
 56              ShellPage.SetDefaultSndMessageCallback(msg =>
 57              {
 58                  // IPC Manager is null when launching runner directly
 59                  App.GetTwoWayIPCManager()?.Send(msg);
 60              });
 61  
 62              // send IPC Message
 63              ShellPage.SetRestartAdminSndMessageCallback(msg =>
 64              {
 65                  App.GetTwoWayIPCManager()?.Send(msg);
 66                  Environment.Exit(0); // close application
 67              });
 68  
 69              // send IPC Message
 70              ShellPage.SetCheckForUpdatesMessageCallback(msg =>
 71              {
 72                  App.GetTwoWayIPCManager()?.Send(msg);
 73              });
 74  
 75              // open main window
 76              ShellPage.SetOpenMainWindowCallback(type =>
 77              {
 78                  DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
 79                       App.OpenSettingsWindow(type));
 80              });
 81  
 82              // open main window
 83              ShellPage.SetUpdatingGeneralSettingsCallback((ModuleType moduleType, bool isEnabled) =>
 84              {
 85                  SettingsRepository<GeneralSettings> repository = SettingsRepository<GeneralSettings>.GetInstance(SettingsUtils.Default);
 86                  GeneralSettings generalSettingsConfig = repository.SettingsConfig;
 87                  bool needToUpdate = ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, moduleType) != isEnabled;
 88  
 89                  if (needToUpdate)
 90                  {
 91                      ModuleHelper.SetIsModuleEnabled(generalSettingsConfig, moduleType, isEnabled);
 92                      var outgoing = new OutGoingGeneralSettings(generalSettingsConfig);
 93  
 94                      // Save settings to file
 95                      SettingsUtils.Default.SaveSettings(generalSettingsConfig.ToJsonString());
 96  
 97                      // Send IPC message asynchronously to avoid blocking UI and potential recursive calls
 98                      Task.Run(() =>
 99                      {
100                          ShellPage.SendDefaultIPCMessage(outgoing.ToString());
101                      });
102  
103                      ShellPage.ShellHandler?.SignalGeneralDataUpdate();
104                  }
105  
106                  return needToUpdate;
107              });
108  
109              // open oobe
110              ShellPage.SetOpenOobeCallback(() =>
111              {
112                  if (App.GetOobeWindow() == null)
113                  {
114                      App.SetOobeWindow(new OobeWindow(OOBE.Enums.PowerToysModules.Overview));
115                  }
116  
117                  App.GetOobeWindow().Activate();
118              });
119  
120              // open whats new window
121              ShellPage.SetOpenWhatIsNewCallback(() =>
122              {
123                  if (App.GetScoobeWindow() == null)
124                  {
125                      App.SetScoobeWindow(new ScoobeWindow());
126                  }
127  
128                  App.GetScoobeWindow().Activate();
129              });
130  
131              this.InitializeComponent();
132              SetAppTitleBar();
133  
134              // receive IPC Message
135              App.IPCMessageReceivedCallback = (string msg) =>
136              {
137                  if (ShellPage.ShellHandler.IPCResponseHandleList != null)
138                  {
139                      var success = JsonObject.TryParse(msg, out JsonObject json);
140                      if (success)
141                      {
142                          foreach (Action<JsonObject> handle in ShellPage.ShellHandler.IPCResponseHandleList)
143                          {
144                              handle(json);
145                          }
146                      }
147                      else
148                      {
149                          Logger.LogError("Failed to parse JSON from IPC message.");
150                      }
151                  }
152              };
153  
154              bootTime.Stop();
155  
156              PowerToysTelemetry.Log.WriteEvent(new SettingsBootEvent() { BootTimeMs = bootTime.ElapsedMilliseconds });
157          }
158  
159          private void SetAppTitleBar()
160          {
161              // We need to assign the window here so it can configure the custom title bar area correctly.
162              shellPage.TitleBar.Window = this;
163              WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(this));
164          }
165  
166          public void NavigateToSection(System.Type type)
167          {
168              ShellPage.Navigate(type);
169          }
170  
171          public void CloseHiddenWindow()
172          {
173              var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
174              if (!NativeMethods.IsWindowVisible(hWnd))
175              {
176                  Close();
177              }
178          }
179  
180          private void Window_Closed(object sender, WindowEventArgs args)
181          {
182              var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
183              WindowHelper.SerializePlacement(hWnd);
184  
185              if (App.GetOobeWindow() == null && App.GetScoobeWindow() == null)
186              {
187                  App.ClearSettingsWindow();
188              }
189              else
190              {
191                  args.Handled = true;
192                  NativeMethods.ShowWindow(hWnd, NativeMethods.SW_HIDE);
193              }
194  
195              App.ThemeService.ThemeChanged -= OnThemeChanged;
196          }
197  
198          private void Window_Activated_SetIcon(object sender, WindowActivatedEventArgs args)
199          {
200              // Set window icon
201              var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
202              WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd);
203              AppWindow appWindow = AppWindow.GetFromWindowId(windowId);
204              appWindow.SetIcon("Assets\\Settings\\icon.ico");
205          }
206  
207          private void Window_Activated(object sender, WindowActivatedEventArgs args)
208          {
209              if (args.WindowActivationState != WindowActivationState.Deactivated)
210              {
211                  this.Activated -= Window_Activated;
212                  var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
213                  var placement = WindowHelper.DeserializePlacementOrDefault(hWnd);
214                  NativeMethods.SetWindowPlacement(hWnd, ref placement);
215              }
216          }
217  
218          private void OnThemeChanged(object sender, ElementTheme theme)
219          {
220              WindowHelper.SetTheme(this, theme);
221          }
222  
223          internal void EnsurePageIsSelected()
224          {
225              ShellPage.EnsurePageIsSelected();
226          }
227      }
228  }