mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request SettingsUtils is initialized multiple times over the whole solution. This creates one singeltone instance (with the default settings), so it only has to be initialized once (and improve performance a bit with that) <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: #xxx <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed
260 lines
9.3 KiB
C#
260 lines
9.3 KiB
C#
// Copyright (c) Microsoft Corporation
|
|
// The Microsoft Corporation licenses this file to you under the MIT license.
|
|
// See the LICENSE file in the project root for more information.
|
|
|
|
using System;
|
|
using ManagedCommon;
|
|
using Microsoft.PowerLauncher.Telemetry;
|
|
using Microsoft.PowerToys.Settings.UI.Helpers;
|
|
using Microsoft.PowerToys.Settings.UI.Library;
|
|
using Microsoft.PowerToys.Settings.UI.Views;
|
|
using Microsoft.PowerToys.Telemetry;
|
|
using Microsoft.UI;
|
|
using Microsoft.UI.Windowing;
|
|
using Microsoft.UI.Xaml;
|
|
using Windows.Data.Json;
|
|
using WinRT.Interop;
|
|
using WinUIEx;
|
|
|
|
namespace Microsoft.PowerToys.Settings.UI
|
|
{
|
|
/// <summary>
|
|
/// An empty window that can be used on its own or navigated to within a Frame.
|
|
/// </summary>
|
|
public sealed partial class MainWindow : WindowEx
|
|
{
|
|
public MainWindow(bool createHidden = false)
|
|
{
|
|
var bootTime = new System.Diagnostics.Stopwatch();
|
|
bootTime.Start();
|
|
|
|
this.Activated += Window_Activated_SetIcon;
|
|
|
|
App.ThemeService.ThemeChanged += OnThemeChanged;
|
|
App.ThemeService.ApplyTheme();
|
|
|
|
ShellPage.SetElevationStatus(App.IsElevated);
|
|
ShellPage.SetIsUserAnAdmin(App.IsUserAnAdmin);
|
|
|
|
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
|
var placement = WindowHelper.DeserializePlacementOrDefault(hWnd);
|
|
if (createHidden)
|
|
{
|
|
placement.ShowCmd = NativeMethods.SW_HIDE;
|
|
|
|
// Restore the last known placement on the first activation
|
|
this.Activated += Window_Activated;
|
|
}
|
|
|
|
NativeMethods.SetWindowPlacement(hWnd, ref placement);
|
|
|
|
var loader = ResourceLoaderInstance.ResourceLoader;
|
|
Title = App.IsElevated ? loader.GetString("SettingsWindow_AdminTitle") : loader.GetString("SettingsWindow_Title");
|
|
|
|
// send IPC Message
|
|
ShellPage.SetDefaultSndMessageCallback(msg =>
|
|
{
|
|
// IPC Manager is null when launching runner directly
|
|
App.GetTwoWayIPCManager()?.Send(msg);
|
|
});
|
|
|
|
// send IPC Message
|
|
ShellPage.SetRestartAdminSndMessageCallback(msg =>
|
|
{
|
|
App.GetTwoWayIPCManager()?.Send(msg);
|
|
Environment.Exit(0); // close application
|
|
});
|
|
|
|
// send IPC Message
|
|
ShellPage.SetCheckForUpdatesMessageCallback(msg =>
|
|
{
|
|
App.GetTwoWayIPCManager()?.Send(msg);
|
|
});
|
|
|
|
// open main window
|
|
ShellPage.SetOpenMainWindowCallback(type =>
|
|
{
|
|
DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
|
|
App.OpenSettingsWindow(type));
|
|
});
|
|
|
|
// open main window
|
|
ShellPage.SetUpdatingGeneralSettingsCallback((ModuleType moduleType, bool isEnabled) =>
|
|
{
|
|
SettingsRepository<GeneralSettings> repository = SettingsRepository<GeneralSettings>.GetInstance(SettingsUtils.Default);
|
|
GeneralSettings generalSettingsConfig = repository.SettingsConfig;
|
|
bool needToUpdate = ModuleHelper.GetIsModuleEnabled(generalSettingsConfig, moduleType) != isEnabled;
|
|
|
|
if (needToUpdate)
|
|
{
|
|
ModuleHelper.SetIsModuleEnabled(generalSettingsConfig, moduleType, isEnabled);
|
|
var outgoing = new OutGoingGeneralSettings(generalSettingsConfig);
|
|
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
|
|
{
|
|
ShellPage.SendDefaultIPCMessage(outgoing.ToString());
|
|
ShellPage.ShellHandler?.SignalGeneralDataUpdate();
|
|
});
|
|
}
|
|
|
|
return needToUpdate;
|
|
});
|
|
|
|
// open oobe
|
|
ShellPage.SetOpenOobeCallback(() =>
|
|
{
|
|
if (App.GetOobeWindow() == null)
|
|
{
|
|
App.SetOobeWindow(new OobeWindow(OOBE.Enums.PowerToysModules.Overview));
|
|
}
|
|
|
|
App.GetOobeWindow().Activate();
|
|
});
|
|
|
|
// open whats new window
|
|
ShellPage.SetOpenWhatIsNewCallback(() =>
|
|
{
|
|
if (App.GetOobeWindow() == null)
|
|
{
|
|
App.SetOobeWindow(new OobeWindow(OOBE.Enums.PowerToysModules.WhatsNew));
|
|
}
|
|
else
|
|
{
|
|
App.GetOobeWindow().SetAppWindow(OOBE.Enums.PowerToysModules.WhatsNew);
|
|
}
|
|
|
|
App.GetOobeWindow().Activate();
|
|
});
|
|
|
|
// open flyout
|
|
ShellPage.SetOpenFlyoutCallback((POINT? p) =>
|
|
{
|
|
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
|
|
{
|
|
if (App.GetFlyoutWindow() == null)
|
|
{
|
|
App.SetFlyoutWindow(new FlyoutWindow(p));
|
|
}
|
|
|
|
FlyoutWindow flyout = App.GetFlyoutWindow();
|
|
flyout.FlyoutAppearPosition = p;
|
|
flyout.Activate();
|
|
|
|
// https://github.com/microsoft/microsoft-ui-xaml/issues/7595 - Activate doesn't bring window to the foreground
|
|
// Need to call SetForegroundWindow to actually gain focus.
|
|
WindowHelpers.BringToForeground(flyout.GetWindowHandle());
|
|
});
|
|
});
|
|
|
|
// disable flyout hiding
|
|
ShellPage.SetDisableFlyoutHidingCallback(() =>
|
|
{
|
|
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
|
|
{
|
|
if (App.GetFlyoutWindow() == null)
|
|
{
|
|
App.SetFlyoutWindow(new FlyoutWindow(null));
|
|
}
|
|
|
|
App.GetFlyoutWindow().ViewModel.DisableHiding();
|
|
});
|
|
});
|
|
|
|
this.InitializeComponent();
|
|
SetAppTitleBar();
|
|
|
|
// receive IPC Message
|
|
App.IPCMessageReceivedCallback = (string msg) =>
|
|
{
|
|
if (ShellPage.ShellHandler.IPCResponseHandleList != null)
|
|
{
|
|
var success = JsonObject.TryParse(msg, out JsonObject json);
|
|
if (success)
|
|
{
|
|
foreach (Action<JsonObject> handle in ShellPage.ShellHandler.IPCResponseHandleList)
|
|
{
|
|
handle(json);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Logger.LogError("Failed to parse JSON from IPC message.");
|
|
}
|
|
}
|
|
};
|
|
|
|
bootTime.Stop();
|
|
|
|
PowerToysTelemetry.Log.WriteEvent(new SettingsBootEvent() { BootTimeMs = bootTime.ElapsedMilliseconds });
|
|
}
|
|
|
|
private void SetAppTitleBar()
|
|
{
|
|
// We need to assign the window here so it can configure the custom title bar area correctly.
|
|
shellPage.TitleBar.Window = this;
|
|
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(this));
|
|
}
|
|
|
|
public void NavigateToSection(System.Type type)
|
|
{
|
|
ShellPage.Navigate(type);
|
|
}
|
|
|
|
public void CloseHiddenWindow()
|
|
{
|
|
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
|
if (!NativeMethods.IsWindowVisible(hWnd))
|
|
{
|
|
Close();
|
|
}
|
|
}
|
|
|
|
private void Window_Closed(object sender, WindowEventArgs args)
|
|
{
|
|
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
|
WindowHelper.SerializePlacement(hWnd);
|
|
|
|
if (App.GetOobeWindow() == null)
|
|
{
|
|
App.ClearSettingsWindow();
|
|
}
|
|
else
|
|
{
|
|
args.Handled = true;
|
|
NativeMethods.ShowWindow(hWnd, NativeMethods.SW_HIDE);
|
|
}
|
|
|
|
App.ThemeService.ThemeChanged -= OnThemeChanged;
|
|
}
|
|
|
|
private void Window_Activated_SetIcon(object sender, WindowActivatedEventArgs args)
|
|
{
|
|
// Set window icon
|
|
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
|
WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd);
|
|
AppWindow appWindow = AppWindow.GetFromWindowId(windowId);
|
|
appWindow.SetIcon("Assets\\Settings\\icon.ico");
|
|
}
|
|
|
|
private void Window_Activated(object sender, WindowActivatedEventArgs args)
|
|
{
|
|
if (args.WindowActivationState != WindowActivationState.Deactivated)
|
|
{
|
|
this.Activated -= Window_Activated;
|
|
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
|
var placement = WindowHelper.DeserializePlacementOrDefault(hWnd);
|
|
NativeMethods.SetWindowPlacement(hWnd, ref placement);
|
|
}
|
|
}
|
|
|
|
private void OnThemeChanged(object sender, ElementTheme theme)
|
|
{
|
|
WindowHelper.SetTheme(this, theme);
|
|
}
|
|
|
|
internal void EnsurePageIsSelected()
|
|
{
|
|
ShellPage.EnsurePageIsSelected();
|
|
}
|
|
}
|
|
}
|