mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-11 13:49:54 +01:00
Compare commits
5 Commits
async-cpp-
...
shawn/Sett
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47dbb44a2c | ||
|
|
ba1b97951c | ||
|
|
ad4a5cdfe7 | ||
|
|
58f9b007a6 | ||
|
|
1c538a781f |
@@ -16,8 +16,8 @@ namespace ManagedCommon
|
||||
{
|
||||
public static void WaitForPowerToysRunner(int powerToysPID, Action act, [System.Runtime.CompilerServices.CallerMemberName] string memberName = "")
|
||||
{
|
||||
var stackTrace = new StackTrace();
|
||||
var assembly = Assembly.GetCallingAssembly().GetName();
|
||||
// AOT-compatible: Use GetExecutingAssembly instead of GetCallingAssembly (not supported in AOT)
|
||||
var assembly = Assembly.GetExecutingAssembly().GetName();
|
||||
PowerToysTelemetry.Log.WriteEvent(new DebugEvent() { Message = $"[{assembly}][{memberName}]WaitForPowerToysRunner waiting for Event powerToysPID={powerToysPID}" });
|
||||
Task.Run(() =>
|
||||
{
|
||||
|
||||
@@ -216,7 +216,7 @@ namespace Microsoft.PowerToys.UITest
|
||||
Rectangle bounds = new Rectangle(0, 0, screenWidth, screenHeight);
|
||||
using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height, PixelFormat.Format24bppRgb))
|
||||
{
|
||||
using (Graphics g = Graphics.FromImage(bitmap))
|
||||
using (System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap))
|
||||
{
|
||||
g.CopyFromScreen(bounds.Location, Point.Empty, bounds.Size);
|
||||
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
<OutputType>Library</OutputType>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<PublishAot>true</PublishAot>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
<!-- UITestAutomation is a test library and should not use AOT -->
|
||||
<PublishAot>false</PublishAot>
|
||||
<InvariantGlobalization>false</InvariantGlobalization>
|
||||
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<PublishTrimmed>false</PublishTrimmed>
|
||||
<!-- Suppress code analysis warnings for test library -->
|
||||
<NoWarn>$(NoWarn);CA1305;CA1310;CA2101</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -19,6 +22,7 @@
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
<PackageReference Include="System.Text.RegularExpressions" />
|
||||
<PackageReference Include="CoenM.ImageSharp.ImageHash" />
|
||||
<PackageReference Include="System.Drawing.Common" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -62,11 +62,12 @@
|
||||
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Only enable Native AOT for Release builds to avoid System.Private.CoreLib.dll version conflicts during development -->
|
||||
<!-- Temporarily disable Native AOT until C++ Desktop Development workload is installed -->
|
||||
<!-- TODO: Re-enable after installing Desktop Development for C++ in Visual Studio -->
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<PublishSingleFile>true</PublishSingleFile>
|
||||
<PublishAot>true</PublishAot>
|
||||
<PublishTrimmed>false</PublishTrimmed>
|
||||
<PublishSingleFile>false</PublishSingleFile>
|
||||
<PublishAot>false</PublishAot>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- For Debug builds, use standard JIT compilation -->
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="$(RepoRoot)src\Common.SelfContained.props" />
|
||||
|
||||
<!-- Force WebView2 to use Win32/WinForms mode instead of WinRT mode -->
|
||||
<!-- Required because Settings.UI.Library has UseWinUI=true which triggers WebView2UseWinRT -->
|
||||
<PropertyGroup>
|
||||
<WebView2UseWinRT>false</WebView2UseWinRT>
|
||||
<WebView2EnableCsWinRTProjection>false</WebView2EnableCsWinRTProjection>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
|
||||
@@ -3,6 +3,13 @@
|
||||
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="$(RepoRoot)src\Common.SelfContained.props" />
|
||||
|
||||
<!-- Force WebView2 to use Win32/WinForms mode instead of WinRT mode -->
|
||||
<!-- Required because Settings.UI.Library has UseWinUI=true which triggers WebView2UseWinRT -->
|
||||
<PropertyGroup>
|
||||
<WebView2UseWinRT>false</WebView2UseWinRT>
|
||||
<WebView2EnableCsWinRTProjection>false</WebView2EnableCsWinRTProjection>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
|
||||
@@ -2,6 +2,12 @@
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
|
||||
|
||||
<!-- Force WebView2 to use Win32/WinForms mode for unit tests -->
|
||||
<PropertyGroup>
|
||||
<WebView2UseWinRT>false</WebView2UseWinRT>
|
||||
<WebView2EnableCsWinRTProjection>false</WebView2EnableCsWinRTProjection>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<AssemblyTitle>UnitTests-SvgPreviewHandler</AssemblyTitle>
|
||||
<AssemblyDescription>PowerToys UnitTests-SvgPreviewHandler</AssemblyDescription>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
using System; // For Action
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// 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.Windows.Input;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
<DataTemplate x:DataType="local:QuickAccessItem">
|
||||
<local:FlyoutMenuButton
|
||||
AutomationProperties.Name="{x:Bind Title}"
|
||||
Command="{x:Bind Command}"
|
||||
CommandParameter="{x:Bind CommandParameter}"
|
||||
Click="FlyoutMenuButton_Click"
|
||||
Tag="{x:Bind}"
|
||||
Visibility="{x:Bind Visible, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<local:FlyoutMenuButton.Content>
|
||||
<TextBlock
|
||||
|
||||
@@ -22,5 +22,13 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(object), typeof(QuickAccessList), new PropertyMetadata(null));
|
||||
|
||||
private void FlyoutMenuButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button && button.Tag is QuickAccessItem item)
|
||||
{
|
||||
item.Command?.Execute(item.CommandParameter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,21 +3,58 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library.HotkeyConflicts
|
||||
{
|
||||
public class HotkeyConflictGroupData
|
||||
public partial class HotkeyConflictGroupData : INotifyPropertyChanged
|
||||
{
|
||||
private bool _conflictIgnored;
|
||||
private bool _isSystemConflict;
|
||||
|
||||
public HotkeyData Hotkey { get; set; }
|
||||
|
||||
public bool IsSystemConflict { get; set; }
|
||||
public bool IsSystemConflict
|
||||
{
|
||||
get => _isSystemConflict;
|
||||
set
|
||||
{
|
||||
if (_isSystemConflict != value)
|
||||
{
|
||||
_isSystemConflict = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ShouldShowSysConflict));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ConflictIgnored { get; set; }
|
||||
public bool ConflictIgnored
|
||||
{
|
||||
get => _conflictIgnored;
|
||||
set
|
||||
{
|
||||
if (_conflictIgnored != value)
|
||||
{
|
||||
_conflictIgnored = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ConflictVisible));
|
||||
OnPropertyChanged(nameof(ShouldShowSysConflict));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ConflictVisible => !ConflictIgnored;
|
||||
|
||||
public bool ShouldShowSysConflict => !ConflictIgnored && IsSystemConflict;
|
||||
|
||||
public List<ModuleHotkeyData> Modules { get; set; }
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
src/settings-ui/Settings.UI.Library/ICommand.cs
Normal file
14
src/settings-ui/Settings.UI.Library/ICommand.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
{
|
||||
/// <summary>
|
||||
/// ICommand interface for WinUI 3 applications, compatible with Native AOT.
|
||||
/// Extends System.Windows.Input.ICommand which is also recognized by WinUI3 XAML bindings.
|
||||
/// </summary>
|
||||
public interface ICommand : System.Windows.Input.ICommand
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ using System.Management;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Windows.Input;
|
||||
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
<PropertyGroup>
|
||||
<Description>PowerToys Settings UI Library</Description>
|
||||
<AssemblyName>PowerToys.Settings.UI.Lib</AssemblyName>
|
||||
<!-- Enable WinUI to access Microsoft.UI.Xaml.Input.ICommand for AOT-compatible command binding -->
|
||||
<UseWinUI>true</UseWinUI>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -15,6 +17,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.IO.Abstractions" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -153,6 +153,11 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
[JsonSerializable(typeof(List<VcpValueInfo>))]
|
||||
[JsonSerializable(typeof(SettingsUILibraryHelpers.SearchLocation))]
|
||||
|
||||
// Search Index Types (for AOT compatibility)
|
||||
[JsonSerializable(typeof(SettingsUILibrary.SettingEntry))]
|
||||
[JsonSerializable(typeof(SettingsUILibrary.SettingEntry[]))]
|
||||
[JsonSerializable(typeof(SettingsUILibrary.EntryType))]
|
||||
|
||||
// AdvancedPaste AI Provider Types (for AOT compatibility)
|
||||
[JsonSerializable(typeof(PasteAIConfiguration))]
|
||||
[JsonSerializable(typeof(PasteAIProviderDefinition))]
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands
|
||||
{
|
||||
|
||||
@@ -2,32 +2,36 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands
|
||||
{
|
||||
public class RelayCommand : ICommand
|
||||
// Preserve for AOT - ensure command execution methods are not trimmed
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class RelayCommand : Microsoft.PowerToys.Settings.UI.Library.ICommand
|
||||
{
|
||||
private readonly Action _execute;
|
||||
private readonly Func<bool> _canExecute;
|
||||
private readonly Func<bool>? _canExecute;
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
public RelayCommand(Action execute)
|
||||
: this(execute, null)
|
||||
{
|
||||
}
|
||||
|
||||
public RelayCommand(Action execute, Func<bool> canExecute)
|
||||
public RelayCommand(Action execute, Func<bool>? canExecute)
|
||||
{
|
||||
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public bool CanExecute(object parameter) => _canExecute == null || _canExecute();
|
||||
public bool CanExecute(object? parameter) => _canExecute == null || _canExecute();
|
||||
|
||||
public void Execute(object parameter) => _execute();
|
||||
public void Execute(object? parameter) => _execute();
|
||||
|
||||
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
@@ -2,33 +2,47 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands
|
||||
{
|
||||
public class RelayCommand<T> : ICommand
|
||||
// Preserve for AOT - ensure command execution methods are not trimmed
|
||||
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.PublicProperties)]
|
||||
public class RelayCommand<T> : Microsoft.PowerToys.Settings.UI.Library.ICommand
|
||||
{
|
||||
private readonly Action<T> execute;
|
||||
|
||||
private readonly Func<T, bool> canExecute;
|
||||
private readonly Func<T, bool>? canExecute;
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
public RelayCommand(Action<T> execute)
|
||||
: this(execute, null)
|
||||
{
|
||||
}
|
||||
|
||||
public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
|
||||
public RelayCommand(Action<T> execute, Func<T, bool>? canExecute)
|
||||
{
|
||||
this.execute = execute ?? throw new ArgumentNullException(nameof(execute));
|
||||
this.canExecute = canExecute;
|
||||
}
|
||||
|
||||
public bool CanExecute(object parameter) => canExecute == null || canExecute((T)parameter);
|
||||
public bool CanExecute(object? parameter)
|
||||
{
|
||||
// AOT-friendly: no reflection, just direct cast
|
||||
// The null-forgiving operator is safe here because we're just checking CanExecute
|
||||
return canExecute == null || canExecute((T)parameter!);
|
||||
}
|
||||
|
||||
public void Execute(object parameter) => execute((T)parameter);
|
||||
public void Execute(object? parameter)
|
||||
{
|
||||
// AOT-friendly: simple cast, no reflection or type checking
|
||||
// This matches the original main branch behavior exactly
|
||||
execute((T)parameter!);
|
||||
}
|
||||
|
||||
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
@@ -30,7 +29,7 @@ public sealed partial class ImageResizerFitToStringConverter : IValueConverter
|
||||
fitText;
|
||||
}
|
||||
|
||||
return DependencyProperty.UnsetValue;
|
||||
return Microsoft.UI.Xaml.DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
@@ -38,7 +37,7 @@ public sealed partial class ImageResizerSizeToAccessibleTextConverter : IValueCo
|
||||
{
|
||||
(string presetName, string nameId) => FormatNameText(presetName, nameId),
|
||||
(ImageSize preset, string _) => FormatDescriptionText(preset),
|
||||
_ => DependencyProperty.UnsetValue,
|
||||
_ => Microsoft.UI.Xaml.DependencyProperty.UnsetValue,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,14 +45,14 @@ public sealed partial class ImageResizerSizeToAccessibleTextConverter : IValueCo
|
||||
{
|
||||
return AccessibilityFormats.TryGetValue(nameId, out string format) ?
|
||||
string.Format(CultureInfo.CurrentCulture, format, presetName) :
|
||||
DependencyProperty.UnsetValue;
|
||||
Microsoft.UI.Xaml.DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
private object FormatDescriptionText(ImageSize preset)
|
||||
{
|
||||
if (preset == null)
|
||||
{
|
||||
return DependencyProperty.UnsetValue;
|
||||
return Microsoft.UI.Xaml.DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
string fitText = _fitConverter.Convert(preset.Fit, typeof(string), null, null) as string;
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
@@ -31,7 +30,7 @@ public sealed partial class ImageResizerUnitToStringConverter : IValueConverter
|
||||
unitText;
|
||||
}
|
||||
|
||||
return DependencyProperty.UnsetValue;
|
||||
return Microsoft.UI.Xaml.DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace Microsoft.PowerToys.Settings.UI.Converters
|
||||
}
|
||||
else
|
||||
{
|
||||
return (Microsoft.UI.Xaml.Controls.InfoBarSeverity)Enum.Parse(typeof(Microsoft.UI.Xaml.Controls.InfoBarSeverity), (string)value, true);
|
||||
// Use generic overload for AOT compatibility (IL2026)
|
||||
return Enum.Parse<Microsoft.UI.Xaml.Controls.InfoBarSeverity>((string)value, ignoreCase: true);
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -2,34 +2,35 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
{
|
||||
internal sealed partial class AsyncCommand : ICommand
|
||||
internal sealed partial class AsyncCommand : Microsoft.PowerToys.Settings.UI.Library.ICommand
|
||||
{
|
||||
private readonly Func<Task> _execute;
|
||||
private readonly Func<bool> _canExecute;
|
||||
private readonly Func<bool>? _canExecute;
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
public AsyncCommand(Func<Task> execute, Func<bool> canExecute = null)
|
||||
public AsyncCommand(Func<Task> execute, Func<bool>? canExecute = null)
|
||||
{
|
||||
_execute = execute;
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public bool CanExecute(object parameter)
|
||||
public bool CanExecute(object? parameter)
|
||||
{
|
||||
return _canExecute == null || _canExecute();
|
||||
}
|
||||
|
||||
public async void Execute(object parameter)
|
||||
public async void Execute(object? parameter)
|
||||
{
|
||||
await _execute();
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public class CHOOSEFONT
|
||||
{
|
||||
public int lStructSize = Marshal.SizeOf(typeof(CHOOSEFONT));
|
||||
// Use generic overload for AOT compatibility (IL3050)
|
||||
public int lStructSize = Marshal.SizeOf<CHOOSEFONT>();
|
||||
public IntPtr hwndOwner = IntPtr.Zero;
|
||||
public IntPtr hDC = IntPtr.Zero;
|
||||
public IntPtr lpLogFont = IntPtr.Zero;
|
||||
|
||||
@@ -2,59 +2,60 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
{
|
||||
public partial class RelayCommand : ICommand
|
||||
public partial class RelayCommand : Microsoft.PowerToys.Settings.UI.Library.ICommand
|
||||
{
|
||||
private readonly Action _execute;
|
||||
private readonly Func<bool> _canExecute;
|
||||
private readonly Func<bool>? _canExecute;
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
public RelayCommand(Action execute)
|
||||
: this(execute, null)
|
||||
{
|
||||
}
|
||||
|
||||
public RelayCommand(Action execute, Func<bool> canExecute)
|
||||
public RelayCommand(Action execute, Func<bool>? canExecute)
|
||||
{
|
||||
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public bool CanExecute(object parameter) => _canExecute == null || _canExecute();
|
||||
public bool CanExecute(object? parameter) => _canExecute == null || _canExecute();
|
||||
|
||||
public void Execute(object parameter) => _execute();
|
||||
public void Execute(object? parameter) => _execute();
|
||||
|
||||
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "abstract T and abstract")]
|
||||
public partial class RelayCommand<T> : ICommand
|
||||
public partial class RelayCommand<T> : Microsoft.PowerToys.Settings.UI.Library.ICommand
|
||||
{
|
||||
private readonly Action<T> execute;
|
||||
|
||||
private readonly Func<T, bool> canExecute;
|
||||
private readonly Func<T, bool>? canExecute;
|
||||
|
||||
public event EventHandler CanExecuteChanged;
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
public RelayCommand(Action<T> execute)
|
||||
: this(execute, null)
|
||||
{
|
||||
}
|
||||
|
||||
public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
|
||||
public RelayCommand(Action<T> execute, Func<T, bool>? canExecute)
|
||||
{
|
||||
this.execute = execute ?? throw new ArgumentNullException(nameof(execute));
|
||||
this.canExecute = canExecute;
|
||||
}
|
||||
|
||||
public bool CanExecute(object parameter) => canExecute == null || canExecute((T)parameter);
|
||||
public bool CanExecute(object? parameter) => canExecute == null || canExecute((T)parameter!);
|
||||
|
||||
public void Execute(object parameter) => execute((T)parameter);
|
||||
public void Execute(object? parameter) => execute((T)parameter!);
|
||||
|
||||
public void OnCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
161
src/settings-ui/Settings.UI/Helpers/SettingsDeepLink.cs
Normal file
161
src/settings-ui/Settings.UI/Helpers/SettingsDeepLink.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
// 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.
|
||||
|
||||
// This is a local copy of Common.UI.SettingsDeepLink for AOT compatibility.
|
||||
// Common.UI cannot be referenced in AOT builds because it depends on WPF.
|
||||
#if BUILD_INFO_PUBLISH_AOT
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using ManagedCommon;
|
||||
|
||||
namespace Common.UI
|
||||
{
|
||||
public static class SettingsDeepLink
|
||||
{
|
||||
public enum SettingsWindow
|
||||
{
|
||||
Dashboard = 0,
|
||||
Overview,
|
||||
AlwaysOnTop,
|
||||
Awake,
|
||||
ColorPicker,
|
||||
CmdNotFound,
|
||||
LightSwitch,
|
||||
FancyZones,
|
||||
FileLocksmith,
|
||||
Run,
|
||||
ImageResizer,
|
||||
KBM,
|
||||
MouseUtils,
|
||||
MouseWithoutBorders,
|
||||
Peek,
|
||||
PowerAccent,
|
||||
PowerLauncher,
|
||||
PowerPreview,
|
||||
PowerRename,
|
||||
FileExplorer,
|
||||
ShortcutGuide,
|
||||
Hosts,
|
||||
MeasureTool,
|
||||
PowerOCR,
|
||||
Workspaces,
|
||||
RegistryPreview,
|
||||
CropAndLock,
|
||||
EnvironmentVariables,
|
||||
AdvancedPaste,
|
||||
NewPlus,
|
||||
CmdPal,
|
||||
ZoomIt,
|
||||
PowerDisplay,
|
||||
}
|
||||
|
||||
private static string SettingsWindowNameToString(SettingsWindow value)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case SettingsWindow.Dashboard:
|
||||
return "Dashboard";
|
||||
case SettingsWindow.Overview:
|
||||
return "Overview";
|
||||
case SettingsWindow.AlwaysOnTop:
|
||||
return "AlwaysOnTop";
|
||||
case SettingsWindow.Awake:
|
||||
return "Awake";
|
||||
case SettingsWindow.ColorPicker:
|
||||
return "ColorPicker";
|
||||
case SettingsWindow.CmdNotFound:
|
||||
return "CmdNotFound";
|
||||
case SettingsWindow.LightSwitch:
|
||||
return "LightSwitch";
|
||||
case SettingsWindow.FancyZones:
|
||||
return "FancyZones";
|
||||
case SettingsWindow.FileLocksmith:
|
||||
return "FileLocksmith";
|
||||
case SettingsWindow.Run:
|
||||
return "Run";
|
||||
case SettingsWindow.ImageResizer:
|
||||
return "ImageResizer";
|
||||
case SettingsWindow.KBM:
|
||||
return "KBM";
|
||||
case SettingsWindow.MouseUtils:
|
||||
return "MouseUtils";
|
||||
case SettingsWindow.MouseWithoutBorders:
|
||||
return "MouseWithoutBorders";
|
||||
case SettingsWindow.Peek:
|
||||
return "Peek";
|
||||
case SettingsWindow.PowerAccent:
|
||||
return "PowerAccent";
|
||||
case SettingsWindow.PowerLauncher:
|
||||
return "PowerLauncher";
|
||||
case SettingsWindow.PowerPreview:
|
||||
return "PowerPreview";
|
||||
case SettingsWindow.PowerRename:
|
||||
return "PowerRename";
|
||||
case SettingsWindow.FileExplorer:
|
||||
return "FileExplorer";
|
||||
case SettingsWindow.ShortcutGuide:
|
||||
return "ShortcutGuide";
|
||||
case SettingsWindow.Hosts:
|
||||
return "Hosts";
|
||||
case SettingsWindow.MeasureTool:
|
||||
return "MeasureTool";
|
||||
case SettingsWindow.PowerOCR:
|
||||
return "PowerOcr";
|
||||
case SettingsWindow.Workspaces:
|
||||
return "Workspaces";
|
||||
case SettingsWindow.RegistryPreview:
|
||||
return "RegistryPreview";
|
||||
case SettingsWindow.CropAndLock:
|
||||
return "CropAndLock";
|
||||
case SettingsWindow.EnvironmentVariables:
|
||||
return "EnvironmentVariables";
|
||||
case SettingsWindow.AdvancedPaste:
|
||||
return "AdvancedPaste";
|
||||
case SettingsWindow.NewPlus:
|
||||
return "NewPlus";
|
||||
case SettingsWindow.CmdPal:
|
||||
return "CmdPal";
|
||||
case SettingsWindow.ZoomIt:
|
||||
return "ZoomIt";
|
||||
case SettingsWindow.PowerDisplay:
|
||||
return "PowerDisplay";
|
||||
default:
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OpenSettings(SettingsWindow window)
|
||||
{
|
||||
try
|
||||
{
|
||||
var exePath = Path.Combine(
|
||||
PowerToysPathResolver.GetPowerToysInstallPath(),
|
||||
"PowerToys.exe");
|
||||
|
||||
if (exePath == null || !File.Exists(exePath))
|
||||
{
|
||||
Logger.LogError($"Failed to find powertoys exe path, {exePath}");
|
||||
return;
|
||||
}
|
||||
|
||||
var args = "--open-settings=" + SettingsWindowNameToString(window);
|
||||
|
||||
Process.Start(new ProcessStartInfo
|
||||
{
|
||||
FileName = exePath,
|
||||
Arguments = args,
|
||||
UseShellExecute = false,
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6,8 +6,9 @@ using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Windows.Management.Deployment;
|
||||
using Windows.System;
|
||||
|
||||
@@ -16,7 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
||||
/// <summary>
|
||||
/// Helper class to manage installation status and installation command for a Microsoft Store extension.
|
||||
/// </summary>
|
||||
public class StoreExtensionHelper : INotifyPropertyChanged
|
||||
public partial class StoreExtensionHelper : INotifyPropertyChanged
|
||||
{
|
||||
private readonly string _packageFamilyName;
|
||||
private readonly string _storeUri;
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="$(RepoRoot)src\Common.Dotnet.AotCompatibility.props" />
|
||||
<Import Project="$(RepoRoot)src\Common.SelfContained.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>Microsoft.PowerToys.Settings.UI</RootNamespace>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<PublishProfile>win-$(Platform).pubxml</PublishProfile>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
<WindowsPackageType>None</WindowsPackageType>
|
||||
@@ -19,6 +21,25 @@
|
||||
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
|
||||
<ProjectPriFileName>PowerToys.Settings.pri</ProjectPriFileName>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- For debugging purposes, uncomment this block to enable AOT builds -->
|
||||
<PropertyGroup>
|
||||
<EnableSettingsAOT>true</EnableSettingsAOT>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(EnableSettingsAOT)' == 'true'">
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>false</PublishSingleFile>
|
||||
<DisableRuntimeMarshalling>false</DisableRuntimeMarshalling>
|
||||
<PublishAot>true</PublishAot>
|
||||
<!-- Use environmental tools to bypass VS version detection issue with VS 2026 -->
|
||||
<IlcUseEnvironmentalTools>true</IlcUseEnvironmentalTools>
|
||||
<!-- Trim is mandatory for AOT, but disable reflection removal to preserve WPF compatibility -->
|
||||
<IlcDisableReflection>false</IlcDisableReflection>
|
||||
<!-- Suppress trim/AOT warnings from third-party assemblies and XAML Command binding type checks -->
|
||||
<NoWarn>$(NoWarn);IL2026;IL2060;IL2070;IL2071;IL2072;IL2075;IL2076;IL2104;IL3000;IL3002;IL3050;IL3053;WMC1121</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Assets\Settings\Icons\Models\Azure.svg" />
|
||||
<None Remove="Assets\Settings\Icons\Models\FoundryLocal.svg" />
|
||||
@@ -62,6 +83,14 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Navigation Icons - PNG files (required for AOT publish) -->
|
||||
<Content Include="Assets\Settings\Icons\*.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<!-- Module Images - PNG files (required for AOT publish) -->
|
||||
<Content Include="Assets\Settings\Modules\*.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<!-- AI Model Provider Icons - SVG files -->
|
||||
<Content Include="Assets\Settings\Icons\Models\*.svg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
@@ -114,7 +143,7 @@
|
||||
<ItemGroup>
|
||||
<!-- HACK: Common.UI is referenced, even if it is not used, to force dll versions to be the same as in other projects that use it. It's still unclear why this is the case, but this is need for flattening the install directory. -->
|
||||
<ProjectReference Include="..\..\common\Common.Search\Common.Search.csproj" />
|
||||
<ProjectReference Include="..\..\common\Common.UI\Common.UI.csproj" />
|
||||
<ProjectReference Condition="'$(EnableSettingsAOT)' != 'true'" Include="..\..\common\Common.UI\Common.UI.csproj" />
|
||||
<ProjectReference Include="..\..\common\AllExperiments\AllExperiments.csproj" />
|
||||
<ProjectReference Include="..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
|
||||
<ProjectReference Include="..\..\common\interop\PowerToys.Interop.vcxproj" />
|
||||
@@ -139,7 +168,7 @@
|
||||
<!-- TODO: fix issues and reenable -->
|
||||
<!-- These are caused by streamjsonrpc dependency on Microsoft.VisualStudio.Threading.Analyzers -->
|
||||
<!-- We might want to add that to the project and fix the issues as well -->
|
||||
<NoWarn>VSTHRD002;VSTHRD110;VSTHRD100;VSTHRD200;VSTHRD101</NoWarn>
|
||||
<NoWarn>$(NoWarn);VSTHRD002;VSTHRD110;VSTHRD100;VSTHRD200;VSTHRD101</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Removed hard-coded resource exclusion. -->
|
||||
@@ -219,4 +248,15 @@
|
||||
<Message Importance="high" Text="[Settings] Building XamlIndexBuilder prior to compile. Views='$(MSBuildProjectDirectory)\SettingsXAML\Views' Out='$(GeneratedJsonFile)'" />
|
||||
<MSBuild Projects="..\Settings.UI.XamlIndexBuilder\Settings.UI.XamlIndexBuilder.csproj" Targets="Build" Properties="Configuration=$(Configuration);Platform=Any CPU;TargetFramework=net9.0;XamlViewsDir=$(MSBuildProjectDirectory)\SettingsXAML\Views;GeneratedJsonFile=$(GeneratedJsonFile)" />
|
||||
</Target>
|
||||
|
||||
<!-- Build information for AOT -->
|
||||
<PropertyGroup Condition=" '$(PublishAot)' == 'true' ">
|
||||
<DefineConstants>$(DefineConstants);BUILD_INFO_PUBLISH_AOT</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(PublishTrimmed)' == 'true' ">
|
||||
<DefineConstants>$(DefineConstants);BUILD_INFO_PUBLISH_TRIMMED</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(CIBuild)' == 'true' ">
|
||||
<DefineConstants>$(DefineConstants);BUILD_INFO_CIBUILD</DefineConstants>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -17,6 +17,7 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Common.Search.FuzzSearch;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Views;
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
using Settings.UI.Library;
|
||||
@@ -33,7 +34,6 @@ namespace Microsoft.PowerToys.Settings.UI.Services
|
||||
private static bool _isIndexBuilt;
|
||||
private static bool _isIndexBuilding;
|
||||
private const string PrebuiltIndexResourceName = "Microsoft.PowerToys.Settings.UI.Assets.search.index.json";
|
||||
private static JsonSerializerOptions _serializerOptions = new() { PropertyNameCaseInsensitive = true };
|
||||
|
||||
public static ImmutableArray<SettingEntry> Index
|
||||
{
|
||||
@@ -121,7 +121,8 @@ namespace Microsoft.PowerToys.Settings.UI.Services
|
||||
return;
|
||||
}
|
||||
|
||||
metadataList = JsonSerializer.Deserialize<SettingEntry[]>(json, _serializerOptions);
|
||||
// Use source-generated deserializer for AOT compatibility (IL2026/IL3050)
|
||||
metadataList = JsonSerializer.Deserialize(json, SettingsSerializationContext.Default.SettingEntryArray);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -262,6 +263,7 @@ namespace Microsoft.PowerToys.Settings.UI.Services
|
||||
.ToList();
|
||||
}
|
||||
|
||||
// AOT-compatible type lookup using switch expression instead of reflection (IL2026)
|
||||
private static Type GetPageTypeFromName(string pageTypeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pageTypeName))
|
||||
@@ -276,8 +278,43 @@ namespace Microsoft.PowerToys.Settings.UI.Services
|
||||
return cached;
|
||||
}
|
||||
|
||||
var assembly = typeof(GeneralPage).Assembly;
|
||||
var type = assembly.GetType($"Microsoft.PowerToys.Settings.UI.Views.{pageTypeName}");
|
||||
// Use compile-time known types instead of Assembly.GetType for AOT compatibility
|
||||
var type = pageTypeName switch
|
||||
{
|
||||
nameof(DashboardPage) => typeof(DashboardPage),
|
||||
nameof(GeneralPage) => typeof(GeneralPage),
|
||||
nameof(AdvancedPastePage) => typeof(AdvancedPastePage),
|
||||
nameof(AlwaysOnTopPage) => typeof(AlwaysOnTopPage),
|
||||
nameof(AwakePage) => typeof(AwakePage),
|
||||
nameof(CmdNotFoundPage) => typeof(CmdNotFoundPage),
|
||||
nameof(CmdPalPage) => typeof(CmdPalPage),
|
||||
nameof(ColorPickerPage) => typeof(ColorPickerPage),
|
||||
nameof(CropAndLockPage) => typeof(CropAndLockPage),
|
||||
nameof(EnvironmentVariablesPage) => typeof(EnvironmentVariablesPage),
|
||||
nameof(FancyZonesPage) => typeof(FancyZonesPage),
|
||||
nameof(FileLocksmithPage) => typeof(FileLocksmithPage),
|
||||
nameof(HostsPage) => typeof(HostsPage),
|
||||
nameof(ImageResizerPage) => typeof(ImageResizerPage),
|
||||
nameof(KeyboardManagerPage) => typeof(KeyboardManagerPage),
|
||||
nameof(LightSwitchPage) => typeof(LightSwitchPage),
|
||||
nameof(MeasureToolPage) => typeof(MeasureToolPage),
|
||||
nameof(MouseUtilsPage) => typeof(MouseUtilsPage),
|
||||
nameof(MouseWithoutBordersPage) => typeof(MouseWithoutBordersPage),
|
||||
nameof(NewPlusPage) => typeof(NewPlusPage),
|
||||
nameof(PeekPage) => typeof(PeekPage),
|
||||
nameof(PowerAccentPage) => typeof(PowerAccentPage),
|
||||
nameof(PowerLauncherPage) => typeof(PowerLauncherPage),
|
||||
nameof(PowerOcrPage) => typeof(PowerOcrPage),
|
||||
nameof(PowerPreviewPage) => typeof(PowerPreviewPage),
|
||||
nameof(PowerRenamePage) => typeof(PowerRenamePage),
|
||||
nameof(PowerDisplayPage) => typeof(PowerDisplayPage),
|
||||
nameof(RegistryPreviewPage) => typeof(RegistryPreviewPage),
|
||||
nameof(ShortcutGuidePage) => typeof(ShortcutGuidePage),
|
||||
nameof(WorkspacesPage) => typeof(WorkspacesPage),
|
||||
nameof(ZoomItPage) => typeof(ZoomItPage),
|
||||
_ => null,
|
||||
};
|
||||
|
||||
_pageTypeCache[pageTypeName] = type;
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Security.Cryptography;
|
||||
using System.Windows.Input;
|
||||
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// 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.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Services;
|
||||
using Microsoft.PowerToys.Settings.UI.Views;
|
||||
@@ -9,11 +11,36 @@ using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public sealed partial class CheckUpdateControl : UserControl
|
||||
public sealed partial class CheckUpdateControl : UserControl, INotifyPropertyChanged
|
||||
{
|
||||
public bool UpdateAvailable { get; set; }
|
||||
private bool _updateAvailable;
|
||||
private UpdatingSettings _updateSettingsConfig;
|
||||
|
||||
public UpdatingSettings UpdateSettingsConfig { get; set; }
|
||||
public bool UpdateAvailable
|
||||
{
|
||||
get => _updateAvailable;
|
||||
set
|
||||
{
|
||||
if (_updateAvailable != value)
|
||||
{
|
||||
_updateAvailable = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UpdatingSettings UpdateSettingsConfig
|
||||
{
|
||||
get => _updateSettingsConfig;
|
||||
set
|
||||
{
|
||||
if (_updateSettingsConfig != value)
|
||||
{
|
||||
_updateSettingsConfig = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public CheckUpdateControl()
|
||||
{
|
||||
@@ -26,5 +53,12 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
NavigationService.Navigate(typeof(GeneralPage));
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +230,8 @@ namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
|
||||
NavigationViewItem selectedItem = this.navigationView.SelectedItem as NavigationViewItem;
|
||||
if (selectedItem != null)
|
||||
{
|
||||
Modules[(int)(PowerToysModules)Enum.Parse(typeof(PowerToysModules), (string)selectedItem.Tag, true)].LogClosingModuleEvent();
|
||||
// Use generic overload for AOT compatibility (IL2026)
|
||||
Modules[(int)Enum.Parse<PowerToysModules>((string)selectedItem.Tag, ignoreCase: true)].LogClosingModuleEvent();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
using LanguageModelProvider;
|
||||
using Microsoft.PowerToys.Settings.UI.Controls;
|
||||
@@ -681,7 +680,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
await LoadFoundryLocalModelsAsync();
|
||||
}
|
||||
|
||||
private sealed class FoundryDownloadableModel : INotifyPropertyChanged
|
||||
private sealed partial class FoundryDownloadableModel : INotifyPropertyChanged
|
||||
{
|
||||
private readonly List<string> _deviceTags;
|
||||
private double _progress;
|
||||
|
||||
@@ -55,14 +55,14 @@
|
||||
Glyph="" />
|
||||
<HyperlinkButton
|
||||
x:Uid="CmdNotFound_UninstallButton"
|
||||
Command="{x:Bind ViewModel.UninstallModuleEventHandler}"
|
||||
Click="UninstallButton_Click"
|
||||
IsEnabled="{x:Bind ViewModel.IsModuleGpoEnabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" />
|
||||
</StackPanel>
|
||||
</tkcontrols:Case>
|
||||
<tkcontrols:Case Value="False">
|
||||
<Button
|
||||
x:Uid="CmdNotFound_InstallButton"
|
||||
Command="{x:Bind ViewModel.InstallModuleEventHandler}"
|
||||
Click="InstallButton_Click"
|
||||
IsEnabled="{x:Bind ViewModel.IsModuleGpoDisabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</tkcontrols:Case>
|
||||
@@ -76,7 +76,7 @@
|
||||
IsClosable="False"
|
||||
IsOpen="True">
|
||||
<InfoBar.ActionButton>
|
||||
<HyperlinkButton x:Uid="CmdNotFound_CheckCompatibility" Command="{x:Bind ViewModel.CheckRequirementsEventHandler}">
|
||||
<HyperlinkButton x:Uid="CmdNotFound_CheckCompatibility" Click="CheckRequirementsButton_Click">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="CmdNotFound_CheckCompatibilityTooltip" TextWrapping="Wrap" />
|
||||
</ToolTipService.ToolTip>
|
||||
@@ -112,7 +112,7 @@
|
||||
Glyph="" />
|
||||
<Button
|
||||
x:Uid="CmdNotFound_InstallButton"
|
||||
Command="{x:Bind ViewModel.InstallPowerShell7EventHandler}"
|
||||
Click="InstallPowerShell7Button_Click"
|
||||
IsEnabled="{x:Bind ViewModel.IsModuleGpoDisabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" />
|
||||
</StackPanel>
|
||||
</tkcontrols:Case>
|
||||
@@ -145,7 +145,7 @@
|
||||
Glyph="" />
|
||||
<Button
|
||||
x:Uid="CmdNotFound_InstallButton"
|
||||
Command="{x:Bind ViewModel.InstallWinGetClientModuleEventHandler}"
|
||||
Click="InstallWinGetButton_Click"
|
||||
IsEnabled="{x:Bind ViewModel.IsModuleGpoDisabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}" />
|
||||
</StackPanel>
|
||||
</tkcontrols:Case>
|
||||
|
||||
@@ -18,5 +18,30 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
DataContext = ViewModel;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void UninstallButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.UninstallModuleEventHandler?.Execute(null);
|
||||
}
|
||||
|
||||
private void InstallButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.InstallModuleEventHandler?.Execute(null);
|
||||
}
|
||||
|
||||
private void CheckRequirementsButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.CheckRequirementsEventHandler?.Execute(null);
|
||||
}
|
||||
|
||||
private void InstallPowerShell7Button_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.InstallPowerShell7EventHandler?.Execute(null);
|
||||
}
|
||||
|
||||
private void InstallWinGetButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.InstallWinGetClientModuleEventHandler?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,6 +196,7 @@
|
||||
x:Name="ColorFormatDialog"
|
||||
x:Uid="ColorFormatDialog"
|
||||
Closed="ColorFormatDialog_Closed"
|
||||
PrimaryButtonClick="ColorFormatDialog_PrimaryButtonClick"
|
||||
IsPrimaryButtonEnabled="{Binding IsValid, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
PrimaryButtonStyle="{ThemeResource AccentButtonStyle}">
|
||||
<ContentDialog.DataContext>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Input;
|
||||
|
||||
using CommunityToolkit.WinUI.Controls;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
@@ -25,6 +24,15 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
|
||||
private ResourceLoader resourceLoader = ResourceLoaderInstance.ResourceLoader;
|
||||
|
||||
private enum DialogActionMode
|
||||
{
|
||||
None,
|
||||
Add,
|
||||
Update,
|
||||
}
|
||||
|
||||
private DialogActionMode _dialogActionMode = DialogActionMode.None;
|
||||
|
||||
public ColorPickerPage()
|
||||
{
|
||||
var settingsUtils = SettingsUtils.Default;
|
||||
@@ -129,7 +137,9 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
ColorFormatDialog.Tag = string.Empty;
|
||||
|
||||
ColorFormatDialog.PrimaryButtonText = resourceLoader.GetString("ColorFormatSave");
|
||||
ColorFormatDialog.PrimaryButtonCommand = AddCommand;
|
||||
|
||||
// Use Click event instead of Command for AOT compatibility
|
||||
_dialogActionMode = DialogActionMode.Add;
|
||||
await ColorFormatDialog.ShowAsync();
|
||||
}
|
||||
|
||||
@@ -142,7 +152,9 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
ColorFormatDialog.Tag = new KeyValuePair<string, string>(colorFormatModel.Name, colorFormatModel.Format);
|
||||
|
||||
ColorFormatDialog.PrimaryButtonText = resourceLoader.GetString("ColorFormatUpdate");
|
||||
ColorFormatDialog.PrimaryButtonCommand = UpdateCommand;
|
||||
|
||||
// Use Click event instead of Command for AOT compatibility
|
||||
_dialogActionMode = DialogActionMode.Update;
|
||||
await ColorFormatDialog.ShowAsync();
|
||||
}
|
||||
|
||||
@@ -156,6 +168,18 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
ViewModel.RefreshEnabledState();
|
||||
}
|
||||
|
||||
private void ColorFormatDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
if (_dialogActionMode == DialogActionMode.Add)
|
||||
{
|
||||
Add();
|
||||
}
|
||||
else if (_dialogActionMode == DialogActionMode.Update)
|
||||
{
|
||||
Update();
|
||||
}
|
||||
}
|
||||
|
||||
private void ColorFormatDialog_Closed(ContentDialog sender, ContentDialogClosedEventArgs args)
|
||||
{
|
||||
if (args.Result != ContentDialogResult.Primary && ColorFormatDialog.Tag is KeyValuePair<string, string>)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
Name="EnvironmentVariablesLaunchButtonControl"
|
||||
x:Uid="EnvironmentVariables_LaunchButtonControl"
|
||||
ActionIcon="{ui:FontIcon Glyph=}"
|
||||
Command="{x:Bind ViewModel.LaunchEventHandler}"
|
||||
Click="LaunchButton_Click"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsClickEnabled="True" />
|
||||
<tkcontrols:SettingsCard
|
||||
|
||||
@@ -24,5 +24,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
ViewModel.RefreshEnabledState();
|
||||
}
|
||||
|
||||
private void LaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.LaunchEventHandler?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
x:Uid="FancyZones_LaunchEditorButtonControl"
|
||||
ActionIcon="{ui:FontIcon Glyph=}"
|
||||
AutomationProperties.AutomationId="LaunchLayoutEditorButton"
|
||||
Command="{x:Bind ViewModel.LaunchEditorEventHandler}"
|
||||
Click="LaunchEditorButton_Click"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsClickEnabled="True" />
|
||||
|
||||
|
||||
@@ -31,5 +31,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
ViewModel.RefreshEnabledState();
|
||||
}
|
||||
|
||||
private void LaunchEditorButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.LaunchEditorEventHandler?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
Name="HostsLaunchButtonControl"
|
||||
x:Uid="Hosts_LaunchButtonControl"
|
||||
ActionIcon="{ui:FontIcon Glyph=}"
|
||||
Command="{x:Bind ViewModel.LaunchEventHandler}"
|
||||
Click="LaunchButton_Click"
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsClickEnabled="True" />
|
||||
<tkcontrols:SettingsCard
|
||||
@@ -115,7 +115,7 @@
|
||||
</TextBlock>
|
||||
<Button
|
||||
Grid.Column="1"
|
||||
Command="{x:Bind ViewModel.SelectBackupPathEventHandler}"
|
||||
Click="SelectBackupPathButton_Click"
|
||||
Content=""
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}">
|
||||
<ToolTipService.ToolTip>
|
||||
|
||||
@@ -28,5 +28,15 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
ViewModel.RefreshEnabledState();
|
||||
}
|
||||
|
||||
private void LaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.LaunchEventHandler?.Execute(null);
|
||||
}
|
||||
|
||||
private void SelectBackupPathButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.SelectBackupPathEventHandler?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Common.UI;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
Width="248" />
|
||||
<Button
|
||||
x:Uid="MouseWithoutBorders_Connect"
|
||||
Command="{x:Bind ConnectCommand, Mode=OneTime}"
|
||||
Click="ConnectButton_Click"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
</StackPanel>
|
||||
</tkcontrols:SettingsCard>
|
||||
@@ -65,11 +65,11 @@
|
||||
<TextBox IsReadOnly="True" Text="{x:Bind ViewModel.SecurityKey, Mode=TwoWay}" />
|
||||
<Button
|
||||
x:Uid="MouseWithoutBorders_NewKey"
|
||||
Command="{x:Bind GenerateNewKeyCommand, Mode=OneTime}"
|
||||
Click="GenerateNewKeyButton_Click"
|
||||
Style="{StaticResource AccentButtonStyle}" />
|
||||
<Button
|
||||
x:Uid="MouseWithoutBorders_Connect"
|
||||
Command="{x:Bind ShowConnectFieldsCommand, Mode=OneTime}"
|
||||
Click="ShowConnectFieldsButton_Click"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
Visibility="{x:Bind Path=ViewModel.ConnectFieldsVisible, Mode=OneWay, Converter={StaticResource ReverseBoolToVisibilityConverter}, ConverterParameter=True}" />
|
||||
</StackPanel>
|
||||
@@ -86,7 +86,7 @@
|
||||
Width="32"
|
||||
Height="32"
|
||||
Padding="4"
|
||||
Command="{x:Bind CopyPCNameCommand, Mode=OneTime}"
|
||||
Click="CopyPCNameButton_Click"
|
||||
Content=""
|
||||
FontFamily="{StaticResource SymbolThemeFontFamily}">
|
||||
<ToolTipService.ToolTip>
|
||||
@@ -160,7 +160,7 @@
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<Button HorizontalAlignment="Right" Command="{x:Bind ReconnectCommand, Mode=OneTime}">
|
||||
<Button HorizontalAlignment="Right" Click="ReconnectButton_Click">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="MouseWithoutBorders_ReconnectTooltip" TextWrapping="Wrap" />
|
||||
</ToolTipService.ToolTip>
|
||||
@@ -210,7 +210,7 @@
|
||||
Name="MouseWithoutBordersUninstallService"
|
||||
x:Uid="MouseWithoutBorders_UninstallService"
|
||||
ActionIcon="{ui:FontIcon Glyph=}"
|
||||
Command="{x:Bind ViewModel.UninstallServiceEventHandler}"
|
||||
Click="UninstallServiceButton_Click"
|
||||
IsClickEnabled="{x:Bind ViewModel.CanUninstallService, Mode=OneWay}"
|
||||
IsEnabled="{x:Bind ViewModel.CanUninstallService, Mode=OneWay}" />
|
||||
</controls:SettingsGroup>
|
||||
@@ -476,7 +476,7 @@
|
||||
Name="MouseWithoutBordersAddFirewallRuleButtonControl"
|
||||
x:Uid="MouseWithoutBorders_AddFirewallRuleButtonControl"
|
||||
ActionIcon="{ui:FontIcon Glyph=}"
|
||||
Command="{x:Bind ViewModel.AddFirewallRuleEventHandler}"
|
||||
Click="AddFirewallRuleButton_Click"
|
||||
IsClickEnabled="True" />
|
||||
<controls:GPOInfoControl ShowWarning="{x:Bind ViewModel.ShowPolicyConfiguredInfoForOriginalUiSetting, Mode=OneWay}">
|
||||
<tkcontrols:SettingsCard
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
using System;
|
||||
using System.IO.Abstractions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
@@ -171,5 +170,40 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
ViewModel.RefreshEnabledState();
|
||||
}
|
||||
|
||||
private void ConnectButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ConnectCommand?.Execute(null);
|
||||
}
|
||||
|
||||
private void GenerateNewKeyButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
GenerateNewKeyCommand?.Execute(null);
|
||||
}
|
||||
|
||||
private void ShowConnectFieldsButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ShowConnectFieldsCommand?.Execute(null);
|
||||
}
|
||||
|
||||
private void CopyPCNameButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
CopyPCNameCommand?.Execute(null);
|
||||
}
|
||||
|
||||
private void ReconnectButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ReconnectCommand?.Execute(null);
|
||||
}
|
||||
|
||||
private void UninstallServiceButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.UninstallServiceEventHandler?.Execute(null);
|
||||
}
|
||||
|
||||
private void AddFirewallRuleButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.AddFirewallRuleEventHandler?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,5 +25,15 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
{
|
||||
ViewModel.RefreshEnabledState();
|
||||
}
|
||||
|
||||
private void InstallTemplatePackageButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.OpenCurrentNewTemplateFolder?.Execute(null);
|
||||
}
|
||||
|
||||
private void UninstallTemplatePackageButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.PickAnotherNewTemplateFolder?.Execute(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
}
|
||||
}
|
||||
|
||||
// AOT-compatible type lookup using switch expression instead of reflection (IL2026)
|
||||
private Type GetPageTypeFromName(string pageTypeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pageTypeName))
|
||||
@@ -87,8 +88,41 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
return null;
|
||||
}
|
||||
|
||||
var assembly = typeof(GeneralPage).Assembly;
|
||||
return assembly.GetType($"Microsoft.PowerToys.Settings.UI.Views.{pageTypeName}");
|
||||
return pageTypeName switch
|
||||
{
|
||||
nameof(DashboardPage) => typeof(DashboardPage),
|
||||
nameof(GeneralPage) => typeof(GeneralPage),
|
||||
nameof(AdvancedPastePage) => typeof(AdvancedPastePage),
|
||||
nameof(AlwaysOnTopPage) => typeof(AlwaysOnTopPage),
|
||||
nameof(AwakePage) => typeof(AwakePage),
|
||||
nameof(CmdNotFoundPage) => typeof(CmdNotFoundPage),
|
||||
nameof(CmdPalPage) => typeof(CmdPalPage),
|
||||
nameof(ColorPickerPage) => typeof(ColorPickerPage),
|
||||
nameof(CropAndLockPage) => typeof(CropAndLockPage),
|
||||
nameof(EnvironmentVariablesPage) => typeof(EnvironmentVariablesPage),
|
||||
nameof(FancyZonesPage) => typeof(FancyZonesPage),
|
||||
nameof(FileLocksmithPage) => typeof(FileLocksmithPage),
|
||||
nameof(HostsPage) => typeof(HostsPage),
|
||||
nameof(ImageResizerPage) => typeof(ImageResizerPage),
|
||||
nameof(KeyboardManagerPage) => typeof(KeyboardManagerPage),
|
||||
nameof(LightSwitchPage) => typeof(LightSwitchPage),
|
||||
nameof(MeasureToolPage) => typeof(MeasureToolPage),
|
||||
nameof(MouseUtilsPage) => typeof(MouseUtilsPage),
|
||||
nameof(MouseWithoutBordersPage) => typeof(MouseWithoutBordersPage),
|
||||
nameof(NewPlusPage) => typeof(NewPlusPage),
|
||||
nameof(PeekPage) => typeof(PeekPage),
|
||||
nameof(PowerAccentPage) => typeof(PowerAccentPage),
|
||||
nameof(PowerLauncherPage) => typeof(PowerLauncherPage),
|
||||
nameof(PowerOcrPage) => typeof(PowerOcrPage),
|
||||
nameof(PowerPreviewPage) => typeof(PowerPreviewPage),
|
||||
nameof(PowerRenamePage) => typeof(PowerRenamePage),
|
||||
nameof(PowerDisplayPage) => typeof(PowerDisplayPage),
|
||||
nameof(RegistryPreviewPage) => typeof(RegistryPreviewPage),
|
||||
nameof(ShortcutGuidePage) => typeof(ShortcutGuidePage),
|
||||
nameof(WorkspacesPage) => typeof(WorkspacesPage),
|
||||
nameof(ZoomItPage) => typeof(ZoomItPage),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -138,6 +138,7 @@
|
||||
IsPaneToggleButtonVisible="False"
|
||||
IsSettingsVisible="False"
|
||||
IsTitleBarAutoPaddingEnabled="False"
|
||||
ItemInvoked="NavigationView_ItemInvoked"
|
||||
PaneClosed="NavigationView_PaneClosed"
|
||||
PaneOpened="NavigationView_PaneOpened"
|
||||
SelectedItem="{x:Bind ViewModel.Selected, Mode=OneWay}"
|
||||
@@ -447,11 +448,7 @@
|
||||
Visibility="{x:Bind ViewModel.ShowCloseMenu, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</NavigationView.PaneFooter>
|
||||
<i:Interaction.Behaviors>
|
||||
<ic:EventTriggerBehavior EventName="ItemInvoked">
|
||||
<ic:InvokeCommandAction Command="{x:Bind ViewModel.ItemInvokedCommand}" />
|
||||
</ic:EventTriggerBehavior>
|
||||
</i:Interaction.Behaviors>
|
||||
<!-- Direct event handler instead of InvokeCommandAction for AOT compatibility -->
|
||||
<Frame x:Name="shellFrame" />
|
||||
</NavigationView>
|
||||
<ContentDialog
|
||||
|
||||
@@ -338,6 +338,19 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
OpenWhatIsNewWindowCallback();
|
||||
}
|
||||
|
||||
private void NavigationView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
|
||||
{
|
||||
// Direct event handler for AOT compatibility (InvokeCommandAction doesn't work reliably with AOT)
|
||||
if (args?.InvokedItemContainer != null)
|
||||
{
|
||||
var pageType = args.InvokedItemContainer.GetValue(NavHelper.NavigateToProperty) as Type;
|
||||
if (pageType != null)
|
||||
{
|
||||
NavigationService.Navigate(pageType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void NavigationView_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
|
||||
{
|
||||
NavigationViewItem selectedItem = args.SelectedItem as NavigationViewItem;
|
||||
@@ -535,6 +548,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
}
|
||||
}
|
||||
|
||||
// AOT-compatible type lookup using switch expression instead of reflection (IL2026)
|
||||
private static Type GetPageTypeFromName(string pageTypeName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pageTypeName))
|
||||
@@ -542,8 +556,41 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
return null;
|
||||
}
|
||||
|
||||
var assembly = typeof(GeneralPage).Assembly;
|
||||
return assembly.GetType($"Microsoft.PowerToys.Settings.UI.Views.{pageTypeName}");
|
||||
return pageTypeName switch
|
||||
{
|
||||
nameof(DashboardPage) => typeof(DashboardPage),
|
||||
nameof(GeneralPage) => typeof(GeneralPage),
|
||||
nameof(AdvancedPastePage) => typeof(AdvancedPastePage),
|
||||
nameof(AlwaysOnTopPage) => typeof(AlwaysOnTopPage),
|
||||
nameof(AwakePage) => typeof(AwakePage),
|
||||
nameof(CmdNotFoundPage) => typeof(CmdNotFoundPage),
|
||||
nameof(CmdPalPage) => typeof(CmdPalPage),
|
||||
nameof(ColorPickerPage) => typeof(ColorPickerPage),
|
||||
nameof(CropAndLockPage) => typeof(CropAndLockPage),
|
||||
nameof(EnvironmentVariablesPage) => typeof(EnvironmentVariablesPage),
|
||||
nameof(FancyZonesPage) => typeof(FancyZonesPage),
|
||||
nameof(FileLocksmithPage) => typeof(FileLocksmithPage),
|
||||
nameof(HostsPage) => typeof(HostsPage),
|
||||
nameof(ImageResizerPage) => typeof(ImageResizerPage),
|
||||
nameof(KeyboardManagerPage) => typeof(KeyboardManagerPage),
|
||||
nameof(LightSwitchPage) => typeof(LightSwitchPage),
|
||||
nameof(MeasureToolPage) => typeof(MeasureToolPage),
|
||||
nameof(MouseUtilsPage) => typeof(MouseUtilsPage),
|
||||
nameof(MouseWithoutBordersPage) => typeof(MouseWithoutBordersPage),
|
||||
nameof(NewPlusPage) => typeof(NewPlusPage),
|
||||
nameof(PeekPage) => typeof(PeekPage),
|
||||
nameof(PowerAccentPage) => typeof(PowerAccentPage),
|
||||
nameof(PowerLauncherPage) => typeof(PowerLauncherPage),
|
||||
nameof(PowerOcrPage) => typeof(PowerOcrPage),
|
||||
nameof(PowerPreviewPage) => typeof(PowerPreviewPage),
|
||||
nameof(PowerRenamePage) => typeof(PowerRenamePage),
|
||||
nameof(PowerDisplayPage) => typeof(PowerDisplayPage),
|
||||
nameof(RegistryPreviewPage) => typeof(RegistryPreviewPage),
|
||||
nameof(ShortcutGuidePage) => typeof(ShortcutGuidePage),
|
||||
nameof(WorkspacesPage) => typeof(WorkspacesPage),
|
||||
nameof(ZoomItPage) => typeof(ZoomItPage),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
private void CtrlF_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
||||
|
||||
@@ -50,7 +50,8 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
|
||||
private static LOGFONT PickFontDialog(LOGFONT font)
|
||||
{
|
||||
IntPtr pLogFont = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(LOGFONT)));
|
||||
// Use generic overload for AOT compatibility (IL3050)
|
||||
IntPtr pLogFont = Marshal.AllocHGlobal(Marshal.SizeOf<LOGFONT>());
|
||||
if (font != null)
|
||||
{
|
||||
font.lfHeight = -21;
|
||||
@@ -72,12 +73,16 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
||||
chooseFont.nSizeMin = 16;
|
||||
chooseFont.nSizeMax = 16;
|
||||
chooseFont.nFontType = 0x2000; // SCREEN_FONTTYPE as in the original ZoomIt source.
|
||||
chooseFont.hInstance = Marshal.GetHINSTANCE(typeof(ZoomItPage).Module);
|
||||
|
||||
// Use IntPtr.Zero instead of Marshal.GetHINSTANCE for AOT compatibility (IL3002)
|
||||
// This works fine for ChooseFont dialog as the system will use the process HINSTANCE
|
||||
chooseFont.hInstance = IntPtr.Zero;
|
||||
|
||||
// TODO: chooseFont.lpTemplateName = FORMATDLGORD31; and CHOOSE_FONT_FLAGS.CF_ENABLETEMPLATE
|
||||
chooseFont.lpLogFont = pLogFont;
|
||||
|
||||
IntPtr pChooseFont = Marshal.AllocHGlobal(Marshal.SizeOf(chooseFont));
|
||||
// Use generic overload for AOT compatibility (IL3050)
|
||||
IntPtr pChooseFont = Marshal.AllocHGlobal(Marshal.SizeOf<CHOOSEFONT>());
|
||||
Marshal.StructureToPtr(chooseFont, pChooseFont, false);
|
||||
|
||||
bool callResult = NativeMethods.ChooseFont(pChooseFont);
|
||||
|
||||
@@ -23,7 +23,7 @@ using Windows.Management.Deployment;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class CmdPalViewModel : PageViewModelBase
|
||||
public partial class CmdPalViewModel : PageViewModelBase
|
||||
{
|
||||
protected override string ModuleName => "CmdPal";
|
||||
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels.Commands
|
||||
{
|
||||
public partial class ButtonClickCommand : ICommand
|
||||
public partial class ButtonClickCommand : Microsoft.PowerToys.Settings.UI.Library.ICommand
|
||||
{
|
||||
private readonly Action _execute;
|
||||
|
||||
@@ -17,16 +19,16 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels.Commands
|
||||
}
|
||||
|
||||
// Occurs when changes occur that affect whether or not the command should execute.
|
||||
public event EventHandler CanExecuteChanged;
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
// Defines the method that determines whether the command can execute in its current state.
|
||||
public bool CanExecute(object parameter)
|
||||
public bool CanExecute(object? parameter)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Defines the method to be called when the command is invoked.
|
||||
public void Execute(object parameter)
|
||||
public void Execute(object? parameter)
|
||||
{
|
||||
_execute();
|
||||
}
|
||||
|
||||
@@ -10,16 +10,17 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
|
||||
using Microsoft.PowerToys.Settings.Utilities;
|
||||
using Microsoft.Win32;
|
||||
using LibraryRelayCommand = Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands.RelayCommand;
|
||||
using NativeMethods = Microsoft.PowerToys.Settings.Utilities.NativeMethods;
|
||||
using RelayCommand = Microsoft.PowerToys.Settings.UI.Helpers.RelayCommand;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
|
||||
@@ -12,7 +12,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json;
|
||||
using System.Windows.Input;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
/// <summary>
|
||||
/// ViewModel for monitor selection in profile editor
|
||||
/// </summary>
|
||||
public class MonitorSelectionItem : INotifyPropertyChanged
|
||||
public partial class MonitorSelectionItem : INotifyPropertyChanged
|
||||
{
|
||||
private bool _isSelected;
|
||||
private int _brightness = 100;
|
||||
|
||||
@@ -8,7 +8,6 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
@@ -21,7 +21,7 @@ using Settings.UI.Library;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class PeekViewModel : PageViewModelBase
|
||||
public partial class PeekViewModel : PageViewModelBase
|
||||
{
|
||||
protected override string ModuleName => PeekSettings.ModuleName;
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json;
|
||||
using System.Windows.Input;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
/// <summary>
|
||||
/// ViewModel for Profile Editor Dialog
|
||||
/// </summary>
|
||||
public class ProfileEditorViewModel : INotifyPropertyChanged
|
||||
public partial class ProfileEditorViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private string _profileName = string.Empty;
|
||||
private ObservableCollection<MonitorSelectionItem> _monitors;
|
||||
|
||||
@@ -12,7 +12,7 @@ using Settings.UI.Library;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class SearchResultsViewModel : INotifyPropertyChanged
|
||||
public partial class SearchResultsViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private ObservableCollection<SettingEntry> _moduleResults = new();
|
||||
private ObservableCollection<SettingsGroup> _groupedSettingsResults = new();
|
||||
@@ -97,7 +97,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
|
||||
#pragma warning disable SA1402 // File may only contain a single type
|
||||
public class SettingsGroup : INotifyPropertyChanged
|
||||
public partial class SettingsGroup : INotifyPropertyChanged
|
||||
#pragma warning restore SA1402 // File may only contain a single type
|
||||
{
|
||||
private string _groupName;
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -12,7 +14,6 @@ using System.Reflection;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Text.Json.Serialization.Metadata;
|
||||
using System.Windows.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
@@ -25,11 +26,11 @@ using Microsoft.Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class ShortcutConflictViewModel : PageViewModelBase
|
||||
public partial class ShortcutConflictViewModel : PageViewModelBase
|
||||
{
|
||||
private readonly SettingsFactory _settingsFactory;
|
||||
private readonly Func<string, int> _ipcMSGCallBackFunc;
|
||||
private readonly Dispatcher _dispatcher;
|
||||
private readonly Microsoft.UI.Dispatching.DispatcherQueue? _dispatcherQueue;
|
||||
|
||||
private bool _disposed;
|
||||
private AllHotkeyConflictsData _conflictsData = new();
|
||||
@@ -41,7 +42,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
ISettingsRepository<GeneralSettings> settingsRepository,
|
||||
Func<string, int> ipcMSGCallBackFunc)
|
||||
{
|
||||
_dispatcher = Dispatcher.CurrentDispatcher;
|
||||
// Use WinUI 3 DispatcherQueue instead of WPF Dispatcher for AOT compatibility
|
||||
_dispatcherQueue = Microsoft.UI.Dispatching.DispatcherQueue.GetForCurrentThread();
|
||||
_ipcMSGCallBackFunc = ipcMSGCallBackFunc ?? throw new ArgumentNullException(nameof(ipcMSGCallBackFunc));
|
||||
resourceLoader = ResourceLoaderInstance.ResourceLoader;
|
||||
|
||||
@@ -63,7 +65,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
public ObservableCollection<HotkeyConflictGroupData> ConflictItems
|
||||
{
|
||||
get => _conflictItems;
|
||||
get => _conflictItems ?? new ObservableCollection<HotkeyConflictGroupData>();
|
||||
private set => Set(ref _conflictItems, value);
|
||||
}
|
||||
|
||||
@@ -117,13 +119,14 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Error loading settings for {moduleKey}: {ex.Message}");
|
||||
return null;
|
||||
return null!; // Suppress nullable warning - caller handles null
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnConflictsUpdated(object sender, AllHotkeyConflictsEventArgs e)
|
||||
{
|
||||
_dispatcher.BeginInvoke(() =>
|
||||
// WinUI 3 DispatcherQueue uses TryEnqueue instead of BeginInvoke
|
||||
_dispatcherQueue?.TryEnqueue(() =>
|
||||
{
|
||||
ConflictsData = e.Conflicts ?? new AllHotkeyConflictsData();
|
||||
});
|
||||
@@ -133,8 +136,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
var items = new ObservableCollection<HotkeyConflictGroupData>();
|
||||
|
||||
ProcessConflicts(ConflictsData?.InAppConflicts, false, items);
|
||||
ProcessConflicts(ConflictsData?.SystemConflicts, true, items);
|
||||
ProcessConflicts(ConflictsData?.InAppConflicts ?? Enumerable.Empty<HotkeyConflictGroupData>(), false, items);
|
||||
ProcessConflicts(ConflictsData?.SystemConflicts ?? Enumerable.Empty<HotkeyConflictGroupData>(), true, items);
|
||||
|
||||
ConflictItems = items;
|
||||
OnPropertyChanged(nameof(ConflictItems));
|
||||
@@ -218,7 +221,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
settings.IsSystemConflict = isSystemConflict;
|
||||
}
|
||||
|
||||
private void OnModuleHotkeyDataPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
private void OnModuleHotkeyDataPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (sender is ModuleHotkeyData moduleData && e.PropertyName == nameof(ModuleHotkeyData.HotkeySettings))
|
||||
{
|
||||
@@ -272,10 +275,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
try
|
||||
{
|
||||
var jsonTypeInfo = GetJsonTypeInfo(settingsConfig.GetType());
|
||||
var serializedSettings = jsonTypeInfo != null
|
||||
? JsonSerializer.Serialize(settingsConfig, jsonTypeInfo)
|
||||
: JsonSerializer.Serialize(settingsConfig);
|
||||
// Use source-generated serializer for AOT compatibility (IL2026/IL3050)
|
||||
var serializedSettings = SerializeSettings(settingsConfig);
|
||||
|
||||
string ipcMessage;
|
||||
if (string.Equals(moduleName, "GeneralSettings", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -303,30 +304,43 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private JsonTypeInfo GetJsonTypeInfo(Type settingsType)
|
||||
// AOT-compatible serialization using source-generated context
|
||||
private string SerializeSettings(ISettingsConfig settingsConfig)
|
||||
{
|
||||
try
|
||||
return settingsConfig switch
|
||||
{
|
||||
var contextType = typeof(SourceGenerationContextContext);
|
||||
var defaultProperty = contextType.GetProperty("Default", BindingFlags.Public | BindingFlags.Static);
|
||||
var defaultContext = defaultProperty?.GetValue(null) as JsonSerializerContext;
|
||||
GeneralSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.GeneralSettings),
|
||||
AdvancedPasteSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.AdvancedPasteSettings),
|
||||
AlwaysOnTopSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.AlwaysOnTopSettings),
|
||||
AwakeSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.AwakeSettings),
|
||||
CmdNotFoundSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.CmdNotFoundSettings),
|
||||
ColorPickerSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.ColorPickerSettings),
|
||||
CropAndLockSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.CropAndLockSettings),
|
||||
EnvironmentVariablesSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.EnvironmentVariablesSettings),
|
||||
FancyZonesSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.FancyZonesSettings),
|
||||
FileLocksmithSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.FileLocksmithSettings),
|
||||
HostsSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.HostsSettings),
|
||||
ImageResizerSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.ImageResizerSettings),
|
||||
KeyboardManagerSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.KeyboardManagerSettings),
|
||||
LightSwitchSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.LightSwitchSettings),
|
||||
MeasureToolSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.MeasureToolSettings),
|
||||
MouseWithoutBordersSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.MouseWithoutBordersSettings),
|
||||
NewPlusSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.NewPlusSettings),
|
||||
PeekSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.PeekSettings),
|
||||
PowerAccentSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.PowerAccentSettings),
|
||||
PowerDisplaySettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.PowerDisplaySettings),
|
||||
PowerLauncherSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.PowerLauncherSettings),
|
||||
PowerOcrSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.PowerOcrSettings),
|
||||
PowerPreviewSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.PowerPreviewSettings),
|
||||
PowerRenameSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.PowerRenameSettings),
|
||||
RegistryPreviewSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.RegistryPreviewSettings),
|
||||
ShortcutGuideSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.ShortcutGuideSettings),
|
||||
WorkspacesSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.WorkspacesSettings),
|
||||
ZoomItSettings s => JsonSerializer.Serialize(s, SettingsSerializationContext.Default.ZoomItSettings),
|
||||
|
||||
if (defaultContext != null)
|
||||
{
|
||||
var typeInfoProperty = contextType.GetProperties(BindingFlags.Public | BindingFlags.Instance)
|
||||
.FirstOrDefault(p => p.PropertyType.IsGenericType &&
|
||||
p.PropertyType.GetGenericTypeDefinition() == typeof(JsonTypeInfo<>) &&
|
||||
p.PropertyType.GetGenericArguments()[0] == settingsType);
|
||||
|
||||
return typeInfoProperty?.GetValue(defaultContext) as JsonTypeInfo;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine($"Error getting JsonTypeInfo for {settingsType.Name}: {ex.Message}");
|
||||
}
|
||||
|
||||
return null;
|
||||
// If we hit this case, SettingsSerializationContext is incomplete - this should be caught in development
|
||||
_ => throw new InvalidOperationException($"Settings type {settingsConfig.GetType().Name} is not registered in SettingsSerializationContext. Please add [JsonSerializable(typeof({settingsConfig.GetType().Name}))] to the context."),
|
||||
};
|
||||
}
|
||||
|
||||
private string GetHotkeyLocalizationHeader(string moduleName, int hotkeyID, string headerKey)
|
||||
|
||||
@@ -22,7 +22,7 @@ using Windows.Devices.Enumeration;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
public class ZoomItViewModel : Observable
|
||||
public partial class ZoomItViewModel : Observable
|
||||
{
|
||||
private const string FormatGif = "GIF";
|
||||
private const string FormatMp4 = "MP4";
|
||||
@@ -66,12 +66,6 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
|
||||
{
|
||||
MaxDepth = 0,
|
||||
IncludeFields = true,
|
||||
};
|
||||
|
||||
public ZoomItViewModel(SettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc, Func<string, string, string, int, string> pickFileDialog, Func<LOGFONT, LOGFONT> pickFontDialog)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(settingsUtils);
|
||||
@@ -84,7 +78,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
GeneralSettingsConfig = settingsRepository.SettingsConfig;
|
||||
|
||||
var zoomItSettings = global::PowerToys.ZoomItSettingsInterop.ZoomItSettings.LoadSettingsJson();
|
||||
_zoomItSettings = JsonSerializer.Deserialize<ZoomItSettings>(zoomItSettings, _serializerOptions);
|
||||
|
||||
// Use source-generated deserializer for AOT compatibility (IL2026/IL3050)
|
||||
_zoomItSettings = JsonSerializer.Deserialize(zoomItSettings, SettingsSerializationContext.Default.ZoomItSettings);
|
||||
|
||||
InitializeEnabledValue();
|
||||
|
||||
@@ -424,7 +420,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
{
|
||||
var encodedFont = _zoomItSettings.Properties.Font.Value;
|
||||
byte[] decodedFont = Convert.FromBase64String(encodedFont);
|
||||
int size = Marshal.SizeOf(typeof(LOGFONT));
|
||||
int size = Marshal.SizeOf<LOGFONT>();
|
||||
if (size != decodedFont.Length)
|
||||
{
|
||||
throw new InvalidOperationException("Expected byte array from saved Settings doesn't match the LOGFONT structure size");
|
||||
@@ -438,7 +434,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
Marshal.Copy(decodedFont, 0, ptr, size);
|
||||
|
||||
// Marshal the unmanaged memory back to a LOGFONT structure
|
||||
return (LOGFONT)Marshal.PtrToStructure(ptr, typeof(LOGFONT));
|
||||
// Use generic overload for AOT compatibility
|
||||
return Marshal.PtrToStructure<LOGFONT>(ptr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -450,7 +447,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
set
|
||||
{
|
||||
_typeFont = value;
|
||||
int size = Marshal.SizeOf(typeof(LOGFONT));
|
||||
int size = Marshal.SizeOf<LOGFONT>();
|
||||
byte[] bytes = new byte[size];
|
||||
|
||||
// Allocate unmanaged memory for the LOGFONT structure
|
||||
@@ -840,7 +837,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
// Reload settings to get the new format's scaling value
|
||||
var reloadedSettings = global::PowerToys.ZoomItSettingsInterop.ZoomItSettings.LoadSettingsJson();
|
||||
var reloaded = JsonSerializer.Deserialize<ZoomItSettings>(reloadedSettings, _serializerOptions);
|
||||
|
||||
// Use source-generated deserializer for AOT compatibility (IL2026/IL3050)
|
||||
var reloaded = JsonSerializer.Deserialize(reloadedSettings, SettingsSerializationContext.Default.ZoomItSettings);
|
||||
if (reloaded != null && reloaded.Properties != null)
|
||||
{
|
||||
_zoomItSettings.Properties.RecordScaling.Value = reloaded.Properties.RecordScaling.Value;
|
||||
@@ -894,8 +893,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
private void NotifySettingsChanged()
|
||||
{
|
||||
// Use source-generated serializer for AOT compatibility (IL2026/IL3050)
|
||||
global::PowerToys.ZoomItSettingsInterop.ZoomItSettings.SaveSettingsJson(
|
||||
JsonSerializer.Serialize(_zoomItSettings));
|
||||
JsonSerializer.Serialize(_zoomItSettings, SettingsSerializationContext.Default.ZoomItSettings));
|
||||
SendCustomAction("refresh_settings");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user