// 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 System.ComponentModel; using System.Drawing; using System.Windows; using System.Windows.Interop; using Microsoft.PowerLauncher.Telemetry; using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.PowerToys.Settings.UI.Views; using Microsoft.PowerToys.Telemetry; using Microsoft.Toolkit.Wpf.UI.XamlHost; using PowerToys.Settings.Helpers; using Windows.ApplicationModel.Resources; using Windows.Data.Json; namespace PowerToys.Settings { // Interaction logic for MainWindow.xaml. public partial class MainWindow : Window { private static Window inst; private bool isOpen = true; public MainWindow() { var bootTime = new System.Diagnostics.Stopwatch(); bootTime.Start(); this.InitializeComponent(); Utils.FitToScreen(this); ResourceLoader loader = ResourceLoader.GetForViewIndependentUse(); Title = loader.GetString("SettingsWindow_Title"); bootTime.Stop(); PowerToysTelemetry.Log.WriteEvent(new SettingsBootEvent() { BootTimeMs = bootTime.ElapsedMilliseconds }); } public static void CloseHiddenWindow() { if (inst != null && inst.Visibility == Visibility.Hidden) { inst.Close(); } } public void NavigateToSection(Type type) { if (inst != null) { Activate(); ShellPage.Navigate(type); } } protected override void OnSourceInitialized(EventArgs e) { base.OnSourceInitialized(e); var handle = new WindowInteropHelper(this).Handle; NativeMethods.GetWindowPlacement(handle, out var startupPlacement); var placement = Utils.DeserializePlacementOrDefault(handle); NativeMethods.SetWindowPlacement(handle, ref placement); var windowRect = new Rectangle((int)Left, (int)Top, (int)Width, (int)Height); var screenRect = new Rectangle((int)SystemParameters.VirtualScreenLeft, (int)SystemParameters.VirtualScreenTop, (int)SystemParameters.VirtualScreenWidth, (int)SystemParameters.VirtualScreenHeight); var intersection = Rectangle.Intersect(windowRect, screenRect); // Restore default position if 5% of width or height of the window is offscreen if (intersection.Width < (Width * 0.95) || intersection.Height < (Height * 0.95)) { NativeMethods.SetWindowPlacement(handle, ref startupPlacement); } } protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); var handle = new WindowInteropHelper(this).Handle; Utils.SerializePlacement(handle); } private void WindowsXamlHost_ChildChanged(object sender, EventArgs e) { // If sender is null, it could lead to a NullReferenceException. This might occur on restarting as admin (check https://github.com/microsoft/PowerToys/issues/7393 for details) if (sender == null) { return; } // Hook up x:Bind source. WindowsXamlHost windowsXamlHost = sender as WindowsXamlHost; ShellPage shellPage = windowsXamlHost.GetUwpInternalObject() as ShellPage; if (shellPage != null) { // send IPC Message ShellPage.SetDefaultSndMessageCallback(msg => { // IPC Manager is null when launching runner directly Program.GetTwoWayIPCManager()?.Send(msg); }); // send IPC Message ShellPage.SetRestartAdminSndMessageCallback(msg => { Program.GetTwoWayIPCManager()?.Send(msg); isOpen = false; System.Windows.Application.Current.Shutdown(); // close application }); // send IPC Message ShellPage.SetCheckForUpdatesMessageCallback(msg => { Program.GetTwoWayIPCManager()?.Send(msg); }); // open oobe ShellPage.SetOpenOobeCallback(() => { var oobe = new OobeWindow(Microsoft.PowerToys.Settings.UI.OOBE.Enums.PowerToysModulesEnum.Overview); oobe.Show(); }); // receive IPC Message Program.IPCMessageReceivedCallback = (string msg) => { if (ShellPage.ShellHandler.IPCResponseHandleList != null) { var success = JsonObject.TryParse(msg, out JsonObject json); if (success) { foreach (Action handle in ShellPage.ShellHandler.IPCResponseHandleList) { handle(json); } } else { Logger.LogError("Failed to parse JSON from IPC message."); } } }; ShellPage.SetElevationStatus(Program.IsElevated); ShellPage.SetIsUserAnAdmin(Program.IsUserAnAdmin); shellPage.Refresh(); } // XAML Islands: If the window is open, explicitly force it to be shown to solve the blank dialog issue https://github.com/microsoft/PowerToys/issues/3384 if (isOpen) { try { Show(); } catch (InvalidOperationException) { } } } private void MainWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { if (OobeWindow.IsOpened) { e.Cancel = true; ((Window)sender).Hide(); } else { isOpen = false; } // XAML Islands: If the window is closed while minimized, exit the process. Required to avoid process not terminating issue - https://github.com/microsoft/PowerToys/issues/4430 if (WindowState == WindowState.Minimized) { // Run Environment.Exit on a separate task to avoid performance impact System.Threading.Tasks.Task.Run(() => { Environment.Exit(0); }); } } private void MainWindow_Loaded(object sender, RoutedEventArgs e) { inst = (Window)sender; } private void MainWindow_Activated(object sender, EventArgs e) { if (((Window)sender).Visibility == Visibility.Hidden) { ((Window)sender).Visibility = Visibility.Visible; } } } }