From fe53a9c89ae2d913f9ba759741a25f05032c40d4 Mon Sep 17 00:00:00 2001 From: Clint Rutkas Date: Thu, 10 Apr 2025 05:27:17 +0000 Subject: [PATCH 01/70] empowering users to maximize OOBE to their heart desire (#37823) empowering users to maximize to their heart desire --- .../SettingsXAML/OobeWindow.xaml.cs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/settings-ui/Settings.UI/SettingsXAML/OobeWindow.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/OobeWindow.xaml.cs index 48153c127a..56262fea6a 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/OobeWindow.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/OobeWindow.xaml.cs @@ -31,7 +31,6 @@ namespace Microsoft.PowerToys.Settings.UI private WindowId _windowId; private IntPtr _hWnd; private AppWindow _appWindow; - private WindowMessageMonitor _msgMonitor; private bool disposedValue; public OobeWindow(PowerToysModules initialModule) @@ -46,10 +45,6 @@ namespace Microsoft.PowerToys.Settings.UI _appWindow = AppWindow.GetFromWindowId(_windowId); this.Activated += Window_Activated_SetIcon; - OverlappedPresenter presenter = _appWindow.Presenter as OverlappedPresenter; - presenter.IsMinimizable = false; - presenter.IsMaximizable = false; - var dpi = NativeMethods.GetDpiForWindow(_hWnd); _currentDPI = dpi; float scalingFactor = (float)dpi / DefaultDPI; @@ -63,18 +58,6 @@ namespace Microsoft.PowerToys.Settings.UI this.initialModule = initialModule; - _msgMonitor = new WindowMessageMonitor(this); - _msgMonitor.WindowMessageReceived += (_, e) => - { - const int WM_NCLBUTTONDBLCLK = 0x00A3; - if (e.Message.MessageId == WM_NCLBUTTONDBLCLK) - { - // Disable double click on title bar to maximize window - e.Result = 0; - e.Handled = true; - } - }; - this.SizeChanged += OobeWindow_SizeChanged; var loader = Helpers.ResourceLoaderInstance.ResourceLoader; @@ -154,8 +137,6 @@ namespace Microsoft.PowerToys.Settings.UI { if (!disposedValue) { - _msgMonitor?.Dispose(); - disposedValue = true; } } From 94e85597966ba01ce262f9a60c2cf25609a94fb6 Mon Sep 17 00:00:00 2001 From: Laszlo Nemeth <57342539+donlaci@users.noreply.github.com> Date: Thu, 10 Apr 2025 10:29:06 +0200 Subject: [PATCH 02/70] [Bug report] - Auto fill bug report parameters. (#37991) --- .github/ISSUE_TEMPLATE/bug_report.yml | 31 +++++--- .../SettingsXAML/Views/GeneralPage.xaml | 2 +- .../SettingsXAML/Views/GeneralPage.xaml.cs | 2 + .../ViewModels/GeneralViewModel.cs | 78 +++++++++++++++++++ 4 files changed, 100 insertions(+), 13 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 08bbc04c55..e55d081c91 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,6 +1,5 @@ name: "🕷️ Bug report" description: Report errors or unexpected behavior -type: Bug labels: - Issue-Bug - Needs-Triage @@ -8,7 +7,8 @@ body: - type: markdown attributes: value: Please make sure to [search for existing issues](https://github.com/microsoft/PowerToys/issues) before filing a new one! -- type: input +- id: version + type: input attributes: label: Microsoft PowerToys version placeholder: X.XX.X @@ -16,7 +16,8 @@ body: validations: required: true -- type: dropdown +- id: installed + type: dropdown attributes: label: Installation method description: How / Where was PowerToys installed from? @@ -33,14 +34,6 @@ body: validations: required: true -- type: dropdown - attributes: - label: Running as admin - description: Are you running PowerToys as Admin? - options: - - "Yes" - - "No" - - type: dropdown attributes: label: Area(s) with issue? @@ -67,7 +60,7 @@ body: - Keyboard Manager - Mouse Utilities - Mouse Without Borders - - New+ + - New+ - Peek - PowerRename - PowerToys Run @@ -106,6 +99,19 @@ body: validations: required: false +- id: additionalInfo + type: textarea + attributes: + label: Additional Information + placeholder: | + OS version + .Net version + System Language + User or System Installation + Running as admin + validations: + required: false + - type: textarea attributes: label: Other Software @@ -116,3 +122,4 @@ body: My Cool Application v0.3 (include a code snippet if it would help!) validations: required: false + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml index fcd06e8292..079a634e97 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml @@ -458,7 +458,7 @@ - + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs index a7b0bcf5dc..b40a021252 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml.cs @@ -84,6 +84,8 @@ namespace Microsoft.PowerToys.Settings.UI.Views DataContext = ViewModel; + ViewModel.InitializeReportBugLink(); + doRefreshBackupRestoreStatus(100); } diff --git a/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs index 3669681bb7..c535ffa579 100644 --- a/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs @@ -9,6 +9,7 @@ using System.Diagnostics; using System.Globalization; using System.IO; using System.IO.Abstractions; +using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Text.Json; @@ -25,11 +26,19 @@ using Microsoft.PowerToys.Settings.UI.Library.Utilities; using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands; using Microsoft.PowerToys.Settings.UI.SerializationContext; using Microsoft.PowerToys.Telemetry; +using Microsoft.Win32; +using Windows.System.Profile; namespace Microsoft.PowerToys.Settings.UI.ViewModels { public partial class GeneralViewModel : Observable { + public enum InstallScope + { + PerMachine = 0, + PerUser, + } + private GeneralSettings GeneralSettingsConfig { get; set; } private UpdatingSettings UpdatingSettingsConfig { get; set; } @@ -72,6 +81,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private SettingsBackupAndRestoreUtils settingsBackupAndRestoreUtils = SettingsBackupAndRestoreUtils.Instance; + private const string InstallScopeRegKey = @"Software\Classes\powertoys\"; + public GeneralViewModel(ISettingsRepository settingsRepository, string runAsAdminText, string runAsUserText, bool isElevated, bool isAdmin, Func ipcMSGCallBackFunc, Func ipcMSGRestartAsAdminMSGCallBackFunc, Func ipcMSGCheckForUpdatesCallBackFunc, string configFileSubfolder = "", Action dispatcherAction = null, Action hideBackupAndRestoreMessageAreaAction = null, Action doBackupAndRestoreDryRun = null, Func> pickSingleFolderDialog = null, Windows.ApplicationModel.Resources.ResourceLoader resourceLoader = null) { CheckForUpdatesEventHandler = new ButtonClickCommand(CheckForUpdatesClick); @@ -256,6 +267,73 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private int _initLanguagesIndex; private bool _languageChanged; + private string reportBugLink; + + // Gets or sets a value indicating whether run powertoys on start-up. + public string ReportBugLink + { + get => reportBugLink; + set + { + reportBugLink = value; + OnPropertyChanged(nameof(ReportBugLink)); + } + } + + public void InitializeReportBugLink() + { + var version = GetPowerToysVersion(); + + string isElevatedString = "PowerToys is running " + (IsElevated ? "as admin (elevated)" : "as user (non-elevated)"); + + string installScope = GetCurrentInstallScope() == InstallScope.PerMachine ? "per machine (system)" : "per user"; + + var info = $"OS Version: {GetOSVersion()} \n.NET Version: {GetDotNetVersion()}\n{isElevatedString}\nInstall scope: {installScope}\nOperating System Language: {CultureInfo.InstalledUICulture.DisplayName}\nSystem locale: {CultureInfo.InstalledUICulture.Name}"; + + var gitHubURL = "https://github.com/microsoft/PowerToys/issues/new?template=bug_report.yml&labels=Issue-Bug%2CTriage-Needed" + + "&version=" + version + "&additionalInfo=" + System.Web.HttpUtility.UrlEncode(info); + + ReportBugLink = gitHubURL; + } + + private string GetPowerToysVersion() + { + return Helper.GetProductVersion().TrimStart('v'); + } + + private string GetOSVersion() + { + return Environment.OSVersion.VersionString; + } + + public static string GetDotNetVersion() + { + return $".NET {Environment.Version}"; + } + + public static InstallScope GetCurrentInstallScope() + { + // Check HKLM first + if (Registry.LocalMachine.OpenSubKey(InstallScopeRegKey) != null) + { + return InstallScope.PerMachine; + } + + // If not found, check HKCU + var userKey = Registry.CurrentUser.OpenSubKey(InstallScopeRegKey); + if (userKey != null) + { + var installScope = userKey.GetValue("InstallScope") as string; + userKey.Close(); + if (!string.IsNullOrEmpty(installScope) && installScope.Contains("perUser")) + { + return InstallScope.PerUser; + } + } + + return InstallScope.PerMachine; // Default if no specific registry key found + } + // Gets or sets a value indicating whether run powertoys on start-up. public bool Startup { From 41472a483cf74371295ceca85e2decdcfc863bf1 Mon Sep 17 00:00:00 2001 From: RokyZevon <12629919+RokyZevon@users.noreply.github.com> Date: Thu, 10 Apr 2025 22:00:33 +0800 Subject: [PATCH 03/70] [cmdpal] fix a broken link in README.md (#38714) related issue: #38713 --- src/modules/cmdpal/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/cmdpal/README.md b/src/modules/cmdpal/README.md index 83f37f0c16..2ca4f2f0cf 100644 --- a/src/modules/cmdpal/README.md +++ b/src/modules/cmdpal/README.md @@ -40,7 +40,7 @@ Projects of interest are: [Initial SDK Spec]: ./doc/initial-sdk-spec/initial-sdk-spec.md [generic samples]: ./Exts/SamplePagesExtension -[real samples]: .Exts/ProcessMonitorExtension +[real samples]: ./Exts/ProcessMonitorExtension [real extensions that we've "shipped" already]: https://github.com/zadjii/CmdPalExtensions/blob/main/src/extensions From a7994402fe9ea7b89abf0702abb9833977367f4d Mon Sep 17 00:00:00 2001 From: Yu Leng <42196638+moooyo@users.noreply.github.com> Date: Thu, 10 Apr 2025 23:34:52 +0800 Subject: [PATCH 04/70] [cmdpal] Add Open URL fallback command for WebSearch ext (#38685) ## Summary of the Pull Request 1. Add new fallback command for websearch https://github.com/user-attachments/assets/39362d66-db59-42d4-b07c-7bfd60b2e420 ## PR Checklist - [x] **Closes:** #38497 --------- Co-authored-by: Yu Leng (from Dev Box) --- .../Commands/OpenURLCommand.cs | 37 ++++++++ .../FallbackOpenURLItem.cs | 88 +++++++++++++++++++ .../Properties/Resources.Designer.cs | 18 ++++ .../Properties/Resources.resx | 6 ++ .../WebSearchCommandsProvider.cs | 4 +- 5 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Commands/OpenURLCommand.cs create mode 100644 src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/FallbackOpenURLItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Commands/OpenURLCommand.cs b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Commands/OpenURLCommand.cs new file mode 100644 index 0000000000..fd3f3a8f18 --- /dev/null +++ b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Commands/OpenURLCommand.cs @@ -0,0 +1,37 @@ +// 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 Microsoft.CmdPal.Ext.WebSearch.Helpers; +using Microsoft.CommandPalette.Extensions.Toolkit; + +using BrowserInfo = Microsoft.CmdPal.Ext.WebSearch.Helpers.DefaultBrowserInfo; + +namespace Microsoft.CmdPal.Ext.WebSearch.Commands; + +internal sealed partial class OpenURLCommand : InvokableCommand +{ + private readonly SettingsManager _settingsManager; + + public string Url { get; internal set; } = string.Empty; + + internal OpenURLCommand(string url, SettingsManager settingsManager) + { + Url = url; + BrowserInfo.UpdateIfTimePassed(); + Icon = IconHelpers.FromRelativePath("Assets\\WebSearch.png"); + Name = string.Empty; + _settingsManager = settingsManager; + } + + public override CommandResult Invoke() + { + if (!ShellHelpers.OpenCommandInShell(BrowserInfo.Path, BrowserInfo.ArgumentsPattern, $"{Url}")) + { + // TODO GH# 138 --> actually display feedback from the extension somewhere. + return CommandResult.KeepOpen(); + } + + return CommandResult.Dismiss(); + } +} diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/FallbackOpenURLItem.cs b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/FallbackOpenURLItem.cs new file mode 100644 index 0000000000..721af2ec8e --- /dev/null +++ b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/FallbackOpenURLItem.cs @@ -0,0 +1,88 @@ +// 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.Globalization; +using System.Text; +using Microsoft.CmdPal.Ext.WebSearch.Commands; +using Microsoft.CmdPal.Ext.WebSearch.Helpers; +using Microsoft.CmdPal.Ext.WebSearch.Properties; +using Microsoft.CommandPalette.Extensions.Toolkit; +using BrowserInfo = Microsoft.CmdPal.Ext.WebSearch.Helpers.DefaultBrowserInfo; + +namespace Microsoft.CmdPal.Ext.WebSearch; + +internal sealed partial class FallbackOpenURLItem : FallbackCommandItem +{ + private readonly OpenURLCommand _executeItem; + private static readonly CompositeFormat PluginOpenURL = System.Text.CompositeFormat.Parse(Properties.Resources.plugin_open_url); + private static readonly CompositeFormat PluginOpenUrlInBrowser = System.Text.CompositeFormat.Parse(Properties.Resources.plugin_open_url_in_browser); + + public FallbackOpenURLItem(SettingsManager settings) + : base(new OpenURLCommand(string.Empty, settings), string.Empty) + { + _executeItem = (OpenURLCommand)this.Command!; + Title = string.Empty; + _executeItem.Name = string.Empty; + Subtitle = string.Empty; + Icon = IconHelpers.FromRelativePath("Assets\\WebSearch.png"); + } + + public override void UpdateQuery(string query) + { + if (!IsValidUrl(query)) + { + Title = string.Empty; + Subtitle = string.Empty; + return; + } + + var success = Uri.TryCreate(query, UriKind.Absolute, out var uri); + + // if url not contain schema, add http:// by default. + if (!success) + { + query = "https://" + query; + } + + _executeItem.Url = query; + _executeItem.Name = string.IsNullOrEmpty(query) ? string.Empty : Properties.Resources.open_in_default_browser; + + Title = string.Format(CultureInfo.CurrentCulture, PluginOpenURL, query); + Subtitle = string.Format(CultureInfo.CurrentCulture, PluginOpenUrlInBrowser, BrowserInfo.Name ?? BrowserInfo.MSEdgeName); + } + + public static bool IsValidUrl(string url) + { + if (string.IsNullOrWhiteSpace(url)) + { + return false; + } + + if (!url.Contains('.', StringComparison.OrdinalIgnoreCase)) + { + // eg: 'com', 'org'. We don't think it's a valid url. + // This can simplify the logic of checking if the url is valid. + return false; + } + + if (Uri.IsWellFormedUriString(url, UriKind.Absolute)) + { + return true; + } + + if (!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase) && + !url.StartsWith("https://", StringComparison.OrdinalIgnoreCase) && + !url.StartsWith("ftp://", StringComparison.OrdinalIgnoreCase) && + !url.StartsWith("file://", StringComparison.OrdinalIgnoreCase)) + { + if (Uri.IsWellFormedUriString("https://" + url, UriKind.Absolute)) + { + return true; + } + } + + return false; + } +} diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs index e138b74ecc..15a8c4631f 100644 --- a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs +++ b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs @@ -195,6 +195,24 @@ namespace Microsoft.CmdPal.Ext.WebSearch.Properties { } } + /// + /// Looks up a localized string similar to Open "{0}". + /// + public static string plugin_open_url { + get { + return ResourceManager.GetString("plugin_open_url", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Open url in {0}. + /// + public static string plugin_open_url_in_browser { + get { + return ResourceManager.GetString("plugin_open_url_in_browser", resourceCulture); + } + } + /// /// Looks up a localized string similar to Failed to open {0}.. /// diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx index 9caaca6c2f..aec5b771c9 100644 --- a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx +++ b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx @@ -163,6 +163,12 @@ Search the web in {0} + + Open "{0}" + + + Open url in {0} + Failed to open {0}. diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/WebSearchCommandsProvider.cs b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/WebSearchCommandsProvider.cs index 7772d9b8b3..6768ff8baf 100644 --- a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/WebSearchCommandsProvider.cs +++ b/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/WebSearchCommandsProvider.cs @@ -14,6 +14,7 @@ public partial class WebSearchCommandsProvider : CommandProvider { private readonly SettingsManager _settingsManager = new(); private readonly FallbackExecuteSearchItem _fallbackItem; + private readonly FallbackOpenURLItem _openUrlFallbackItem; public WebSearchCommandsProvider() { @@ -23,6 +24,7 @@ public partial class WebSearchCommandsProvider : CommandProvider Settings = _settingsManager.Settings; _fallbackItem = new FallbackExecuteSearchItem(_settingsManager); + _openUrlFallbackItem = new FallbackOpenURLItem(_settingsManager); } public override ICommandItem[] TopLevelCommands() @@ -36,5 +38,5 @@ public partial class WebSearchCommandsProvider : CommandProvider ]; } - public override IFallbackCommandItem[]? FallbackCommands() => [_fallbackItem]; + public override IFallbackCommandItem[]? FallbackCommands() => [_openUrlFallbackItem, _fallbackItem]; } From 55f8f3a53efcee4868d4c3166b1ba4d80a804eb8 Mon Sep 17 00:00:00 2001 From: Davide Giacometti <25966642+davidegiacometti@users.noreply.github.com> Date: Thu, 10 Apr 2025 23:44:54 +0200 Subject: [PATCH 05/70] [CmdPal] Tray icon settings (#38672) ## Summary of the Pull Request Added a settings to enable/disable the system tray icon (enabled by default). Adopter the term "system tray icon" for consistency with Windows 11 settings. ## PR Checklist - [x] **Closes:** #38407 --- .../SettingsModel.cs | 2 + .../SettingsViewModel.cs | 10 +++ .../Microsoft.CmdPal.UI/MainWindow.xaml.cs | 72 ++++++++++--------- .../Settings/GeneralPage.xaml | 4 ++ .../Strings/en-us/Resources.resw | 6 ++ 5 files changed, 60 insertions(+), 34 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs index 785c27c3c9..86612e83aa 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs @@ -36,6 +36,8 @@ public partial class SettingsModel : ObservableObject public bool HighlightSearchOnActivate { get; set; } = true; + public bool ShowSystemTrayIcon { get; set; } = true; + public Dictionary ProviderSettings { get; set; } = []; public Dictionary Aliases { get; set; } = []; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs index 190d75b0c3..c66c07c47b 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs @@ -87,6 +87,16 @@ public partial class SettingsViewModel : INotifyPropertyChanged } } + public bool ShowSystemTrayIcon + { + get => _settings.ShowSystemTrayIcon; + set + { + _settings.ShowSystemTrayIcon = value; + Save(); + } + } + public ObservableCollection CommandProviders { get; } = []; public SettingsViewModel(SettingsModel settings, IServiceProvider serviceProvider, TaskScheduler scheduler) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index ac1b0e0860..2ec74b37f2 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -54,7 +54,6 @@ public sealed partial class MainWindow : Window, // Notification Area ("Tray") icon data private NOTIFYICONDATAW? _trayIconData; - private bool _createdIcon; private DestroyIconSafeHandle? _largeIcon; private DesktopAcrylicController? _acrylicController; @@ -99,7 +98,6 @@ public sealed partial class MainWindow : Window, _hotkeyWndProc = HotKeyPrc; var hotKeyPrcPointer = Marshal.GetFunctionPointerForDelegate(_hotkeyWndProc); _originalWndProc = Marshal.GetDelegateForFunctionPointer(PInvoke.SetWindowLongPtr(_hwnd, WINDOW_LONG_PTR_INDEX.GWL_WNDPROC, hotKeyPrcPointer)); - AddNotificationIcon(); // Load our settings, and then also wire up a settings changed handler HotReloadSettings(); @@ -149,6 +147,7 @@ public sealed partial class MainWindow : Window, var settings = App.Current.Services.GetService()!; SetupHotkey(settings); + SetupTrayIcon(settings.ShowSystemTrayIcon); // This will prevent our window from appearing in alt+tab or the taskbar. // You'll _need_ to use the hotkey to summon it. @@ -299,7 +298,7 @@ public sealed partial class MainWindow : Window, var extensionService = serviceProvider.GetService()!; extensionService.SignalStopExtensionsAsync(); - RemoveNotificationIcon(); + RemoveTrayIcon(); // WinUI bug is causing a crash on shutdown when FailFastOnErrors is set to true (#51773592). // Workaround by turning it off before shutdown. @@ -491,9 +490,9 @@ public sealed partial class MainWindow : Window, // WM_WINDOWPOSCHANGING which is always received on explorer startup sequence. case PInvoke.WM_WINDOWPOSCHANGING: { - if (!_createdIcon) + if (_trayIconData == null) { - AddNotificationIcon(); + SetupTrayIcon(); } } @@ -505,7 +504,7 @@ public sealed partial class MainWindow : Window, { // Handle the case where explorer.exe restarts. // Even if we created it before, do it again - AddNotificationIcon(); + SetupTrayIcon(); } else if (uMsg == WM_TRAY_ICON) { @@ -525,55 +524,60 @@ public sealed partial class MainWindow : Window, return PInvoke.CallWindowProc(_originalWndProc, hwnd, uMsg, wParam, lParam); } - private void AddNotificationIcon() + private void SetupTrayIcon(bool? showSystemTrayIcon = null) { - // We only need to build the tray data once. - if (_trayIconData == null) + if (showSystemTrayIcon ?? App.Current.Services.GetService()!.ShowSystemTrayIcon) { - // We need to stash this handle, so it doesn't clean itself up. If - // explorer restarts, we'll come back through here, and we don't - // really need to re-load the icon in that case. We can just use - // the handle from the first time. - _largeIcon = GetAppIconHandle(); - _trayIconData = new NOTIFYICONDATAW() + // We only need to build the tray data once. + if (_trayIconData == null) { - cbSize = (uint)Marshal.SizeOf(typeof(NOTIFYICONDATAW)), - hWnd = _hwnd, - uID = MY_NOTIFY_ID, - uFlags = NOTIFY_ICON_DATA_FLAGS.NIF_MESSAGE | NOTIFY_ICON_DATA_FLAGS.NIF_ICON | NOTIFY_ICON_DATA_FLAGS.NIF_TIP, - uCallbackMessage = WM_TRAY_ICON, - hIcon = (HICON)_largeIcon.DangerousGetHandle(), - szTip = RS_.GetString("AppStoreName"), - }; + // We need to stash this handle, so it doesn't clean itself up. If + // explorer restarts, we'll come back through here, and we don't + // really need to re-load the icon in that case. We can just use + // the handle from the first time. + _largeIcon = GetAppIconHandle(); + _trayIconData = new NOTIFYICONDATAW() + { + cbSize = (uint)Marshal.SizeOf(typeof(NOTIFYICONDATAW)), + hWnd = _hwnd, + uID = MY_NOTIFY_ID, + uFlags = NOTIFY_ICON_DATA_FLAGS.NIF_MESSAGE | NOTIFY_ICON_DATA_FLAGS.NIF_ICON | NOTIFY_ICON_DATA_FLAGS.NIF_TIP, + uCallbackMessage = WM_TRAY_ICON, + hIcon = (HICON)_largeIcon.DangerousGetHandle(), + szTip = RS_.GetString("AppStoreName"), + }; + } + + var d = (NOTIFYICONDATAW)_trayIconData; + + // Add the notification icon + PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_ADD, in d); } - - var d = (NOTIFYICONDATAW)_trayIconData; - - // Add the notification icon - if (PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_ADD, in d)) + else { - _createdIcon = true; + RemoveTrayIcon(); } } - private void RemoveNotificationIcon() + private void RemoveTrayIcon() { - if (_trayIconData != null && _createdIcon) + if (_trayIconData != null) { var d = (NOTIFYICONDATAW)_trayIconData; if (PInvoke.Shell_NotifyIcon(NOTIFY_ICON_MESSAGE.NIM_DELETE, in d)) { - _createdIcon = false; + _trayIconData = null; } } + + _largeIcon?.Close(); } private DestroyIconSafeHandle GetAppIconHandle() { var exePath = System.Reflection.Assembly.GetExecutingAssembly().Location; DestroyIconSafeHandle largeIcon; - DestroyIconSafeHandle smallIcon; - PInvoke.ExtractIconEx(exePath, 0, out largeIcon, out smallIcon, 1); + PInvoke.ExtractIconEx(exePath, 0, out largeIcon, out _, 1); return largeIcon; } } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml index e8a36e618a..8494bed1e1 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml @@ -68,6 +68,10 @@ + + + + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw index 03e8c40eaa..0a4000997a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw @@ -385,4 +385,10 @@ Right-click to remove the key combination, thereby deactivating the shortcut. Behavior + + Show system tray icon + + + Choose if Command Palette is visible in the system tray + \ No newline at end of file From 4cb72ee126caf1f720c507f6a1dbe658cd515366 Mon Sep 17 00:00:00 2001 From: Gordon Lam <73506701+yeelam-gordon@users.noreply.github.com> Date: Thu, 10 Apr 2025 21:58:10 -0700 Subject: [PATCH 06/70] Add Zhiwei as part of PowerToys! (#38744) * Add Zhiwei as part of PowerToys! * Fix the expect.txt for Zhiwei * Fix the case problem on expect.txt zhiwei => Zhiwei --- .github/actions/spell-check/expect.txt | 1 + COMMUNITY.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index b688d6bae0..e87b37fc78 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1988,6 +1988,7 @@ YStr YTM YVIRTUALSCREEN ZEROINIT +Zhiwei zonable zoneset Zoneszonabletester diff --git a/COMMUNITY.md b/COMMUNITY.md index 3e7cd6719e..ccfa61decf 100644 --- a/COMMUNITY.md +++ b/COMMUNITY.md @@ -188,6 +188,7 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter - [@cinnamon-msft](https://github.com/cinnamon-msft) - Kayla Cinnamon - Lead - [@nguyen-dows](https://github.com/nguyen-dows) - Christopher Nguyen - Product Manager - [@craigloewen-msft](https://github.com/craigloewen-msft) - Craig Loewen - Product Manager +- [@zhiwei-ms](https://github.com/zhiwei-ms) - Zhiwei Yu - Product Manager - [@dhowett](https://github.com/dhowett) - Dustin Howett - Dev lead - [@yeelam-gordon](https://github.com/yeelam-gordon) - Gordon Lam - Dev lead - [@jamrobot](https://github.com/jamrobot) - Jerry Xu - Dev lead From b32c04fca191bd6e37be1a9c6df46a31a1a835ef Mon Sep 17 00:00:00 2001 From: ruslanlap <106077551+ruslanlap@users.noreply.github.com> Date: Fri, 11 Apr 2025 21:45:25 +0300 Subject: [PATCH 07/70] [PowerToysRun][Docs] Add QuickNotes to Third-Party plugins (#38663) * Add QuickNotes plugin to third-party Run plugins documentation * chore: add ruslanlap to spelling allow-list * chore: add ruslanlap to spelling allow-list * chore: add ruslanlap to spelling allow-list * Add ruslanlap to allowed names and remove from expected words list --- .github/actions/spell-check/allow/names.txt | 1 + .github/actions/spell-check/expect.txt | 48 ++------------------- doc/thirdPartyRunPlugins.md | 1 + 3 files changed, 5 insertions(+), 45 deletions(-) diff --git a/.github/actions/spell-check/allow/names.txt b/.github/actions/spell-check/allow/names.txt index 44131fecfb..289da43b14 100644 --- a/.github/actions/spell-check/allow/names.txt +++ b/.github/actions/spell-check/allow/names.txt @@ -188,6 +188,7 @@ zhaoqpcn Zoltan Zykova Sameerjs +ruslanlap # OTHERS diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index e87b37fc78..8fb29864f3 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -56,12 +56,10 @@ APIIs Apm APPBARDATA APPEXECLINK -APPICONREFERENCE APPLICATIONFRAMEHOST appmanifest APPMODEL APPNAME -APPPUBLISHER appref appsettings appwindow @@ -173,7 +171,6 @@ CCHFORMNAME CCom CContext CDeclaration -cdn CElems CENTERALIGN certlm @@ -254,8 +251,6 @@ createdump CREATEPROCESS CREATESCHEDULEDTASK CREATESTRUCT -CREATETHREAD -CREATEWINDOW CREATEWINDOWFAILED CRECT CRH @@ -308,11 +303,7 @@ DCOM DComposition DCR ddd -DDEAPPLICATION -DDECOMMAND DDEIf -DDEIFEXEC -DDETOPIC DDevice DDxgi Deact @@ -326,16 +317,13 @@ DEFAULTFLAGS DEFAULTICON defaultlib DEFAULTONLY -DEFAULTTOFOLDER DEFAULTTONEAREST DEFAULTTONULL DEFAULTTOPRIMARY -DEFAULTTOSTAR DEFERERASE DEFPUSHBUTTON deinitialization DELA -DELEGATEEXECUTE DELETEDKEYIMAGE DELETESCANS deletethis @@ -389,7 +377,6 @@ dreamsofameaningfullife drivedetectionwarning Droid DROPFILES -DROPTARGET DSTINVERT DSurface DTexture @@ -510,12 +497,10 @@ Fira FIXEDFILEINFO FIXEDSYS flac -flaticon flyouts FMask fmtid FOF -WANTNUKEWARNING FOFX FOLDERID folderpath @@ -525,7 +510,6 @@ FORCEMINIMIZE FORMATDLGORD formatetc FORPARSING -fpvm Fqc FRAMECHANGED frm @@ -559,7 +543,6 @@ GETSECKEY GETSTICKYKEYS GETTEXTLENGTH GHND -gifv GMEM GNumber gpedit @@ -653,7 +636,6 @@ HROW hsb HSCROLL hsi -HSSH HTCLIENT hthumbnail HTOUCHINPUT @@ -691,7 +673,6 @@ iextn IFACEMETHOD IFACEMETHODIMP IFile -IGNOREBASECLASS IGNOREUNKNOWN IGo iid @@ -740,8 +721,6 @@ Inste Interlop INTRESOURCE INVALIDARG -INVALIDCALL -INVALIDINDEX invalidoperatioexception ipcmanager IPREVIEW @@ -803,7 +782,6 @@ LEVELID LExit lhwnd LIBID -libraryincludes LIMITSIZE LIMITTEXT lindex @@ -905,7 +883,6 @@ MBM MBR MDICHILD MDL -mdpvm mdtext mdtxt mdwn @@ -1053,7 +1030,6 @@ NOCRLF nodeca NODRAWCAPTION NODRAWICON -NOFIXUPS NOINHERITLAYOUT NOINTERFACE NOINVERT @@ -1069,13 +1045,11 @@ NONELEVATED NONINFRINGEMENT nonspace nonstd -NOOPEN NOOWNERZORDER NOPARENTNOTIFY NOPREFIX NOREDIRECTIONBITMAP NOREDRAW -NOREMAPCLSID NOREMOVE norename NOREPEAT @@ -1094,11 +1068,9 @@ NOTIFYICONDATAW NOTIMPL NOTOPMOST NOTRACK -NOTRUNCATE NOTSRCCOPY NOTSRCERASE NOTXORPEN -NOUSERSETTINGS NOZORDER NPH npmjs @@ -1318,7 +1290,6 @@ Quarternary QUERYENDSESSION QUERYOPEN QUEUESYNC -QUICKTIP QUNS QXZ RAII @@ -1347,7 +1318,6 @@ REFCLSID REFIID REGCLS regfile -REGISTERCLASSEX REGISTERCLASSFAILED REGISTRYHEADER registrypath @@ -1359,7 +1329,6 @@ REINSTALLMODE reloadable Relogger remappings -REMAPRUNDLL REMAPSUCCESSFUL REMAPUNSUCCESSFUL Remotable @@ -1436,7 +1405,6 @@ SDDL SDKDDK sdns searchterm -searchtext SEARCHUI SECONDARYDISPLAY secpol @@ -1484,8 +1452,6 @@ SHELLDLL shellex SHELLEXECUTEINFO SHELLEXECUTEINFOW -SHELLEXTENSION -SHELLNEWVALUE SHFILEINFO SHFILEOPSTRUCT SHGDN @@ -1495,7 +1461,6 @@ SHGFIICON SHGFILARGEICON shinfo shlwapi -SHNAMEMAPPING shobjidl SHORTCUTATLEAST SHORTCUTMAXONEACTIONKEY @@ -1546,7 +1511,6 @@ SNAPPROCESS snwprintf softline SOURCECLIENTAREAONLY -sourced sourcedoc SOURCEHEADER sourcesdirectory @@ -1685,7 +1649,6 @@ THotkey throughs TIcon TILEDWINDOW -TILEINFO TILLSON timedate timediff @@ -1699,9 +1662,6 @@ TLayout tlb tlbimp tlc -TPMLEFTALIGN -TPMRETURNCMD -TMPVAR TNP Toolhelp toolkitconverters @@ -1709,6 +1669,8 @@ toolwindow TOPDOWNDIB TOUCHEVENTF TOUCHINPUT +TPMLEFTALIGN +TPMRETURNCMD TRACEHANDLE tracelogging tracerpt @@ -1782,7 +1744,6 @@ USRDLL UType uuidv uwp -ums uxt uxtheme vabdq @@ -1809,7 +1770,6 @@ VERTSIZE VFT vget vgetq -videourl viewmodel VIRTKEY VIRTUALDESK @@ -1843,7 +1803,7 @@ vstprintf VSTT vswhere Vtbl -WANTMAPPINGHANDLE +WANTNUKEWARNING WANTPALM wasdk wbem @@ -1958,7 +1918,6 @@ WUX Wwanpp XAxis xclip -xdoc XDocument XElement xfd @@ -1981,7 +1940,6 @@ Yeet YIncrement yinle yinyue -youtube YPels YResolution YStr diff --git a/doc/thirdPartyRunPlugins.md b/doc/thirdPartyRunPlugins.md index 90966ead20..03bafa1c66 100644 --- a/doc/thirdPartyRunPlugins.md +++ b/doc/thirdPartyRunPlugins.md @@ -43,6 +43,7 @@ Contact the developers of a plugin directly for assistance with a specific plugi | [TailwindCSS](https://github.com/skttl/ptrun-tailwindcss) | [skttl](https://github.com/skttl) | Search the documentation of TailwindCSS | | [HttpStatusCodes](https://github.com/grzhan/HttpStatusCodePowerToys) | [grzhan](https://github.com/grzhan) | Search for http status codes | | [SVGL](https://github.com/Sameerjs6/powertoys-svgl) | [SameerJS6](https://github.com/SameerJS6) | Search, Browse and copy SVG logos from SVGL. | +| [QuickNotes](https://github.com/ruslanlap/CommunityPowerToysRunPlugin-QuickNotes) | [ruslanlap](https://github.com/ruslanlap) | Create, manage, and search notes directly from PowerToys Run. | ## Extending software plugins From 5c8aa67781eb88cd8995c736e9609904b20d536b Mon Sep 17 00:00:00 2001 From: Muhammad Danish Date: Mon, 14 Apr 2025 04:19:22 +0500 Subject: [PATCH 08/70] Add securityContext to configuration files (#38017) For the winget DSC, Setting developer mode, installing Visual Studio 2022 & fetching and installing VS components all require elevation. Added securityContext: elevated for these resources. These configurations can now be invoked from user context, and will prompt for a single UAC to run resources that require elevation in a separate process. --- .config/configuration.vsEnterprise.winget | 6 ++++++ .config/configuration.vsProfessional.winget | 6 ++++++ .config/configuration.winget | 6 ++++++ 3 files changed, 18 insertions(+) diff --git a/.config/configuration.vsEnterprise.winget b/.config/configuration.vsEnterprise.winget index 84e05ed511..4d19d37137 100644 --- a/.config/configuration.vsEnterprise.winget +++ b/.config/configuration.vsEnterprise.winget @@ -6,12 +6,16 @@ properties: directives: description: Enable Developer Mode allowPrerelease: true + # Requires elevation for the set operation + securityContext: elevated settings: Ensure: Present - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage directives: description: Install Visual Studio 2022 Enterprise (Any edition will work) + # Requires elevation for the set operation + securityContext: elevated settings: id: Microsoft.VisualStudio.2022.Enterprise source: winget @@ -21,6 +25,8 @@ properties: directives: description: Install required VS workloads allowPrerelease: true + # Requires elevation for the get and set operations + securityContext: elevated settings: productId: Microsoft.VisualStudio.Product.Enterprise channelId: VisualStudio.17.Release diff --git a/.config/configuration.vsProfessional.winget b/.config/configuration.vsProfessional.winget index 6ac0babf9f..78fb1c13d5 100644 --- a/.config/configuration.vsProfessional.winget +++ b/.config/configuration.vsProfessional.winget @@ -6,12 +6,16 @@ properties: directives: description: Enable Developer Mode allowPrerelease: true + # Requires elevation for the set operation + securityContext: elevated settings: Ensure: Present - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage directives: description: Install Visual Studio 2022 Professional (Any edition will work) + # Requires elevation for the set operation + securityContext: elevated settings: id: Microsoft.VisualStudio.2022.Professional source: winget @@ -21,6 +25,8 @@ properties: directives: description: Install required VS workloads allowPrerelease: true + # Requires elevation for the get and set operations + securityContext: elevated settings: productId: Microsoft.VisualStudio.Product.Professional channelId: VisualStudio.17.Release diff --git a/.config/configuration.winget b/.config/configuration.winget index df3eeea441..456eca47f2 100644 --- a/.config/configuration.winget +++ b/.config/configuration.winget @@ -6,12 +6,16 @@ properties: directives: description: Enable Developer Mode allowPrerelease: true + # Requires elevation for the set operation + securityContext: elevated settings: Ensure: Present - resource: Microsoft.WinGet.DSC/WinGetPackage id: vsPackage directives: description: Install Visual Studio 2022 Community (Any edition will work) + # Requires elevation for the set operation + securityContext: elevated settings: id: Microsoft.VisualStudio.2022.Community source: winget @@ -21,6 +25,8 @@ properties: directives: description: Install required VS workloads allowPrerelease: true + # Requires elevation for the get and set operations + securityContext: elevated settings: productId: Microsoft.VisualStudio.Product.Community channelId: VisualStudio.17.Release From 03bc72c4369311176fa4b66b1b494478f331919f Mon Sep 17 00:00:00 2001 From: Bennett Blodinger Date: Sun, 13 Apr 2025 18:20:43 -0500 Subject: [PATCH 09/70] Change log extension from .txt => .log (#33813) * Change log extension From .txt to .log * Also add workspace logs --------- Co-authored-by: Jaime Bernardo --- src/common/AllExperiments/Logger.cs | 2 +- src/common/ManagedCommon/Logger.cs | 2 +- src/common/logger/logger_settings.h | 60 ++++++++++++++--------------- src/common/utils/logger_helper.h | 2 +- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/common/AllExperiments/Logger.cs b/src/common/AllExperiments/Logger.cs index 7604618bdf..b9e1f20969 100644 --- a/src/common/AllExperiments/Logger.cs +++ b/src/common/AllExperiments/Logger.cs @@ -25,7 +25,7 @@ namespace AllExperiments } // Using InvariantCulture since this is used for a log file name - var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt"); + var logFilePath = Path.Combine(ApplicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log"); Trace.Listeners.Add(new TextWriterTraceListener(logFilePath)); diff --git a/src/common/ManagedCommon/Logger.cs b/src/common/ManagedCommon/Logger.cs index b67d63c3b5..cd85d500e1 100644 --- a/src/common/ManagedCommon/Logger.cs +++ b/src/common/ManagedCommon/Logger.cs @@ -54,7 +54,7 @@ namespace ManagedCommon Directory.CreateDirectory(applicationLogPath); } - var logFilePath = Path.Combine(applicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".txt"); + var logFilePath = Path.Combine(applicationLogPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log"); Trace.Listeners.Add(new TextWriterTraceListener(logFilePath)); diff --git a/src/common/logger/logger_settings.h b/src/common/logger/logger_settings.h index dab7ad64a2..c880614237 100644 --- a/src/common/logger/logger_settings.h +++ b/src/common/logger/logger_settings.h @@ -8,49 +8,49 @@ struct LogSettings inline const static std::wstring logLevelOption = L"logLevel"; inline const static std::string runnerLoggerName = "runner"; inline const static std::wstring logPath = L"Logs\\"; - inline const static std::wstring runnerLogPath = L"RunnerLogs\\runner-log.txt"; + inline const static std::wstring runnerLogPath = L"RunnerLogs\\runner-log.log"; inline const static std::string actionRunnerLoggerName = "action-runner"; - inline const static std::wstring actionRunnerLogPath = L"RunnerLogs\\action-runner-log.txt"; + inline const static std::wstring actionRunnerLogPath = L"RunnerLogs\\action-runner-log.log"; inline const static std::string updateLoggerName = "update"; - inline const static std::wstring updateLogPath = L"UpdateLogs\\update-log.txt"; + inline const static std::wstring updateLogPath = L"UpdateLogs\\update-log.log"; inline const static std::string fileExplorerLoggerName = "FileExplorer"; - inline const static std::wstring fileExplorerLogPath = L"Logs\\file-explorer-log.txt"; + inline const static std::wstring fileExplorerLogPath = L"Logs\\file-explorer-log.log"; inline const static std::string gcodePrevLoggerName = "GcodePrevHandler"; - inline const static std::wstring gcodePrevLogPath = L"logs\\FileExplorer_localLow\\GcodePreviewHandler\\gcode-prev-handler-log.txt"; + inline const static std::wstring gcodePrevLogPath = L"logs\\FileExplorer_localLow\\GcodePreviewHandler\\gcode-prev-handler-log.log"; inline const static std::string gcodeThumbLoggerName = "GcodeThumbnailProvider"; - inline const static std::wstring gcodeThumbLogPath = L"logs\\FileExplorer_localLow\\GcodeThumbnailProvider\\gcode-thumbnail-provider-log.txt"; + inline const static std::wstring gcodeThumbLogPath = L"logs\\FileExplorer_localLow\\GcodeThumbnailProvider\\gcode-thumbnail-provider-log.log"; inline const static std::string mdPrevLoggerName = "MDPrevHandler"; - inline const static std::wstring mdPrevLogPath = L"logs\\FileExplorer_localLow\\MDPrevHandler\\md-prev-handler-log.txt"; + inline const static std::wstring mdPrevLogPath = L"logs\\FileExplorer_localLow\\MDPrevHandler\\md-prev-handler-log.log"; inline const static std::string monacoPrevLoggerName = "MonacoPrevHandler"; - inline const static std::wstring monacoPrevLogPath = L"logs\\FileExplorer_localLow\\MonacoPrevHandler\\monaco-prev-handler-log.txt"; + inline const static std::wstring monacoPrevLogPath = L"logs\\FileExplorer_localLow\\MonacoPrevHandler\\monaco-prev-handler-log.log"; inline const static std::string pdfPrevLoggerName = "PdfPrevHandler"; - inline const static std::wstring pdfPrevLogPath = L"logs\\FileExplorer_localLow\\PdfPrevHandler\\pdf-prev-handler-log.txt"; + inline const static std::wstring pdfPrevLogPath = L"logs\\FileExplorer_localLow\\PdfPrevHandler\\pdf-prev-handler-log.log"; inline const static std::string pdfThumbLoggerName = "PdfThumbnailProvider"; - inline const static std::wstring pdfThumbLogPath = L"logs\\FileExplorer_localLow\\PdfThumbnailProvider\\pdf-thumbnail-provider-log.txt"; + inline const static std::wstring pdfThumbLogPath = L"logs\\FileExplorer_localLow\\PdfThumbnailProvider\\pdf-thumbnail-provider-log.log"; inline const static std::string qoiPrevLoggerName = "QoiPrevHandler"; - inline const static std::wstring qoiPrevLogPath = L"logs\\FileExplorer_localLow\\QoiPreviewHandler\\qoi-prev-handler-log.txt"; + inline const static std::wstring qoiPrevLogPath = L"logs\\FileExplorer_localLow\\QoiPreviewHandler\\qoi-prev-handler-log.log"; inline const static std::string qoiThumbLoggerName = "QoiThumbnailProvider"; - inline const static std::wstring qoiThumbLogPath = L"logs\\FileExplorer_localLow\\QoiThumbnailProvider\\qoi-thumbnail-provider-log.txt"; + inline const static std::wstring qoiThumbLogPath = L"logs\\FileExplorer_localLow\\QoiThumbnailProvider\\qoi-thumbnail-provider-log.log"; inline const static std::string stlThumbLoggerName = "StlThumbnailProvider"; - inline const static std::wstring stlThumbLogPath = L"logs\\FileExplorer_localLow\\StlThumbnailProvider\\stl-thumbnail-provider-log.txt"; + inline const static std::wstring stlThumbLogPath = L"logs\\FileExplorer_localLow\\StlThumbnailProvider\\stl-thumbnail-provider-log.log"; inline const static std::string svgPrevLoggerName = "SvgPrevHandler"; - inline const static std::wstring svgPrevLogPath = L"logs\\FileExplorer_localLow\\SvgPrevHandler\\svg-prev-handler-log.txt"; + inline const static std::wstring svgPrevLogPath = L"logs\\FileExplorer_localLow\\SvgPrevHandler\\svg-prev-handler-log.log"; inline const static std::string svgThumbLoggerName = "SvgThumbnailProvider"; - inline const static std::wstring svgThumbLogPath = L"logs\\FileExplorer_localLow\\SvgThumbnailProvider\\svg-thumbnail-provider-log.txt"; + inline const static std::wstring svgThumbLogPath = L"logs\\FileExplorer_localLow\\SvgThumbnailProvider\\svg-thumbnail-provider-log.log"; inline const static std::string launcherLoggerName = "launcher"; - inline const static std::wstring launcherLogPath = L"LogsModuleInterface\\launcher-log.txt"; + inline const static std::wstring launcherLogPath = L"LogsModuleInterface\\launcher-log.log"; inline const static std::string mouseWithoutBordersLoggerName = "mouseWithoutBorders"; - inline const static std::wstring mouseWithoutBordersLogPath = L"LogsModuleInterface\\mouseWithoutBorders-log.txt"; - inline const static std::wstring awakeLogPath = L"Logs\\awake-log.txt"; - inline const static std::wstring powerAccentLogPath = L"quick-accent-log.txt"; + inline const static std::wstring mouseWithoutBordersLogPath = L"LogsModuleInterface\\mouseWithoutBorders-log.log"; + inline const static std::wstring awakeLogPath = L"Logs\\awake-log.log"; + inline const static std::wstring powerAccentLogPath = L"quick-accent-log.log"; inline const static std::string fancyZonesLoggerName = "fancyzones"; - inline const static std::wstring fancyZonesLogPath = L"fancyzones-log.txt"; + inline const static std::wstring fancyZonesLogPath = L"fancyzones-log.log"; inline const static std::wstring fancyZonesOldLogPath = L"FancyZonesLogs\\"; // needed to clean up old logs inline const static std::string shortcutGuideLoggerName = "shortcut-guide"; - inline const static std::wstring shortcutGuideLogPath = L"ShortcutGuideLogs\\shortcut-guide-log.txt"; - inline const static std::wstring powerOcrLogPath = L"Logs\\text-extractor-log.txt"; + inline const static std::wstring shortcutGuideLogPath = L"ShortcutGuideLogs\\shortcut-guide-log.log"; + inline const static std::wstring powerOcrLogPath = L"Logs\\text-extractor-log.log"; inline const static std::string keyboardManagerLoggerName = "keyboard-manager"; - inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.txt"; + inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.log"; inline const static std::string findMyMouseLoggerName = "find-my-mouse"; inline const static std::string mouseHighlighterLoggerName = "mouse-highlighter"; inline const static std::string mouseJumpLoggerName = "mouse-jump"; @@ -60,22 +60,22 @@ struct LogSettings inline const static std::string alwaysOnTopLoggerName = "always-on-top"; inline const static std::string powerOcrLoggerName = "TextExtractor"; inline const static std::string fileLocksmithLoggerName = "FileLocksmith"; - inline const static std::wstring alwaysOnTopLogPath = L"always-on-top-log.txt"; + inline const static std::wstring alwaysOnTopLogPath = L"always-on-top-log.log"; inline const static std::string hostsLoggerName = "hosts"; - inline const static std::wstring hostsLogPath = L"Logs\\hosts-log.txt"; + inline const static std::wstring hostsLogPath = L"Logs\\hosts-log.log"; inline const static std::string registryPreviewLoggerName = "registrypreview"; inline const static std::string cropAndLockLoggerName = "crop-and-lock"; - inline const static std::wstring registryPreviewLogPath = L"Logs\\registryPreview-log.txt"; + inline const static std::wstring registryPreviewLogPath = L"Logs\\registryPreview-log.log"; inline const static std::string environmentVariablesLoggerName = "environment-variables"; - inline const static std::wstring cmdNotFoundLogPath = L"Logs\\cmd-not-found-log.txt"; + inline const static std::wstring cmdNotFoundLogPath = L"Logs\\cmd-not-found-log.log"; inline const static std::string cmdNotFoundLoggerName = "cmd-not-found"; inline const static std::string newLoggerName = "NewPlus"; inline const static std::string workspacesLauncherLoggerName = "workspaces-launcher"; - inline const static std::wstring workspacesLauncherLogPath = L"workspaces-launcher-log.txt"; + inline const static std::wstring workspacesLauncherLogPath = L"workspaces-launcher-log.log"; inline const static std::string workspacesWindowArrangerLoggerName = "workspaces-window-arranger"; - inline const static std::wstring workspacesWindowArrangerLogPath = L"workspaces-window-arranger-log.txt"; + inline const static std::wstring workspacesWindowArrangerLogPath = L"workspaces-window-arranger-log.log"; inline const static std::string workspacesSnapshotToolLoggerName = "workspaces-snapshot-tool"; - inline const static std::wstring workspacesSnapshotToolLogPath = L"workspaces-snapshot-tool-log.txt"; + inline const static std::wstring workspacesSnapshotToolLogPath = L"workspaces-snapshot-tool-log.log"; inline const static std::string zoomItLoggerName = "zoom-it"; inline const static int retention = 30; std::wstring logLevel; diff --git a/src/common/utils/logger_helper.h b/src/common/utils/logger_helper.h index c2207525e3..2deec22155 100644 --- a/src/common/utils/logger_helper.h +++ b/src/common/utils/logger_helper.h @@ -91,7 +91,7 @@ namespace LoggerHelpers currentFolder.append(get_product_version()); auto logsPath = currentFolder; - logsPath.append(L"log.txt"); + logsPath.append(L"log.log"); Logger::init(loggerName, logsPath.wstring(), PTSettingsHelper::get_log_settings_file_location()); delete_other_versions_log_folders(rootFolder.wstring(), currentFolder); From 662f04ed34da0fb8e074a6912e85b9afefd03371 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ionu=C8=9B=20Man=C8=9Ba?= Date: Mon, 14 Apr 2025 01:48:10 -0700 Subject: [PATCH 10/70] [KeyboardManager] Fix modifier Key (Not right or left) stuck (#37930) * Fix ctr,alt,shift getting stuck * more changes * Update src/modules/keyboardmanager/common/Helpers.h Co-authored-by: Hao Liu --------- Co-authored-by: Hao Liu --- .../EditorHelpers.cpp | 6 +- .../KeyboardEventHandlers.cpp | 94 +++++++++++-------- .../KeyboardManagerEngineLibrary/trace.cpp | 6 +- .../keyboardmanager/common/Helpers.cpp | 34 +++---- src/modules/keyboardmanager/common/Helpers.h | 4 +- .../common/KeyboardManagerCommon.vcxproj | 1 + .../KeyboardManagerCommon.vcxproj.filters | 3 + .../keyboardmanager/common/Modifiers.h | 26 +++++ .../keyboardmanager/common/RemapShortcut.h | 11 ++- .../keyboardmanager/common/Shortcut.cpp | 42 +++++++-- src/modules/keyboardmanager/common/Shortcut.h | 7 +- 11 files changed, 153 insertions(+), 81 deletions(-) create mode 100644 src/modules/keyboardmanager/common/Modifiers.h diff --git a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditorHelpers.cpp b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditorHelpers.cpp index 059d8931cc..1874899c1b 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditorHelpers.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEditorLibrary/EditorHelpers.cpp @@ -117,15 +117,15 @@ namespace EditorHelpers } if (shortcut.ctrlKey != ModifierKey::Disabled) { - keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetCtrlKey()).c_str())); + keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetCtrlKey(ModifierKey::Both)).c_str())); } if (shortcut.altKey != ModifierKey::Disabled) { - keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetAltKey()).c_str())); + keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetAltKey(ModifierKey::Both)).c_str())); } if (shortcut.shiftKey != ModifierKey::Disabled) { - keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetShiftKey()).c_str())); + keys.push_back(winrt::to_hstring(keyboardMap.GetKeyName(shortcut.GetShiftKey(ModifierKey::Both)).c_str())); } if (shortcut.actionKey != NULL) { diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp index 537e9016ac..080fcc16c2 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/KeyboardEventHandlers.cpp @@ -158,13 +158,13 @@ namespace KeyboardEventHandlers if (data->wParam == WM_KEYUP || data->wParam == WM_SYSKEYUP) { Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(targetShortcut.GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); - Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetModifierKeyEvents(targetShortcut, Modifiers(), keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); // Dummy key is not required here since SetModifierKeyEvents will only add key-up events for the modifiers here, and the action key key-up is already sent before it } else { // Dummy key is not required here since SetModifierKeyEvents will only add key-down events for the modifiers here, and the action key key-down is already sent after it - Helpers::SetModifierKeyEvents(targetShortcut, ModifierKey::Disabled, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); + Helpers::SetModifierKeyEvents(targetShortcut, Modifiers(), keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(targetShortcut.GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SINGLEKEY_FLAG); } } @@ -371,11 +371,35 @@ namespace KeyboardEventHandlers // Remember which win key was pressed initially if (ii.GetVirtualKeyState(VK_RWIN)) { - it->second.winKeyInvoked = ModifierKey::Right; + it->second.modifierKeysInvoked.winKey = ModifierKey::Right; } else if (ii.GetVirtualKeyState(VK_LWIN)) { - it->second.winKeyInvoked = ModifierKey::Left; + it->second.modifierKeysInvoked.winKey = ModifierKey::Left; + } + if (ii.GetVirtualKeyState(VK_RCONTROL)) + { + it->second.modifierKeysInvoked.ctrlKey = ModifierKey::Right; + } + else if (ii.GetVirtualKeyState(VK_LCONTROL)) + { + it->second.modifierKeysInvoked.ctrlKey = ModifierKey::Left; + } + if (ii.GetVirtualKeyState(VK_RSHIFT)) + { + it->second.modifierKeysInvoked.shiftKey = ModifierKey::Right; + } + else if (ii.GetVirtualKeyState(VK_LSHIFT)) + { + it->second.modifierKeysInvoked.shiftKey = ModifierKey::Left; + } + if (ii.GetVirtualKeyState(VK_RMENU)) + { + it->second.modifierKeysInvoked.altKey = ModifierKey::Right; + } + else if (ii.GetVirtualKeyState(VK_LMENU)) + { + it->second.modifierKeysInvoked.altKey = ModifierKey::Left; } if (isRunProgram) @@ -450,7 +474,7 @@ namespace KeyboardEventHandlers { // key down for all new shortcut keys except the common modifiers keyEventList = std::vector{}; - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } else @@ -460,15 +484,15 @@ namespace KeyboardEventHandlers Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release original shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); // Set new shortcut key down state - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Modifier state reset might be required for this key depending on the shortcut's action and target modifiers - ex: Win+Caps -> Ctrl+A - if (it->first.GetCtrlKey() == NULL && it->first.GetAltKey() == NULL && it->first.GetShiftKey() == NULL) + if (it->first.GetCtrlKey(it->second.modifierKeysInvoked.ctrlKey) == NULL && it->first.GetAltKey(it->second.modifierKeysInvoked.altKey) == NULL && it->first.GetShiftKey(it->second.modifierKeysInvoked.shiftKey) == NULL) { Shortcut temp = std::get(it->second.targetShortcut); for (auto keys : temp.GetKeyCodes()) @@ -490,7 +514,7 @@ namespace KeyboardEventHandlers Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release original shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Set target key down state if (std::get(it->second.targetShortcut) != CommonSharedConstants::VK_DISABLED) @@ -499,7 +523,7 @@ namespace KeyboardEventHandlers } // Modifier state reset might be required for this key depending on the shortcut's action and target modifier - ex: Win+Caps -> Ctrl - if (it->first.GetCtrlKey() == NULL && it->first.GetAltKey() == NULL && it->first.GetShiftKey() == NULL) + if (it->first.GetCtrlKey(it->second.modifierKeysInvoked.ctrlKey) == NULL && it->first.GetAltKey(it->second.modifierKeysInvoked.altKey) == NULL && it->first.GetShiftKey(it->second.modifierKeysInvoked.shiftKey) == NULL) { ResetIfModifierKeyForLowerLevelKeyHandlers(ii, static_cast(Helpers::FilterArtificialKeys(std::get(it->second.targetShortcut))), data->lParam->vkCode); } @@ -512,7 +536,7 @@ namespace KeyboardEventHandlers Helpers::SetDummyKeyEvent(keyEventList, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release original shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); Helpers::SetTextKeyEvents(keyEventList, remapping); } @@ -614,12 +638,12 @@ namespace KeyboardEventHandlers Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first, data->lParam->vkCode); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first, data->lParam->vkCode); if (!isAltRightKeyInvoked) { // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate its own key message - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut), data->lParam->vkCode); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut), data->lParam->vkCode); } else { @@ -643,7 +667,7 @@ namespace KeyboardEventHandlers if (!isAltRightKeyInvoked) { // Set original shortcut key down state except the action key and the released modifier since the original action key may or may not be held down. If it is held down it will generate its own key message - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, Shortcut(), data->lParam->vkCode); } else { @@ -656,7 +680,7 @@ namespace KeyboardEventHandlers // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; // If app specific shortcut has finished invoking, reset the target application @@ -719,14 +743,14 @@ namespace KeyboardEventHandlers Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(std::get(it->second.targetShortcut).GetActionKey()), KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); // Release new shortcut state (release in reverse order of shortcut to be accurate) - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); // Set old shortcut key down state - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; // If app specific shortcut has finished invoking, reset the target application @@ -763,7 +787,7 @@ namespace KeyboardEventHandlers if (!isAltRightKeyInvoked) { // Set original shortcut key down state except the action key - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Send a dummy key event to prevent modifier press+release from being triggered. Example: Win+A->V, press Shift+Win+A and release A, since Win will be pressed here we need to send a dummy event after it @@ -773,7 +797,7 @@ namespace KeyboardEventHandlers { // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; } @@ -795,7 +819,7 @@ namespace KeyboardEventHandlers if (remapToShortcut) { // Modifier state reset might be required for this key depending on the target shortcut action key - ex: Ctrl+A -> Win+Caps - if (std::get(it->second.targetShortcut).GetCtrlKey() == NULL && std::get(it->second.targetShortcut).GetAltKey() == NULL && std::get(it->second.targetShortcut).GetShiftKey() == NULL) + if (std::get(it->second.targetShortcut).GetCtrlKey(it->second.modifierKeysInvoked.ctrlKey) == NULL && std::get(it->second.targetShortcut).GetAltKey(it->second.modifierKeysInvoked.altKey) == NULL && std::get(it->second.targetShortcut).GetShiftKey(it->second.modifierKeysInvoked.shiftKey) == NULL) { ResetIfModifierKeyForLowerLevelKeyHandlers(ii, data->lParam->vkCode, std::get(it->second.targetShortcut).GetActionKey()); } @@ -817,7 +841,7 @@ namespace KeyboardEventHandlers if (remapToShortcut) { // Modifier state reset might be required for this key depending on the target shortcut action key - ex: Ctrl+A -> Win+Caps, Shift is pressed. System should not see Shift and Caps pressed together - if (std::get(it->second.targetShortcut).GetCtrlKey() == NULL && std::get(it->second.targetShortcut).GetAltKey() == NULL && std::get(it->second.targetShortcut).GetShiftKey() == NULL) + if (std::get(it->second.targetShortcut).GetCtrlKey(it->second.modifierKeysInvoked.ctrlKey) == NULL && std::get(it->second.targetShortcut).GetAltKey(it->second.modifierKeysInvoked.altKey) == NULL && std::get(it->second.targetShortcut).GetShiftKey(it->second.modifierKeysInvoked.shiftKey) == NULL) { ResetIfModifierKeyForLowerLevelKeyHandlers(ii, data->lParam->vkCode, std::get(it->second.targetShortcut).GetActionKey()); } @@ -837,7 +861,7 @@ namespace KeyboardEventHandlers DWORD to = std::get<0>(newRemapping.targetShortcut); if (!isAltRightKeyInvoked) { - Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(from, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } if (ii.GetVirtualKeyState(static_cast(from.actionKey))) { @@ -851,7 +875,7 @@ namespace KeyboardEventHandlers Shortcut to = std::get(newRemapping.targetShortcut); if (!isAltRightKeyInvoked) { - Helpers::SetModifierKeyEvents(from, it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, to); + Helpers::SetModifierKeyEvents(from, it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, to); } if (ii.GetVirtualKeyState(static_cast(from.actionKey))) { @@ -860,21 +884,11 @@ namespace KeyboardEventHandlers } if (!isAltRightKeyInvoked) { - Helpers::SetModifierKeyEvents(to, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, from); + Helpers::SetModifierKeyEvents(to, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, from); } Helpers::SetKeyEvent(keyEventList, INPUT_KEYBOARD, static_cast(to.actionKey), 0, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); newRemapping.isShortcutInvoked = true; } - - // Remember which win key was pressed initially - if (ii.GetVirtualKeyState(VK_RWIN)) - { - newRemapping.winKeyInvoked = ModifierKey::Right; - } - else if (ii.GetVirtualKeyState(VK_LWIN)) - { - newRemapping.winKeyInvoked = ModifierKey::Left; - } } else { @@ -888,10 +902,10 @@ namespace KeyboardEventHandlers } if (!isAltRightKeyInvoked) { - Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.winKeyInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); + Helpers::SetModifierKeyEvents(std::get(it->second.targetShortcut), it->second.modifierKeysInvoked, keyEventList, false, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, it->first); // Set old shortcut key down state - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG, std::get(it->second.targetShortcut)); } // key down for original shortcut action key with shortcut flag so that we don't invoke the same shortcut remap again @@ -910,7 +924,7 @@ namespace KeyboardEventHandlers { // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; } @@ -960,7 +974,7 @@ namespace KeyboardEventHandlers if (!isAltRightKeyInvoked) { // Set original shortcut key down state - Helpers::SetModifierKeyEvents(it->first, it->second.winKeyInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); + Helpers::SetModifierKeyEvents(it->first, it->second.modifierKeysInvoked, keyEventList, true, KeyboardManagerConstants::KEYBOARDMANAGER_SHORTCUT_FLAG); } // Send the original action key only if it is physically pressed. For remappings to keys other than disabled we already check earlier that it is not pressed in this scenario. For remap to disable @@ -979,7 +993,7 @@ namespace KeyboardEventHandlers { // Reset the remap state it->second.isShortcutInvoked = false; - it->second.winKeyInvoked = ModifierKey::Disabled; + it->second.modifierKeysInvoked.Reset(); it->second.isOriginalActionKeyPressed = false; } diff --git a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/trace.cpp b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/trace.cpp index ab3e49cb87..76a7355bff 100644 --- a/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/trace.cpp +++ b/src/modules/keyboardmanager/KeyboardManagerEngineLibrary/trace.cpp @@ -145,15 +145,15 @@ std::wstring GetShortcutHumanReadableString(Shortcut const& shortcut, LayoutMap& } if (shortcut.ctrlKey != ModifierKey::Disabled) { - humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetCtrlKey()) + L" + "; + humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetCtrlKey(ModifierKey::Both)) + L" + "; } if (shortcut.altKey != ModifierKey::Disabled) { - humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetAltKey()) + L" + "; + humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetAltKey(ModifierKey::Both)) + L" + "; } if (shortcut.shiftKey != ModifierKey::Disabled) { - humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetShiftKey()) + L" + "; + humanReadableShortcut += keyboardMap.GetKeyName(shortcut.GetShiftKey(ModifierKey::Both)) + L" + "; } if (shortcut.actionKey != NULL) { diff --git a/src/modules/keyboardmanager/common/Helpers.cpp b/src/modules/keyboardmanager/common/Helpers.cpp index fb2cefd98a..b619ae73d3 100644 --- a/src/modules/keyboardmanager/common/Helpers.cpp +++ b/src/modules/keyboardmanager/common/Helpers.cpp @@ -262,27 +262,27 @@ namespace Helpers } // Function to set key events for modifier keys: When shortcutToCompare is passed (non-empty shortcut), then the key event is sent only if both shortcut's don't have the same modifier key. When keyToBeReleased is passed (non-NULL), then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare, const DWORD& keyToBeReleased) + void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const Modifiers& modifiersKeys, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare, const DWORD& keyToBeReleased) { // If key down is to be sent, send in the order Win, Ctrl, Alt, Shift if (isKeyDown) { // If shortcutToCompare is non-empty, then the key event is sent only if both shortcut's don't have the same modifier key. If keyToBeReleased is non-NULL, then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - if (shortcutToBeSent.GetWinKey(winKeyInvoked) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(winKeyInvoked) != shortcutToCompare.GetWinKey(winKeyInvoked)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckWinKey(keyToBeReleased))) + if (shortcutToBeSent.GetWinKey(modifiersKeys.winKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(modifiersKeys.winKey) != shortcutToCompare.GetWinKey(modifiersKeys.winKey)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckWinKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(winKeyInvoked)), 0, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(modifiersKeys.winKey)), 0, extraInfoFlag); } - if (shortcutToBeSent.GetCtrlKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey() != shortcutToCompare.GetCtrlKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) + if (shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey) != shortcutToCompare.GetCtrlKey(modifiersKeys.ctrlKey)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey()), 0, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey)), 0, extraInfoFlag); } - if (shortcutToBeSent.GetAltKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey() != shortcutToCompare.GetAltKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckAltKey(keyToBeReleased))) + if (shortcutToBeSent.GetAltKey(modifiersKeys.altKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey(modifiersKeys.altKey) != shortcutToCompare.GetAltKey(modifiersKeys.altKey)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckAltKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey()), 0, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey(modifiersKeys.altKey)), 0, extraInfoFlag); } - if (shortcutToBeSent.GetShiftKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey() != shortcutToCompare.GetShiftKey()) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckShiftKey(keyToBeReleased))) + if (shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey) != shortcutToCompare.GetShiftKey(modifiersKeys.shiftKey)) && (keyToBeReleased == NULL || !shortcutToBeSent.CheckShiftKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey()), 0, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey)), 0, extraInfoFlag); } } @@ -290,21 +290,21 @@ namespace Helpers else { // If shortcutToCompare is non-empty, then the key event is sent only if both shortcut's don't have the same modifier key. If keyToBeReleased is non-NULL, then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - if (shortcutToBeSent.GetShiftKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey() != shortcutToCompare.GetShiftKey() || shortcutToBeSent.CheckShiftKey(keyToBeReleased))) + if (shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey) != shortcutToCompare.GetShiftKey(modifiersKeys.shiftKey) || shortcutToBeSent.CheckShiftKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey()), KEYEVENTF_KEYUP, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetShiftKey(modifiersKeys.shiftKey)), KEYEVENTF_KEYUP, extraInfoFlag); } - if (shortcutToBeSent.GetAltKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey() != shortcutToCompare.GetAltKey() || shortcutToBeSent.CheckAltKey(keyToBeReleased))) + if (shortcutToBeSent.GetAltKey(modifiersKeys.altKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetAltKey(modifiersKeys.altKey) != shortcutToCompare.GetAltKey(modifiersKeys.altKey) || shortcutToBeSent.CheckAltKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey()), KEYEVENTF_KEYUP, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetAltKey(modifiersKeys.altKey)), KEYEVENTF_KEYUP, extraInfoFlag); } - if (shortcutToBeSent.GetCtrlKey() != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey() != shortcutToCompare.GetCtrlKey() || shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) + if (shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey) != shortcutToCompare.GetCtrlKey(modifiersKeys.ctrlKey) || shortcutToBeSent.CheckCtrlKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey()), KEYEVENTF_KEYUP, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetCtrlKey(modifiersKeys.ctrlKey)), KEYEVENTF_KEYUP, extraInfoFlag); } - if (shortcutToBeSent.GetWinKey(winKeyInvoked) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(winKeyInvoked) != shortcutToCompare.GetWinKey(winKeyInvoked) || shortcutToBeSent.CheckWinKey(keyToBeReleased))) + if (shortcutToBeSent.GetWinKey(modifiersKeys.winKey) != NULL && (shortcutToCompare.IsEmpty() || shortcutToBeSent.GetWinKey(modifiersKeys.winKey) != shortcutToCompare.GetWinKey(modifiersKeys.winKey) || shortcutToBeSent.CheckWinKey(keyToBeReleased))) { - Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(winKeyInvoked)), KEYEVENTF_KEYUP, extraInfoFlag); + Helpers::SetKeyEvent(keyEventArray, INPUT_KEYBOARD, static_cast(shortcutToBeSent.GetWinKey(modifiersKeys.winKey)), KEYEVENTF_KEYUP, extraInfoFlag); } } } diff --git a/src/modules/keyboardmanager/common/Helpers.h b/src/modules/keyboardmanager/common/Helpers.h index bd878a3942..8f38bbbbe4 100644 --- a/src/modules/keyboardmanager/common/Helpers.h +++ b/src/modules/keyboardmanager/common/Helpers.h @@ -1,5 +1,6 @@ #pragma once #include "Shortcut.h" +#include "RemapShortcut.h" class LayoutMap; @@ -47,7 +48,8 @@ namespace Helpers std::wstring GetCurrentApplication(bool keepPath); // Function to set key events for modifier keys: When shortcutToCompare is passed (non-empty shortcut), then the key event is sent only if both shortcut's don't have the same modifier key. When keyToBeReleased is passed (non-NULL), then the key event is sent if either the shortcuts don't have the same modifier or if the shortcutToBeSent's modifier matches the keyToBeReleased - void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const ModifierKey& winKeyInvoked, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare = Shortcut(), const DWORD& keyToBeReleased = NULL); + void SetModifierKeyEvents(const Shortcut& shortcutToBeSent, const Modifiers& modifiersKeys, std::vector& keyEventArray, bool isKeyDown, ULONG_PTR extraInfoFlag, const Shortcut& shortcutToCompare = Shortcut(), const DWORD& keyToBeReleased = NULL); + // Function to filter the key codes for artificial key codes int32_t FilterArtificialKeys(const int32_t& key); diff --git a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj index 36e76f971c..36c1238949 100644 --- a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj +++ b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj @@ -54,6 +54,7 @@ + diff --git a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters index d1df33fa5e..287017e312 100644 --- a/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters +++ b/src/modules/keyboardmanager/common/KeyboardManagerCommon.vcxproj.filters @@ -65,6 +65,9 @@ Header Files + + Header Files + diff --git a/src/modules/keyboardmanager/common/Modifiers.h b/src/modules/keyboardmanager/common/Modifiers.h new file mode 100644 index 0000000000..17dc5612e8 --- /dev/null +++ b/src/modules/keyboardmanager/common/Modifiers.h @@ -0,0 +1,26 @@ +#pragma once +#include "ModifierKey.h" + +#include + +class Modifiers +{ +public: + ModifierKey winKey = ModifierKey::Disabled; + ModifierKey ctrlKey = ModifierKey::Disabled; + ModifierKey altKey = ModifierKey::Disabled; + ModifierKey shiftKey = ModifierKey::Disabled; + + void Reset() + { + winKey = ModifierKey::Disabled; + ctrlKey = ModifierKey::Disabled; + altKey = ModifierKey::Disabled; + shiftKey = ModifierKey::Disabled; + } + + inline bool operator==(const Modifiers& other) const + { + return winKey == other.winKey && ctrlKey == other.ctrlKey && altKey == other.altKey && shiftKey == other.shiftKey; + } +}; diff --git a/src/modules/keyboardmanager/common/RemapShortcut.h b/src/modules/keyboardmanager/common/RemapShortcut.h index 8690630b4c..de12867903 100644 --- a/src/modules/keyboardmanager/common/RemapShortcut.h +++ b/src/modules/keyboardmanager/common/RemapShortcut.h @@ -1,6 +1,8 @@ #pragma once #include "Shortcut.h" +#include "Modifiers.h" #include +#include // This class stores all the variables associated with each shortcut remapping class RemapShortcut @@ -8,23 +10,24 @@ class RemapShortcut public: KeyShortcutTextUnion targetShortcut; bool isShortcutInvoked; - ModifierKey winKeyInvoked; + + Modifiers modifierKeysInvoked; // This bool value is only required for remapping shortcuts to Disable bool isOriginalActionKeyPressed; RemapShortcut(const KeyShortcutTextUnion& sc) : - targetShortcut(sc), isShortcutInvoked(false), winKeyInvoked(ModifierKey::Disabled), isOriginalActionKeyPressed(false) + targetShortcut(sc), isShortcutInvoked(false), isOriginalActionKeyPressed(false) { } RemapShortcut() : - targetShortcut(Shortcut()), isShortcutInvoked(false), winKeyInvoked(ModifierKey::Disabled), isOriginalActionKeyPressed(false) + targetShortcut(Shortcut()), isShortcutInvoked(false), isOriginalActionKeyPressed(false) { } inline bool operator==(const RemapShortcut& sc) const { - return targetShortcut == sc.targetShortcut && isShortcutInvoked == sc.isShortcutInvoked && winKeyInvoked == sc.winKeyInvoked; + return targetShortcut == sc.targetShortcut && isShortcutInvoked == sc.isShortcutInvoked && modifierKeysInvoked == sc.modifierKeysInvoked; } bool RemapToKey() diff --git a/src/modules/keyboardmanager/common/Shortcut.cpp b/src/modules/keyboardmanager/common/Shortcut.cpp index 38550199f4..08f161e08c 100644 --- a/src/modules/keyboardmanager/common/Shortcut.cpp +++ b/src/modules/keyboardmanager/common/Shortcut.cpp @@ -185,7 +185,7 @@ DWORD Shortcut::GetWinKey(const ModifierKey& input) const } // Function to return the virtual key code of the ctrl key state expected in the shortcut. Return NULL if it is not a part of the shortcut -DWORD Shortcut::GetCtrlKey() const +DWORD Shortcut::GetCtrlKey(const ModifierKey& input) const { if (ctrlKey == ModifierKey::Disabled) { @@ -201,12 +201,20 @@ DWORD Shortcut::GetCtrlKey() const } else { + if (input == ModifierKey::Right) + { + return VK_RCONTROL; + } + if (input == ModifierKey::Left) + { + return VK_LCONTROL; + } return VK_CONTROL; } } // Function to return the virtual key code of the alt key state expected in the shortcut. Return NULL if it is not a part of the shortcut -DWORD Shortcut::GetAltKey() const +DWORD Shortcut::GetAltKey(const ModifierKey& input) const { if (altKey == ModifierKey::Disabled) { @@ -220,6 +228,14 @@ DWORD Shortcut::GetAltKey() const { return VK_RMENU; } + if (input == ModifierKey::Right) + { + return VK_RMENU; + } + else if (input == ModifierKey::Left || input == ModifierKey::Disabled) + { + return VK_LMENU; + } else { return VK_MENU; @@ -227,7 +243,7 @@ DWORD Shortcut::GetAltKey() const } // Function to return the virtual key code of the shift key state expected in the shortcut. Return NULL if it is not a part of the shortcut -DWORD Shortcut::GetShiftKey() const +DWORD Shortcut::GetShiftKey(const ModifierKey& input) const { if (shiftKey == ModifierKey::Disabled) { @@ -243,6 +259,14 @@ DWORD Shortcut::GetShiftKey() const } else { + if (input == ModifierKey::Right) + { + return VK_RSHIFT; + } + if (input == ModifierKey::Left) + { + return VK_LSHIFT; + } return VK_SHIFT; } } @@ -493,15 +517,15 @@ winrt::hstring Shortcut::ToHstringVK() const } if (ctrlKey != ModifierKey::Disabled) { - output = output + winrt::to_hstring(static_cast(GetCtrlKey())) + winrt::to_hstring(L";"); + output = output + winrt::to_hstring(static_cast(GetCtrlKey(ModifierKey::Both))) + winrt::to_hstring(L";"); } if (altKey != ModifierKey::Disabled) { - output = output + winrt::to_hstring(static_cast(GetAltKey())) + winrt::to_hstring(L";"); + output = output + winrt::to_hstring(static_cast(GetAltKey(ModifierKey::Both))) + winrt::to_hstring(L";"); } if (shiftKey != ModifierKey::Disabled) { - output = output + winrt::to_hstring(static_cast(GetShiftKey())) + winrt::to_hstring(L";"); + output = output + winrt::to_hstring(static_cast(GetShiftKey(ModifierKey::Both))) + winrt::to_hstring(L";"); } if (actionKey != NULL) { @@ -531,15 +555,15 @@ std::vector Shortcut::GetKeyCodes() } if (ctrlKey != ModifierKey::Disabled) { - keys.push_back(GetCtrlKey()); + keys.push_back(GetCtrlKey(ModifierKey::Both)); } if (altKey != ModifierKey::Disabled) { - keys.push_back(GetAltKey()); + keys.push_back(GetAltKey(ModifierKey::Both)); } if (shiftKey != ModifierKey::Disabled) { - keys.push_back(GetShiftKey()); + keys.push_back(GetShiftKey(ModifierKey::Both)); } if (actionKey != NULL) { diff --git a/src/modules/keyboardmanager/common/Shortcut.h b/src/modules/keyboardmanager/common/Shortcut.h index d9a61ff433..439559c9d0 100644 --- a/src/modules/keyboardmanager/common/Shortcut.h +++ b/src/modules/keyboardmanager/common/Shortcut.h @@ -4,7 +4,6 @@ #include #include #include - namespace KeyboardManagerInput { class InputInterface; @@ -142,13 +141,13 @@ public: DWORD GetWinKey(const ModifierKey& input) const; // Function to return the virtual key code of the ctrl key state expected in the shortcut. Return NULL if it is not a part of the shortcut - DWORD GetCtrlKey() const; + DWORD GetCtrlKey(const ModifierKey& input) const; // Function to return the virtual key code of the alt key state expected in the shortcut. Return NULL if it is not a part of the shortcut - DWORD GetAltKey() const; + DWORD GetAltKey(const ModifierKey& input) const; // Function to return the virtual key code of the shift key state expected in the shortcut. Return NULL if it is not a part of the shortcut - DWORD GetShiftKey() const; + DWORD GetShiftKey(const ModifierKey& input) const; // Function to check if the input key matches the win key expected in the shortcut bool CheckWinKey(const DWORD input) const; From d98659273702ce0081e5ece1fa4b8fcb22c879d9 Mon Sep 17 00:00:00 2001 From: OlegHarchevkin <40352094+OlegKharchevkin@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:50:00 +0300 Subject: [PATCH 11/70] =?UTF-8?q?"=C7=94"=20changed=20to=20"=C5=AD"=20in?= =?UTF-8?q?=20GetDefaultLetterKeyEPO=20(#37791)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/modules/poweraccent/PowerAccent.Core/Languages.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/poweraccent/PowerAccent.Core/Languages.cs b/src/modules/poweraccent/PowerAccent.Core/Languages.cs index 542af1b599..567c0ecc2d 100644 --- a/src/modules/poweraccent/PowerAccent.Core/Languages.cs +++ b/src/modules/poweraccent/PowerAccent.Core/Languages.cs @@ -325,7 +325,7 @@ namespace PowerAccent.Core LetterKey.VK_H => new[] { "ĥ" }, LetterKey.VK_J => new[] { "ĵ" }, LetterKey.VK_S => new[] { "ŝ" }, - LetterKey.VK_U => new[] { "ǔ" }, + LetterKey.VK_U => new[] { "ŭ" }, _ => Array.Empty(), }; } From bec6754aa306d7b84e6cfd0264c0f2ac8637b29b Mon Sep 17 00:00:00 2001 From: dcog989 <89043002+dcog989@users.noreply.github.com> Date: Mon, 14 Apr 2025 11:20:55 +0100 Subject: [PATCH 12/70] Fix Color Picker resource leak (#38122) (#38147) * Fix Color Picker resource leak (#38122) Added a using statement to properly dispose of the Graphics object created from the Bitmap. This fixes resource leak. * Fix CI complain * Update MouseInfoProvider.cs fix whitespace --------- Co-authored-by: Kai Tao <69313318+vanzue@users.noreply.github.com> --- .../colorPicker/ColorPickerUI/Mouse/MouseInfoProvider.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/modules/colorPicker/ColorPickerUI/Mouse/MouseInfoProvider.cs b/src/modules/colorPicker/ColorPickerUI/Mouse/MouseInfoProvider.cs index 76c376b761..c28dcc1ae6 100644 --- a/src/modules/colorPicker/ColorPickerUI/Mouse/MouseInfoProvider.cs +++ b/src/modules/colorPicker/ColorPickerUI/Mouse/MouseInfoProvider.cs @@ -104,8 +104,10 @@ namespace ColorPicker.Mouse var rect = new Rectangle((int)mousePosition.X, (int)mousePosition.Y, 1, 1); using (var bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb)) { - var g = Graphics.FromImage(bmp); - g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy); + using (var g = Graphics.FromImage(bmp)) // Ensure Graphics object is disposed + { + g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy); + } return bmp.GetPixel(0, 0); } From badb029bcfb6a3dd8f9890ead6334a71011986b4 Mon Sep 17 00:00:00 2001 From: Clint Rutkas Date: Mon, 14 Apr 2025 17:01:37 +0000 Subject: [PATCH 13/70] Upgrading some of the Testing framework items (#38779) * starting to get some of the baseline * Update NOTICE.md * Upgrading streamjson gets the others on same version of newtonsoft.json * Update PowerToys.Settings.csproj * Update NOTICE.md --- Directory.Packages.props | 10 +++++----- NOTICE.md | 12 ++++++------ .../Programs/Win32Program.cs | 2 +- .../Settings.UI/PowerToys.Settings.csproj | 2 ++ 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index f4cfe643e9..12909c4be4 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -29,7 +29,7 @@ - + @@ -61,7 +61,7 @@ - + @@ -69,7 +69,7 @@ - + @@ -84,8 +84,8 @@ - - + + diff --git a/NOTICE.md b/NOTICE.md index 15693c9590..f11a2b2259 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1393,7 +1393,6 @@ SOFTWARE. ## NuGet Packages used by PowerToys - - AdaptiveCards.ObjectModel.WinUI3 2.0.0-beta - AdaptiveCards.Rendering.WinUI3 2.1.0-beta - AdaptiveCards.Templating 2.0.2 @@ -1419,7 +1418,7 @@ SOFTWARE. - LazyCache 2.4.0 - Mages 3.0.0 - Markdig.Signed 0.34.0 -- MessagePack 2.5.187 +- MessagePack 3.1.3 - Microsoft.Bcl.AsyncInterfaces 9.0.4 - Microsoft.CodeAnalysis.NetAnalyzers 9.0.0 - Microsoft.Data.Sqlite 9.0.4 @@ -1445,14 +1444,14 @@ SOFTWARE. - Microsoft.Xaml.Behaviors.Wpf 1.1.39 - ModernWpfUI 0.9.4 - Moq 4.18.4 -- MSTest 3.6.3 +- MSTest 3.8.3 - NLog.Extensions.Logging 5.3.8 - NLog.Schema 5.2.8 - OpenAI 2.0.0 - ReverseMarkdown 4.1.0 - ScipBe.Common.Office.OneNote 3.0.1 - SharpCompress 0.37.2 -- StreamJsonRpc 2.19.27 +- StreamJsonRpc 2.21.69 - StyleCop.Analyzers 1.2.0-beta.556 - System.CodeDom 9.0.4 - System.CommandLine 2.0.0-beta4.22272.1 @@ -1463,8 +1462,8 @@ SOFTWARE. - System.Diagnostics.EventLog 9.0.4 - System.Diagnostics.PerformanceCounter 9.0.4 - System.Drawing.Common 9.0.4 -- System.IO.Abstractions 21.0.29 -- System.IO.Abstractions.TestingHelpers 21.0.29 +- System.IO.Abstractions 22.0.13 +- System.IO.Abstractions.TestingHelpers 22.0.13 - System.Management 9.0.4 - System.Reactive 6.0.1 - System.Runtime.Caching 9.0.4 @@ -1477,3 +1476,4 @@ SOFTWARE. - WinUIEx 2.2.0 - WPF-UI 3.0.5 - WyHash 1.0.5 + diff --git a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32Program.cs b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32Program.cs index 56fd4d894d..4169a5769b 100644 --- a/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32Program.cs +++ b/src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32Program.cs @@ -82,7 +82,7 @@ namespace Microsoft.Plugin.Program.Programs public ApplicationType AppType { get; set; } // Wrappers for File Operations - public static IFileVersionInfoWrapper FileVersionInfoWrapper { get; set; } = new FileVersionInfoWrapper(); + public static IFileVersionInfoWrapper FileVersionInfoWrapper { get; set; } = new Wox.Infrastructure.FileSystemHelper.FileVersionInfoWrapper(); public static IFile FileWrapper { get; set; } = new FileSystem().File; diff --git a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj index 9d71b62de7..5a69d8beea 100644 --- a/src/settings-ui/Settings.UI/PowerToys.Settings.csproj +++ b/src/settings-ui/Settings.UI/PowerToys.Settings.csproj @@ -75,6 +75,8 @@ + + + From 293fa262bb4f3c942d06a49724855b58f54e3a7b Mon Sep 17 00:00:00 2001 From: ruslanlap <106077551+ruslanlap@users.noreply.github.com> Date: Mon, 14 Apr 2025 20:02:29 +0300 Subject: [PATCH 15/70] [PowerToysRun][Docs] Add Weather and Pomodoro to Third-Party plugins (#38760) * [PowerToysRun][Docs] Add Weather and Pomodoro to Third-Party plugins * [Spell-check] Add ruslanlap to allowed names and update expect.txt * Update expect.txt * Update names.txt * Update names.txt * Update names.txt * Update names.txt --- .github/actions/spell-check/expect.txt | 1 + doc/thirdPartyRunPlugins.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 8fb29864f3..59ec830124 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1196,6 +1196,7 @@ Podcasts POINTERID POINTERUPDATE Pokedex +Pomodoro Popups POPUPWINDOW POSITIONITEM diff --git a/doc/thirdPartyRunPlugins.md b/doc/thirdPartyRunPlugins.md index 03bafa1c66..7070086bc9 100644 --- a/doc/thirdPartyRunPlugins.md +++ b/doc/thirdPartyRunPlugins.md @@ -44,6 +44,8 @@ Contact the developers of a plugin directly for assistance with a specific plugi | [HttpStatusCodes](https://github.com/grzhan/HttpStatusCodePowerToys) | [grzhan](https://github.com/grzhan) | Search for http status codes | | [SVGL](https://github.com/Sameerjs6/powertoys-svgl) | [SameerJS6](https://github.com/SameerJS6) | Search, Browse and copy SVG logos from SVGL. | | [QuickNotes](https://github.com/ruslanlap/CommunityPowerToysRunPlugin-QuickNotes) | [ruslanlap](https://github.com/ruslanlap) | Create, manage, and search notes directly from PowerToys Run. | +| [Weather](https://github.com/ruslanlap/PowerToysRun-Weather) | [ruslanlap](https://github.com/ruslanlap) | Get real-time weather information directly from PowerToys Run. | +| [Pomodoro](https://github.com/ruslanlap/PowerToysRun-Pomodoro) | [ruslanlap](https://github.com/ruslanlap) | Manage Pomodoro productivity sessions directly from PowerToys Run. | ## Extending software plugins From 21aa49cefb817afc05e373e962e436847784a79f Mon Sep 17 00:00:00 2001 From: PesBandi <127593627+PesBandi@users.noreply.github.com> Date: Tue, 15 Apr 2025 05:15:41 +0200 Subject: [PATCH 16/70] [ColorPicker]Only close on escape if focused (#37895) --- .../ColorPickerUI/Helpers/AppStateHandler.cs | 11 +++++------ .../ColorPickerUI/Keyboard/KeyboardMonitor.cs | 13 +++---------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs index 4940bd75e3..b3350702c7 100644 --- a/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs +++ b/src/modules/colorPicker/ColorPickerUI/Helpers/AppStateHandler.cs @@ -222,7 +222,7 @@ namespace ColorPicker.Helpers public bool HandleEnterPressed() { - if (!IsColorPickerVisible()) + if (!_colorPickerShown) { return false; } @@ -233,14 +233,13 @@ namespace ColorPicker.Helpers public bool HandleEscPressed() { - if (!BlockEscapeKeyClosingColorPickerEditor) + if (!BlockEscapeKeyClosingColorPickerEditor + && (_colorPickerShown || (_colorEditorWindow != null && _colorEditorWindow.IsActive))) { return EndUserSession(); } - else - { - return false; - } + + return false; } internal void MoveCursor(int xOffset, int yOffset) diff --git a/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs b/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs index 208f139ae8..d6defaacb2 100644 --- a/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs +++ b/src/modules/colorPicker/ColorPickerUI/Keyboard/KeyboardMonitor.cs @@ -70,17 +70,10 @@ namespace ColorPicker.Keyboard var virtualCode = e.KeyboardData.VirtualCode; // ESC pressed - if (virtualCode == KeyInterop.VirtualKeyFromKey(Key.Escape) - && e.KeyboardState == GlobalKeyboardHook.KeyboardState.KeyDown - ) + if (virtualCode == KeyInterop.VirtualKeyFromKey(Key.Escape) && e.KeyboardState == GlobalKeyboardHook.KeyboardState.KeyDown) { - if (_appStateHandler.IsColorPickerVisible() - || !AppStateHandler.BlockEscapeKeyClosingColorPickerEditor - ) - { - e.Handled = _appStateHandler.EndUserSession(); - return; - } + e.Handled = _appStateHandler.HandleEscPressed(); + return; } if ((virtualCode == KeyInterop.VirtualKeyFromKey(Key.Space) || virtualCode == KeyInterop.VirtualKeyFromKey(Key.Enter)) && (e.KeyboardState == GlobalKeyboardHook.KeyboardState.KeyDown)) From f1bda8d71fd323a2df5422ec08847e86a6122d5b Mon Sep 17 00:00:00 2001 From: Stefan Markovic <57057282+stefansjfw@users.noreply.github.com> Date: Tue, 15 Apr 2025 07:09:35 +0200 Subject: [PATCH 17/70] [cmdpal] Setting a new alias should remove the old one (#38193) * [cmdpal] Fix alias update * Fix the command palette extension alias update issue * clean code --------- Co-authored-by: vanzue --- .../TopLevelViewModel.cs | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs index 4b8a2b49a9..5ff8337494 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/TopLevelViewModel.cs @@ -152,7 +152,7 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem { GenerateId(); - UpdateAlias(); + FetchAliasFromAliasManager(); UpdateHotkey(); UpdateTags(); } @@ -163,24 +163,31 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem private void HandleChangeAlias() { - SetAlias(Alias); + SetAlias(); Save(); } - public void SetAlias(CommandAlias? newAlias) + public void SetAlias() { - _serviceProvider.GetService()!.UpdateAlias(Id, newAlias); - UpdateAlias(); + var commandAlias = Alias is null + ? null + : new CommandAlias(Alias.Alias, Alias.CommandId, Alias.IsDirect); + + _serviceProvider.GetService()!.UpdateAlias(Id, commandAlias); UpdateTags(); } - private void UpdateAlias() + private void FetchAliasFromAliasManager() { - // Add tags for the alias, if we have one. - var aliases = _serviceProvider.GetService(); - if (aliases != null) + var am = _serviceProvider.GetService(); + if (am != null) { - Alias = aliases.AliasFromId(Id); + var commandAlias = am.AliasFromId(Id); + if (commandAlias is not null) + { + // Decouple from the alias manager alias object + Alias = new CommandAlias(commandAlias.Alias, commandAlias.CommandId, commandAlias.IsDirect); + } } } From 60f50d853b1a53a38dcc60d1fce60c03880f1cba Mon Sep 17 00:00:00 2001 From: Typpi <20943337+Nick2bad4u@users.noreply.github.com> Date: Tue, 15 Apr 2025 04:33:05 -0400 Subject: [PATCH 18/70] Apply security best practices for GitHub Actions / Dependency (#38552) This update aligns with Microsoft's security guidelines by pinning all GitHub Action tags and Docker tags to their full-length commits. This practice ensures immutability and reduces the risk of supply chain attacks. Note that 1st and 2nd party actions do not require hash pinning. --- .github/workflows/dependency-review.yml | 26 +++++++++++++++++++++++++ .github/workflows/spelling2.yml | 8 ++++---- 2 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/dependency-review.yml diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000000..0db3dc6595 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,26 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, +# surfacing known-vulnerable versions of the packages declared or updated in the PR. +# Once installed, if the workflow run is marked as required, +# PRs introducing known-vulnerable packages will be blocked from merging. +# +# As recommended by Microsoft's security guidelines (https://docs.opensource.microsoft.com/security/tsg/actions/#requirements-for-security-hardening-your-own-github-actions), +# 3rd-party actions should be pinned to a specific commit hash to prevent supply chain attacks. +# This update aligns with best practices; 1st/2nd-party actions is not required hash pinning. +# +# Source repository: https://github.com/actions/dependency-review-action +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v4 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v4 \ No newline at end of file diff --git a/.github/workflows/spelling2.yml b/.github/workflows/spelling2.yml index e79708399f..03bb66fff6 100644 --- a/.github/workflows/spelling2.yml +++ b/.github/workflows/spelling2.yml @@ -93,7 +93,7 @@ jobs: steps: - name: check-spelling id: spelling - uses: check-spelling/check-spelling@v0.0.24 + uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24 with: config: .github/actions/spell-check suppress_push_for_open_pull_request: ${{ github.actor != 'dependabot[bot]' && 1 }} @@ -156,7 +156,7 @@ jobs: if: (success() || failure()) && needs.spelling.outputs.followup && github.event_name == 'push' steps: - name: comment - uses: check-spelling/check-spelling@v0.0.24 + uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24 with: config: .github/actions/spell-check checkout: true @@ -175,7 +175,7 @@ jobs: if: (success() || failure()) && needs.spelling.outputs.followup && contains(github.event_name, 'pull_request') steps: - name: comment - uses: check-spelling/check-spelling@v0.0.24 + uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24 with: config: .github/actions/spell-check checkout: true @@ -202,7 +202,7 @@ jobs: cancel-in-progress: false steps: - name: apply spelling updates - uses: check-spelling/check-spelling@v0.0.24 + uses: check-spelling/check-spelling@67debf50669c7fc76fc8f5d7f996384535a72b77 # v0.0.24 with: experimental_apply_changes_via_bot: ${{ github.repository_owner != 'microsoft' && 1 }} checkout: true From 2b5181b4c9413f0825c35547114c41eb24ea0da2 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 15 Apr 2025 06:07:22 -0500 Subject: [PATCH 19/70] Rename the `[Ee]xts` dir to `ext` (#38852) **WARNING:** This PR will probably blow up all in-flight PRs at some point in the early days of CmdPal, two of us created seperate `Exts` and `exts` dirs. Depending on what the casing was on the branch that you checked one of those out from, it'd get stuck like that on your PC forever. Windows didn't care, so we never noticed. But GitHub does care, and now browsing the source on GitHub is basically impossible. Closes #38081 --- PowerToys.sln | 34 +++++++++--------- .../Microsoft.CmdPal.UI.ViewModels.csproj | 2 +- .../Microsoft.CmdPal.UI.csproj | 30 ++++++++-------- .../command-palette-anatomy.md | 2 +- .../AllAppsCommandProvider.cs | 0 .../Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs | 0 .../AllAppsSettings.cs | 0 .../Microsoft.CmdPal.Ext.Apps/AppCache.cs | 0 .../Microsoft.CmdPal.Ext.Apps/AppCommand.cs | 0 .../Microsoft.CmdPal.Ext.Apps/AppItem.cs | 0 .../Microsoft.CmdPal.Ext.Apps/AppListItem.cs | 0 .../Assets/AllApps.png | Bin .../Assets/AllApps.svg | 0 .../Commands/OpenInConsoleCommand.cs | 0 .../Commands/OpenPathCommand.cs | 0 .../Commands/RunAsAdminCommand.cs | 0 .../Commands/RunAsUserCommand.cs | 0 .../Microsoft.CmdPal.Ext.Apps.csproj | 0 .../NativeMethods.txt | 0 .../Programs/AppxFactory.cs | 0 .../Programs/AppxPackageHelper.cs | 0 .../Programs/DisabledProgramSource.cs | 0 .../Programs/IApplicationActivationManager.cs | 0 .../Programs/IAppxFactory.cs | 0 .../Programs/IAppxManifestApplication.cs | 0 .../IAppxManifestApplicationsEnumerator.cs | 0 .../Programs/IAppxManifestProperties.cs | 0 .../Programs/IAppxManifestReader.cs | 0 .../Programs/IFileVersionInfoWrapper.cs | 0 .../Programs/IPackage.cs | 0 .../Programs/IPackageCatalog.cs | 0 .../Programs/IPackageManager.cs | 0 .../Programs/IProgram.cs | 0 .../Programs/LogoType.cs | 0 .../Programs/PackageCatalogWrapper.cs | 0 .../Programs/PackageManagerWrapper.cs | 0 .../Programs/PackageWrapper.cs | 0 .../Programs/ProgramSource.cs | 0 .../Programs/ReparsePoint.cs | 0 .../Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs | 0 .../Programs/UWPApplication.cs | 0 .../Programs/Win32Program.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../Storage/EventHandler.cs | 0 .../Storage/FileSystemWatcherWrapper.cs | 0 .../Storage/IFileSystemWatcherWrapper.cs | 0 .../Storage/IProgramRepository.cs | 0 .../Storage/IRepository`1.cs | 0 .../Storage/ListRepository`1.cs | 0 .../Storage/PackageRepository.cs | 0 .../Storage/Win32ProgramFileSystemWatchers.cs | 0 .../Storage/Win32ProgramRepository.cs | 0 .../Utils/IShellLinkHelper.cs | 0 .../Microsoft.CmdPal.Ext.Apps/Utils/Native.cs | 0 .../Utils/ShellCommand.cs | 0 .../Utils/ShellLinkHelper.cs | 0 .../Utils/ShellLocalization.cs | 0 .../Microsoft.CmdPal.Ext.Apps/Utils/Theme.cs | 0 .../Utils/ThemeHelper.cs | 0 .../AddBookmarkForm.cs | 0 .../AddBookmarkPage.cs | 0 .../Assets/Bookmark.png | Bin .../Assets/Bookmark.svg | 0 .../BookmarkData.cs | 0 .../BookmarkPlaceholderForm.cs | 0 .../BookmarkPlaceholderPage.cs | 0 .../Bookmarks.cs | 0 .../BookmarksCommandProvider.cs | 0 .../Microsoft.CmdPal.Ext.Bookmarks.csproj | 2 +- .../OpenInTerminalCommand.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../UrlCommand.cs | 0 .../Assets/Calculator.png | Bin .../Assets/Calculator.svg | 0 .../CalculatorCommandProvider.cs | 0 .../Microsoft.CmdPal.Ext.Calc.csproj | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../ClipboardHistoryCommandsProvider.cs | 0 .../Commands/CopyCommand.cs | 0 .../Commands/PasteCommand.cs | 0 .../Helpers/ClipboardHelper.cs | 0 .../Helpers/NativeMethods.cs | 0 ...crosoft.CmdPal.Ext.ClipboardHistory.csproj | 0 .../Models/ClipboardFormat.cs | 0 .../Models/ClipboardItem.cs | 0 .../Pages/ClipboardHistoryListPage.cs | 0 .../Assets/FileExplorer.png | Bin .../Assets/FileExplorer.svg | 0 .../Commands/CopyPathCommand.cs | 0 .../Commands/OpenFileCommand.cs | 0 .../Commands/OpenInConsoleCommand.cs | 0 .../Commands/OpenPropertiesCommand.cs | 0 .../Commands/OpenWithCommand.cs | 0 .../Data/IndexerItem.cs | 0 .../Data/IndexerListItem.cs | 0 .../FallbackOpenFileItem.cs | 0 .../Indexer/DataSourceManager.cs | 0 .../Indexer/OleDB/DBPROP.cs | 0 .../Indexer/OleDB/DBPROPIDSET.cs | 0 .../Indexer/OleDB/DBPROPSET.cs | 0 .../Indexer/OleDB/IRowset.cs | 0 .../Indexer/OleDB/IRowsetInfo.cs | 0 .../Indexer/SearchQuery.cs | 0 .../Indexer/SearchResult.cs | 0 .../SystemSearch/CSearchCatalogManager.cs | 0 .../CSearchCatalogManagerClass.cs | 0 .../Indexer/SystemSearch/CSearchManager.cs | 0 .../SystemSearch/CSearchManagerClass.cs | 0 .../SystemSearch/CSearchQueryHelper.cs | 0 .../SystemSearch/CSearchQueryHelperClass.cs | 0 .../SystemSearch/ISearchCatalogManager.cs | 0 .../Indexer/SystemSearch/ISearchManager.cs | 0 .../SystemSearch/ISearchQueryHelper.cs | 0 .../Indexer/Utils/QueryStringBuilder.cs | 0 .../Indexer/Utils/UrlToFilePathConverter.cs | 0 .../IndexerCommandsProvider.cs | 0 .../Microsoft.CmdPal.Ext.Indexer.csproj | 0 .../Native/NativeHelpers.cs | 0 .../NativeMethods.txt | 0 .../Pages/DirectoryExplorePage.cs | 0 .../Pages/DirectoryPage.cs | 0 .../Pages/ExploreListItem.cs | 0 .../Pages/Icons.cs | 0 .../Pages/IndexerPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../Assets/Registry.png | Bin .../Assets/Registry.svg | 0 .../Classes/RegistryEntry.cs | 0 .../Commands/CopyRegistryInfoCommand.cs | 0 .../Commands/OpenKeyInEditorCommand.cs | 0 .../Constants/KeyName.cs | 0 .../Constants/MaxTextLength.cs | 0 .../Microsoft.CmdPal.Ext.Registry/CopyType.cs | 0 .../Enumerations/TruncateSide.cs | 0 .../Helpers/ContextMenuHelper.cs | 0 .../Helpers/QueryHelper.cs | 0 .../Helpers/RegistryHelper.cs | 0 .../Helpers/ResultHelper.cs | 0 .../Helpers/ValueHelper.cs | 0 .../Microsoft.CmdPal.Ext.Registry.csproj | 0 .../Pages/RegistryListPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../RegistryCommandsProvider.cs | 0 .../Microsoft.CmdPal.Ext.Shell/Assets/Run.png | Bin .../Microsoft.CmdPal.Ext.Shell/Assets/Run.svg | 0 .../Assets/Run_V2_2x.svg | 0 .../Commands/ExecuteItem.cs | 0 .../FallbackExecuteItem.cs | 0 .../Helpers/ExecutionShell.cs | 0 .../Helpers/RunAsType.cs | 0 .../Helpers/SettingsManager.cs | 0 .../Helpers/ShellListPageHelpers.cs | 0 .../Microsoft.CmdPal.Ext.Shell/Icons.cs | 0 .../Microsoft.CmdPal.Ext.Shell.csproj | 0 .../Pages/ShellListPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../ShellCommandsProvider.cs | 0 .../Assets/SystemCommand.png | Bin .../Assets/SystemCommand.svg | 0 .../EmptyRecycleBinCommand.cs | 0 .../EmptyRecycleBinConfirmation.cs | 0 .../ExecuteCommand.cs | 0 .../ExecuteCommandConfirmation.cs | 0 .../Helpers/Commands.cs | 0 .../Helpers/Icons.cs | 0 .../Helpers/MessageBoxHelper.cs | 0 .../Helpers/Native.cs | 0 .../Helpers/NativeMethods.cs | 0 .../Helpers/NetworkConnectionProperties.cs | 0 .../Helpers/OpenInShellHelper.cs | 0 .../Helpers/ResultHelper.cs | 0 .../Helpers/SettingsManager.cs | 0 .../Helpers/SystemPluginContext.cs | 0 .../Helpers/Win32Helpers.cs | 0 .../Microsoft.CmdPal.Ext.System.csproj | 0 .../OpenInShellCommand.cs | 0 .../Pages/SystemCommandPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../SystemCommandExtensionProvider.cs | 0 .../SystemCommandsCache.cs | 0 .../Assets/TimeDate.png | Bin .../Assets/TimeDate.svg | 0 .../Assets/Warning.dark.png | Bin .../Assets/Warning.light.png | Bin .../Helpers/AvailableResult.cs | 0 .../Helpers/AvailableResultsList.cs | 0 .../Helpers/ResultHelper.cs | 0 .../Helpers/SettingsManager.cs | 0 .../Helpers/TimeAndDateHelper.cs | 0 .../Helpers/TimeDateCalculator.cs | 0 .../Microsoft.CmdPal.Ext.TimeDate.csproj | 0 .../Pages/TimeDateExtensionPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../TimeDateCommandsProvider.cs | 0 .../Assets/WebSearch.png | Bin .../Assets/WebSearch.svg | 0 .../Commands/OpenURLCommand.cs | 0 .../Commands/SearchWebCommand.cs | 0 .../FallbackExecuteSearchItem.cs | 0 .../FallbackOpenURLItem.cs | 0 .../Helpers/DefaultBrowserInfo.cs | 0 .../Helpers/HistoryItem.cs | 0 .../Helpers/SettingsManager.cs | 0 .../Microsoft.CmdPal.Ext.WebSearch.csproj | 0 .../NativeMethods.txt | 0 .../Pages/WebSearchListPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../WebSearchCommandsProvider.cs | 0 .../WebSearchTopLevelCommandItem.cs | 0 .../Assets/Extension.png | Bin .../Assets/Extension.svg | 0 .../Assets/Store.dark.png | Bin .../Assets/Store.dark.svg | 0 .../Assets/Store.light.png | Bin .../Assets/Store.light.svg | 0 .../Assets/WinGet.png | Bin .../Assets/WinGet.svg | 0 .../Microsoft.CmdPal.Ext.WinGet.csproj | 0 .../NativeMethods.txt | 0 .../Pages/InstallPackageCommand.cs | 0 .../Pages/InstallPackageListItem.cs | 0 .../Pages/WinGetExtensionPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../WinGetExtensionCommandsProvider.cs | 0 .../WinGetExtensionHost.cs | 0 .../WinGetStatics.cs | 0 .../ClassModel.cs | 0 .../ClassesDefinition.cs | 0 .../ClsidContext.cs | 0 .../WindowsPackageManagerFactory.cs | 0 .../WindowsPackageManagerStandardFactory.cs | 0 .../Microsoft.CmdPal.Ext.WinGet/app.manifest | 0 .../Assets/WindowWalker.png | Bin .../Assets/WindowWalker.svg | 0 .../Commands/CloseWindowCommand.cs | 0 .../Commands/ExplorerInfoResultCommand.cs | 0 .../Commands/KillProcessCommand.cs | 0 .../Commands/SwitchToWindowCommand.cs | 0 .../Components/ContextMenuHelper.cs | 0 .../Components/FuzzyMatching.cs | 0 .../Components/LivePreview.cs | 0 .../Components/OpenWindows.cs | 0 .../Components/ResultHelper.cs | 0 .../Components/SearchController.cs | 0 .../Components/SearchResult.cs | 0 .../Components/SearchString.cs | 0 .../Components/Window.cs | 0 .../Components/WindowProcess.cs | 0 .../Helpers/CVirtualDesktopManager.cs | 0 .../Helpers/IVirtualDesktopManager.cs | 0 .../Helpers/NativeMethods.cs | 0 .../Helpers/OSVersionHelper.cs | 0 .../Helpers/SettingsManager.cs | 0 .../Helpers/ShellCommand.cs | 0 .../Helpers/VDesktop.cs | 0 .../Helpers/VirtualDesktopHelper.cs | 0 .../Helpers/Win32Helpers.cs | 0 .../Microsoft.CmdPal.Ext.WindowWalker.csproj | 0 .../Pages/WindowWalkerListPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../WindowWalkerCommandsProvider.cs | 0 .../WindowWalkerListItem.cs | 0 .../Action.cs | 0 .../Assets/Services.png | Bin .../Assets/Services.svg | 0 .../Commands/OpenServicesCommand.cs | 0 .../Commands/RestartServiceCommand.cs | 0 .../Commands/ServiceCommand.cs | 0 .../Helpers/ServiceHelper.cs | 0 ...icrosoft.CmdPal.Ext.WindowsServices.csproj | 0 .../Pages/ServicesListPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../ServiceResult.cs | 0 .../WindowsServicesCommandsProvider.cs | 0 .../Assets/WindowsSettings.png | Bin .../Assets/WindowsSettings.svg | 0 .../Classes/WindowsSetting.cs | 0 .../Classes/WindowsSettings.cs | 0 .../Commands/CopySettingCommand.cs | 0 .../Commands/OpenSettingsCommand.cs | 0 .../Helpers/ContextMenuHelper.cs | 0 .../Helpers/JsonSettingsListHelper.cs | 0 .../Helpers/ResultHelper.cs | 0 .../Helpers/TranslationHelper.cs | 0 .../Helpers/UnsupportedSettingsHelper.cs | 0 .../Helpers/WindowsSettingsPathHelper.cs | 0 .../Images/WindowsSettings.dark.png | Bin .../Images/WindowsSettings.light.png | Bin ...icrosoft.CmdPal.Ext.WindowsSettings.csproj | 0 .../Pages/WindowsSettingsListPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../WindowsSettings.json | 0 .../WindowsSettings.schema.json | 0 .../WindowsSettingsCommandsProvider.cs | 0 .../Assets/WindowsTerminal.dark.png | Bin .../Assets/WindowsTerminal.light.png | Bin .../Assets/WindowsTerminal.png | Bin .../Assets/WindowsTerminal.svg | 0 .../Commands/LaunchProfileAsAdminCommand.cs | 0 .../Commands/LaunchProfileCommand.cs | 0 .../Helpers/ApplicationActivationManager.cs | 0 .../Helpers/IApplicationActivationManager.cs | 0 .../Helpers/ITerminalQuery.cs | 0 .../Helpers/SettingsManager.cs | 0 .../Helpers/TerminalHelper.cs | 0 .../Helpers/TerminalQuery.cs | 0 ...icrosoft.CmdPal.Ext.WindowsTerminal.csproj | 0 .../Pages/ProfilesListPage.cs | 0 .../Properties/Resources.Designer.cs | 0 .../Properties/Resources.resx | 0 .../TerminalPackage.cs | 0 .../TerminalProfile.cs | 0 .../TerminalTopLevelCommandItem.cs | 0 .../WindowsTerminalCommandsProvider.cs | 0 .../Assets/LockScreenLogo.scale-200.png | Bin .../Assets/SplashScreen.scale-200.png | Bin .../Assets/Square150x150Logo.scale-200.png | Bin .../Assets/Square44x44Logo.scale-200.png | Bin ...x44Logo.targetsize-24_altform-unplated.png | Bin .../Assets/StoreLogo.png | Bin .../Assets/Wide310x150Logo.scale-200.png | Bin .../Package.appxmanifest | 0 .../ProcessMonitorExtension/ProcessItem.cs | 0 .../ProcessListPage.cs | 0 .../ProcessMonitorCommandProvider.cs | 0 .../ProcessMonitorExtension.csproj | 0 .../ProcessMonitorExtension/Program.cs | 0 .../PublishProfiles/win-arm64.pubxml | 0 .../Properties/PublishProfiles/win-x64.pubxml | 0 .../Properties/launchSettings.json | 0 .../SampleExtension.cs | 0 .../SwitchToProcess.cs | 0 .../TerminateProcess.cs | 0 .../ProcessMonitorExtension/app.manifest | 0 .../Assets/LockScreenLogo.scale-200.png | Bin .../Assets/SplashScreen.scale-200.png | Bin .../Assets/Square150x150Logo.scale-200.png | Bin .../Assets/Square44x44Logo.scale-200.png | Bin ...x44Logo.targetsize-24_altform-unplated.png | Bin .../SamplePagesExtension/Assets/StoreLogo.png | Bin .../Assets/Wide310x150Logo.scale-200.png | Bin .../EvilSampleListPage.cs | 0 .../SamplePagesExtension/EvilSamplesPage.cs | 0 .../ExplodeInFiveSeconds.cs | 0 .../SamplePagesExtension/Package.appxmanifest | 0 .../Pages/SampleCommentsPage.cs | 0 .../Pages/SampleContentPage.cs | 0 .../Pages/SampleDynamicListPage.cs | 0 .../Pages/SampleListPage.cs | 0 .../Pages/SampleListPageWithDetails.cs | 0 .../Pages/SampleMarkdownDetails.cs | 0 .../Pages/SampleMarkdownManyBodies.cs | 0 .../Pages/SampleMarkdownPage.cs | 0 .../Pages/SampleSettingsPage.cs | 0 .../Pages/SendMessageCommand.cs | 0 .../SamplePagesExtension/Program.cs | 0 .../PublishProfiles/win-arm64.pubxml | 0 .../Properties/PublishProfiles/win-x64.pubxml | 0 .../Properties/launchSettings.json | 0 .../SamplePagesExtension/SampleExtension.cs | 0 .../SamplePagesCommandsProvider.cs | 0 .../SamplePagesExtension.csproj | 0 .../SampleUpdatingItemsPage.cs | 0 .../SamplePagesExtension/SamplesListPage.cs | 0 .../SelfImmolateCommand.cs | 0 .../SamplePagesExtension/app.manifest | 0 379 files changed, 35 insertions(+), 35 deletions(-) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/AllAppsCommandProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/AllAppsSettings.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/AppCache.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/AppCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/AppItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/AppListItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.svg (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Commands/OpenInConsoleCommand.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Commands/OpenPathCommand.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Commands/RunAsAdminCommand.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Commands/RunAsUserCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Microsoft.CmdPal.Ext.Apps.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/NativeMethods.txt (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/AppxFactory.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/AppxPackageHelper.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/DisabledProgramSource.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IApplicationActivationManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IAppxFactory.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplication.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplicationsEnumerator.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestProperties.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestReader.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IFileVersionInfoWrapper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IPackage.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IPackageCatalog.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IPackageManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/IProgram.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/LogoType.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/PackageCatalogWrapper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/PackageManagerWrapper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/PackageWrapper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/ProgramSource.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/ReparsePoint.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Properties/Resources.resx (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Storage/EventHandler.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Storage/FileSystemWatcherWrapper.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Storage/IFileSystemWatcherWrapper.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Storage/IProgramRepository.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Storage/IRepository`1.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Storage/ListRepository`1.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Storage/PackageRepository.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramFileSystemWatchers.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramRepository.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Utils/IShellLinkHelper.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Utils/Native.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Utils/ShellCommand.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Utils/ShellLinkHelper.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Utils/ShellLocalization.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Utils/Theme.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Apps/Utils/ThemeHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/BookmarkData.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderForm.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/Bookmarks.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/BookmarksCommandProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj (93%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Bookmark/OpenInTerminalCommand.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.resx (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Bookmark/UrlCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Calc/CalculatorCommandProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Calc/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Calc/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.ClipboardHistory/ClipboardHistoryCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/CopyCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/PasteCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/ClipboardHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/NativeMethods.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardFormat.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.ClipboardHistory/Pages/ClipboardHistoryListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Commands/CopyPathCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Commands/OpenFileCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Commands/OpenInConsoleCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Commands/OpenPropertiesCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Commands/OpenWithCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Data/IndexerItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/FallbackOpenFileItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/DataSourceManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROP.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPIDSET.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPSET.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowset.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowsetInfo.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchQuery.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchResult.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManager.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManagerClass.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManager.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManagerClass.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelper.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelperClass.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchCatalogManager.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchManager.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchQueryHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/QueryStringBuilder.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/UrlToFilePathConverter.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/IndexerCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Native/NativeHelpers.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/NativeMethods.txt (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryExplorePage.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Pages/ExploreListItem.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Pages/Icons.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Indexer/Pages/IndexerPage.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Assets/Registry.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Assets/Registry.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Classes/RegistryEntry.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Commands/CopyRegistryInfoCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Commands/OpenKeyInEditorCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Constants/KeyName.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Constants/MaxTextLength.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/CopyType.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Enumerations/TruncateSide.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Helpers/ContextMenuHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Helpers/QueryHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Helpers/ValueHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Microsoft.CmdPal.Ext.Registry.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Pages/RegistryListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Registry/RegistryCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Assets/Run.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Assets/Run.svg (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Shell/Assets/Run_V2_2x.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Commands/ExecuteItem.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Shell/FallbackExecuteItem.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Shell/Helpers/ExecutionShell.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Helpers/RunAsType.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Helpers/SettingsManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Helpers/ShellListPageHelpers.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.Shell/Icons.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Microsoft.CmdPal.Ext.Shell.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Pages/ShellListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.Shell/ShellCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/EmptyRecycleBinCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/EmptyRecycleBinConfirmation.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/ExecuteCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/ExecuteCommandConfirmation.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/Commands.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/Icons.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/MessageBoxHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/Native.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/NativeMethods.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/OpenInShellHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/ResultHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/SettingsManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/SystemPluginContext.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Helpers/Win32Helpers.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/OpenInShellCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Pages/SystemCommandPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/SystemCommandExtensionProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.System/SystemCommandsCache.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.dark.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.light.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResult.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Helpers/ResultHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeAndDateHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeDateCalculator.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Microsoft.CmdPal.Ext.TimeDate.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Pages/TimeDateExtensionPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.TimeDate/TimeDateCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Commands/OpenURLCommand.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Commands/SearchWebCommand.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WebSearch/FallbackExecuteSearchItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/FallbackOpenURLItem.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Helpers/DefaultBrowserInfo.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Helpers/HistoryItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WebSearch/NativeMethods.txt (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Pages/WebSearchListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/WebSearchCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WebSearch/WebSearchTopLevelCommandItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.svg (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/NativeMethods.txt (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/Pages/WinGetExtensionPage.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.resx (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionCommandsProvider.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionHost.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/WinGetStatics.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassModel.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassesDefinition.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClsidContext.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerFactory.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerStandardFactory.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WinGet/app.manifest (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Commands/CloseWindowCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Commands/ExplorerInfoResultCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Commands/KillProcessCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Commands/SwitchToWindowCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/ContextMenuHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/FuzzyMatching.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/LivePreview.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/OpenWindows.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/ResultHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchController.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchResult.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchString.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/Window.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Components/WindowProcess.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Helpers/CVirtualDesktopManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Helpers/IVirtualDesktopManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Helpers/NativeMethods.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Helpers/OSVersionHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Helpers/SettingsManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Helpers/ShellCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VDesktop.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Helpers/Win32Helpers.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Microsoft.CmdPal.Ext.WindowWalker.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Pages/WindowWalkerListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerListItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Action.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Commands/OpenServicesCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Commands/RestartServiceCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Commands/ServiceCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Helpers/ServiceHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Microsoft.CmdPal.Ext.WindowsServices.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Pages/ServicesListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/ServiceResult.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsServices/WindowsServicesCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSetting.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSettings.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Commands/CopySettingCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Commands/OpenSettingsCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ContextMenuHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/JsonSettingsListHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ResultHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/TranslationHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/UnsupportedSettingsHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/WindowsSettingsPathHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.dark.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.light.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Pages/WindowsSettingsListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.json (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.schema.json (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettingsCommandsProvider.cs (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.dark.png (100%) rename src/modules/cmdpal/{exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.light.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.png (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.svg (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileAsAdminCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ApplicationActivationManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/IApplicationActivationManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ITerminalQuery.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/SettingsManager.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalHelper.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalQuery.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Microsoft.CmdPal.Ext.WindowsTerminal.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Pages/ProfilesListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.Designer.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.resx (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalPackage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalProfile.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalTopLevelCommandItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/Microsoft.CmdPal.Ext.WindowsTerminal/WindowsTerminalCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Assets/LockScreenLogo.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Assets/SplashScreen.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Assets/Square150x150Logo.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Assets/Square44x44Logo.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Assets/StoreLogo.png (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Assets/Wide310x150Logo.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Package.appxmanifest (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/ProcessItem.cs (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/ProcessListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/ProcessMonitorCommandProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/ProcessMonitorExtension.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Program.cs (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Properties/PublishProfiles/win-arm64.pubxml (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Properties/PublishProfiles/win-x64.pubxml (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/Properties/launchSettings.json (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/SampleExtension.cs (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/SwitchToProcess.cs (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/TerminateProcess.cs (100%) rename src/modules/cmdpal/{Exts => ext}/ProcessMonitorExtension/app.manifest (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Assets/LockScreenLogo.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Assets/SplashScreen.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Assets/Square150x150Logo.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Assets/Square44x44Logo.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Assets/StoreLogo.png (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Assets/Wide310x150Logo.scale-200.png (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/EvilSampleListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/EvilSamplesPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/ExplodeInFiveSeconds.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Package.appxmanifest (100%) rename src/modules/cmdpal/{exts => ext}/SamplePagesExtension/Pages/SampleCommentsPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Pages/SampleContentPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Pages/SampleDynamicListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Pages/SampleListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Pages/SampleListPageWithDetails.cs (100%) rename src/modules/cmdpal/{exts => ext}/SamplePagesExtension/Pages/SampleMarkdownDetails.cs (100%) rename src/modules/cmdpal/{exts => ext}/SamplePagesExtension/Pages/SampleMarkdownManyBodies.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Pages/SampleMarkdownPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Pages/SampleSettingsPage.cs (100%) rename src/modules/cmdpal/{exts => ext}/SamplePagesExtension/Pages/SendMessageCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Program.cs (100%) rename src/modules/cmdpal/{exts => ext}/SamplePagesExtension/Properties/PublishProfiles/win-arm64.pubxml (100%) rename src/modules/cmdpal/{exts => ext}/SamplePagesExtension/Properties/PublishProfiles/win-x64.pubxml (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/Properties/launchSettings.json (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/SampleExtension.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/SamplePagesCommandsProvider.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/SamplePagesExtension.csproj (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/SampleUpdatingItemsPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/SamplesListPage.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/SelfImmolateCommand.cs (100%) rename src/modules/cmdpal/{Exts => ext}/SamplePagesExtension/app.manifest (100%) diff --git a/PowerToys.sln b/PowerToys.sln index 9b911b388b..401ba6d598 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -624,19 +624,19 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CommandPalette", "CommandPa EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Built-in Extensions", "Built-in Extensions", "{ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Apps", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj", "{6CE438DF-C245-4997-A360-0A0939E4BA34}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Apps", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Apps\Microsoft.CmdPal.Ext.Apps.csproj", "{6CE438DF-C245-4997-A360-0A0939E4BA34}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Bookmarks", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Bookmark\Microsoft.CmdPal.Ext.Bookmarks.csproj", "{E09AA983-C755-474F-83D6-A5CDF528C070}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Bookmarks", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Bookmark\Microsoft.CmdPal.Ext.Bookmarks.csproj", "{E09AA983-C755-474F-83D6-A5CDF528C070}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Calc", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj", "{6D56B64D-FF1F-488F-AFED-9B9854A5D399}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Calc", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Calc\Microsoft.CmdPal.Ext.Calc.csproj", "{6D56B64D-FF1F-488F-AFED-9B9854A5D399}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Registry", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Registry\Microsoft.CmdPal.Ext.Registry.csproj", "{92EC89E4-9972-453A-8A1A-3A9E230C146A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Registry", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Registry\Microsoft.CmdPal.Ext.Registry.csproj", "{92EC89E4-9972-453A-8A1A-3A9E230C146A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsServices", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WindowsServices\Microsoft.CmdPal.Ext.WindowsServices.csproj", "{51939B4F-1F62-4BFF-A6A2-C08646E5BE95}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsServices", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsServices\Microsoft.CmdPal.Ext.WindowsServices.csproj", "{51939B4F-1F62-4BFF-A6A2-C08646E5BE95}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsSettings", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WindowsSettings\Microsoft.CmdPal.Ext.WindowsSettings.csproj", "{D1160404-D3D1-497A-883A-4059C07C2273}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsSettings", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsSettings\Microsoft.CmdPal.Ext.WindowsSettings.csproj", "{D1160404-D3D1-497A-883A-4059C07C2273}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsTerminal", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WindowsTerminal\Microsoft.CmdPal.Ext.WindowsTerminal.csproj", "{40F6D69D-E321-400F-A767-5628C7AE453D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowsTerminal", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowsTerminal\Microsoft.CmdPal.Ext.WindowsTerminal.csproj", "{40F6D69D-E321-400F-A767-5628C7AE453D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extension SDK", "Extension SDK", "{F3D09629-59A2-4924-A4B9-D6BFAA2C1B49}" EndProject @@ -650,9 +650,9 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.Terminal.UI", "sr EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sample Extensions", "Sample Extensions", "{071E18A4-A530-46B8-AB7D-B862EE55E24E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessMonitorExtension", "src\modules\cmdpal\Exts\ProcessMonitorExtension\ProcessMonitorExtension.csproj", "{C846F7A7-792A-47D9-B0CB-417C900EE03D}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ProcessMonitorExtension", "src\modules\cmdpal\ext\ProcessMonitorExtension\ProcessMonitorExtension.csproj", "{C846F7A7-792A-47D9-B0CB-417C900EE03D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SamplePagesExtension", "src\modules\cmdpal\Exts\SamplePagesExtension\SamplePagesExtension.csproj", "{C831231F-891C-4572-9694-45062534B42A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SamplePagesExtension", "src\modules\cmdpal\ext\SamplePagesExtension\SamplePagesExtension.csproj", "{C831231F-891C-4572-9694-45062534B42A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{7520A2FE-00A2-49B8-83ED-DB216E874C04}" EndProject @@ -660,7 +660,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.UI", "src\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.UI.ViewModels", "src\modules\cmdpal\Microsoft.CmdPal.UI.ViewModels\Microsoft.CmdPal.UI.ViewModels.csproj", "{C66020D1-CB10-4CF7-8715-84C97FD5E5E2}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.ClipboardHistory", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.ClipboardHistory\Microsoft.CmdPal.Ext.ClipboardHistory.csproj", "{79775343-7A3D-445D-9104-3DD5B2893DF9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.ClipboardHistory", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.ClipboardHistory\Microsoft.CmdPal.Ext.ClipboardHistory.csproj", "{79775343-7A3D-445D-9104-3DD5B2893DF9}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalModuleInterface", "src\modules\cmdpal\CmdPalModuleInterface\CmdPalModuleInterface.vcxproj", "{0ADEB797-C8C7-4FFA-ACD5-2AF6CAD7ECD8}" EndProject @@ -668,15 +668,15 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkspacesCsharpLibrary", " EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewPlus.ShellExtension.win10", "src\modules\NewPlus\NewShellExtensionContextMenu.win10\NewPlus.ShellExtension.win10.vcxproj", "{0DB0F63A-D2F8-4DA3-A650-2D0B8724218E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Indexer", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Indexer\Microsoft.CmdPal.Ext.Indexer.csproj", "{453CBB73-A3CB-4D0B-8D24-6940B86FE21D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Indexer", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Indexer\Microsoft.CmdPal.Ext.Indexer.csproj", "{453CBB73-A3CB-4D0B-8D24-6940B86FE21D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Shell", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj", "{C0CE3B5E-16D3-495D-B335-CA791B660162}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.Shell", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.Shell\Microsoft.CmdPal.Ext.Shell.csproj", "{C0CE3B5E-16D3-495D-B335-CA791B660162}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowWalker", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WindowWalker\Microsoft.CmdPal.Ext.WindowWalker.csproj", "{3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CmdPal.Ext.WindowWalker", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WindowWalker\Microsoft.CmdPal.Ext.WindowWalker.csproj", "{3A9A7297-92C4-4F16-B6F9-8D4AB652C86C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WebSearch", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WebSearch\Microsoft.CmdPal.Ext.WebSearch.csproj", "{605E914B-7232-4789-AF46-BF5D3DDFC14E}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WebSearch", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WebSearch\Microsoft.CmdPal.Ext.WebSearch.csproj", "{605E914B-7232-4789-AF46-BF5D3DDFC14E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WinGet", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj", "{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.WinGet", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.WinGet\Microsoft.CmdPal.Ext.WinGet.csproj", "{E81A7D20-9862-ABDB-0AAE-9BC5B517A9F9}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvancedPaste.UnitTests", "src\modules\AdvancedPaste\AdvancedPaste.UnitTests\AdvancedPaste.UnitTests.csproj", "{D5E5F5EA-1B6C-4A73-88BE-304F36C9E4EE}" EndProject @@ -690,7 +690,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItModuleInterface", "sr EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZoomItSettingsInterop", "src\modules\ZoomIt\ZoomItSettingsInterop\ZoomItSettingsInterop.vcxproj", "{CA7D8106-30B9-4AEC-9D05-B69B31B8C461}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.TimeDate", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.TimeDate\Microsoft.CmdPal.Ext.TimeDate.csproj", "{DCC6BD67-17BB-47AA-B507-FB0FE43A7449}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.TimeDate", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.TimeDate\Microsoft.CmdPal.Ext.TimeDate.csproj", "{DCC6BD67-17BB-47AA-B507-FB0FE43A7449}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UITestAutomation", "src\common\UITestAutomation\UITestAutomation.csproj", "{A558C25D-2007-498E-8B6F-43405AFAE9E2}" EndProject @@ -704,7 +704,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Hosts.UITests", "src\module EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryPreview.FuzzTests", "src\modules\registrypreview\RegistryPreview.FuzzTests\RegistryPreview.FuzzTests.csproj", "{5702B3CC-8575-48D5-83D8-15BB42269CD3}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\Exts\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj index ed8831915a..342dbe251c 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj @@ -31,7 +31,7 @@ - + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj b/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj index 9398315223..80fbc58a5e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj @@ -97,26 +97,26 @@ - - - + + + - - - - - - - - - - - - + + + + + + + + + + + + True diff --git a/src/modules/cmdpal/doc/command-pal-anatomy/command-palette-anatomy.md b/src/modules/cmdpal/doc/command-pal-anatomy/command-palette-anatomy.md index 2af4771e16..878daaa69a 100644 --- a/src/modules/cmdpal/doc/command-pal-anatomy/command-palette-anatomy.md +++ b/src/modules/cmdpal/doc/command-pal-anatomy/command-palette-anatomy.md @@ -152,7 +152,7 @@ We've made it easy to build a new extension. Just follow these steps: 2. Run the following PowerShell script, replacing "MastodonExtension" with the `Name` of your extension and "Mastodon extension for cmdpal" with the `DisplayName` of the [command that will show up in the root view](#root-view) of the Command Palette: ```powershell -.\Exts\NewExtension.ps1 -name MastodonExtension -DisplayName "Mastodon extension for cmdpal" +.\ext\NewExtension.ps1 -name MastodonExtension -DisplayName "Mastodon extension for cmdpal" ``` 3. Open the solution in Visual Studio. diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AllAppsCommandProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsCommandProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AllAppsCommandProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsCommandProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/AllAppsSettings.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsSettings.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/AllAppsSettings.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsSettings.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AppCache.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppCache.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AppCache.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppCache.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/AppCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/AppCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AppItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AppItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AppListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/AppListItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Assets/AllApps.svg diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Commands/OpenInConsoleCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Commands/OpenInConsoleCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Commands/OpenInConsoleCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Commands/OpenInConsoleCommand.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Commands/OpenPathCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Commands/OpenPathCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Commands/OpenPathCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Commands/OpenPathCommand.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Commands/RunAsAdminCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Commands/RunAsAdminCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Commands/RunAsAdminCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Commands/RunAsAdminCommand.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Commands/RunAsUserCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Commands/RunAsUserCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Commands/RunAsUserCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Commands/RunAsUserCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Microsoft.CmdPal.Ext.Apps.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Microsoft.CmdPal.Ext.Apps.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Microsoft.CmdPal.Ext.Apps.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Microsoft.CmdPal.Ext.Apps.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/NativeMethods.txt b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/NativeMethods.txt similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/NativeMethods.txt rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/NativeMethods.txt diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/AppxFactory.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/AppxFactory.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/AppxFactory.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/AppxFactory.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/AppxPackageHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/AppxPackageHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/AppxPackageHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/AppxPackageHelper.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/DisabledProgramSource.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/DisabledProgramSource.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/DisabledProgramSource.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/DisabledProgramSource.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IApplicationActivationManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IApplicationActivationManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IApplicationActivationManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IApplicationActivationManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxFactory.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxFactory.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxFactory.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxFactory.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplication.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplication.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplication.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplication.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplicationsEnumerator.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplicationsEnumerator.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplicationsEnumerator.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestApplicationsEnumerator.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestProperties.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestProperties.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestProperties.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestProperties.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestReader.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestReader.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestReader.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IAppxManifestReader.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/IFileVersionInfoWrapper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IFileVersionInfoWrapper.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/IFileVersionInfoWrapper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IFileVersionInfoWrapper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IPackage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IPackage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IPackage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IPackage.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/IPackageCatalog.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IPackageCatalog.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/IPackageCatalog.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IPackageCatalog.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IPackageManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IPackageManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IPackageManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IPackageManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IProgram.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IProgram.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/IProgram.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/IProgram.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/LogoType.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/LogoType.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/LogoType.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/LogoType.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/PackageCatalogWrapper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageCatalogWrapper.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/PackageCatalogWrapper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageCatalogWrapper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/PackageManagerWrapper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageManagerWrapper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/PackageManagerWrapper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageManagerWrapper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/PackageWrapper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageWrapper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/PackageWrapper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/PackageWrapper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/ProgramSource.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/ProgramSource.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/ProgramSource.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/ProgramSource.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/ReparsePoint.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/ReparsePoint.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Programs/ReparsePoint.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/ReparsePoint.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWP.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Properties/Resources.resx diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/EventHandler.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/EventHandler.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/EventHandler.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/EventHandler.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/FileSystemWatcherWrapper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/FileSystemWatcherWrapper.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/FileSystemWatcherWrapper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/FileSystemWatcherWrapper.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/IFileSystemWatcherWrapper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/IFileSystemWatcherWrapper.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/IFileSystemWatcherWrapper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/IFileSystemWatcherWrapper.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/IProgramRepository.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/IProgramRepository.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/IProgramRepository.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/IProgramRepository.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/IRepository`1.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/IRepository`1.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/IRepository`1.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/IRepository`1.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/ListRepository`1.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/ListRepository`1.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/ListRepository`1.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/ListRepository`1.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/PackageRepository.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/PackageRepository.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/PackageRepository.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/PackageRepository.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramFileSystemWatchers.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramFileSystemWatchers.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramFileSystemWatchers.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramFileSystemWatchers.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramRepository.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramRepository.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramRepository.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Storage/Win32ProgramRepository.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/IShellLinkHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/IShellLinkHelper.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/IShellLinkHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/IShellLinkHelper.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/Native.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/Native.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/Native.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/Native.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/ShellCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/ShellCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellCommand.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/ShellLinkHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLinkHelper.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/ShellLinkHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLinkHelper.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/ShellLocalization.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLocalization.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/ShellLocalization.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ShellLocalization.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/Theme.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/Theme.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/Theme.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/Theme.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/ThemeHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ThemeHelper.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Apps/Utils/ThemeHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Utils/ThemeHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Assets/Bookmark.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/BookmarkData.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkData.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/BookmarkData.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkData.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderForm.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderForm.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderForm.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderForm.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkPlaceholderPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/Bookmarks.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Bookmarks.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/Bookmarks.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Bookmarks.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/BookmarksCommandProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarksCommandProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/BookmarksCommandProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarksCommandProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj similarity index 93% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj index eaa4ac6b42..7bbf1efc5f 100644 --- a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj @@ -14,7 +14,7 @@ - + diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Bookmark/OpenInTerminalCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/OpenInTerminalCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Bookmark/OpenInTerminalCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/OpenInTerminalCommand.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Properties/Resources.resx diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Bookmark/UrlCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/UrlCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Bookmark/UrlCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/UrlCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Assets/Calculator.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Calc/CalculatorCommandProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/CalculatorCommandProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Calc/CalculatorCommandProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/CalculatorCommandProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Calc/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Calc/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Calc/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Calc/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/ClipboardHistoryCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/ClipboardHistoryCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/ClipboardHistoryCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/ClipboardHistoryCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/CopyCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/CopyCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/CopyCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/CopyCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/PasteCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/PasteCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/PasteCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Commands/PasteCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/ClipboardHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/ClipboardHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/ClipboardHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/ClipboardHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/NativeMethods.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/NativeMethods.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/NativeMethods.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/NativeMethods.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardFormat.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardFormat.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardFormat.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardFormat.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Models/ClipboardItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Pages/ClipboardHistoryListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Pages/ClipboardHistoryListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.ClipboardHistory/Pages/ClipboardHistoryListPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Pages/ClipboardHistoryListPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Assets/FileExplorer.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/CopyPathCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/CopyPathCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/CopyPathCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/CopyPathCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/OpenFileCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/OpenFileCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/OpenFileCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/OpenFileCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/OpenInConsoleCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/OpenInConsoleCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/OpenInConsoleCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/OpenInConsoleCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/OpenPropertiesCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/OpenPropertiesCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/OpenPropertiesCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/OpenPropertiesCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/OpenWithCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/OpenWithCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Commands/OpenWithCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Commands/OpenWithCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Data/IndexerItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Data/IndexerItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Data/IndexerListItem.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/FallbackOpenFileItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/FallbackOpenFileItem.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/FallbackOpenFileItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/FallbackOpenFileItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/DataSourceManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/DataSourceManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/DataSourceManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/DataSourceManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROP.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROP.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROP.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROP.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPIDSET.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPIDSET.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPIDSET.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPIDSET.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPSET.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPSET.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPSET.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/DBPROPSET.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowset.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowset.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowset.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowset.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowsetInfo.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowsetInfo.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowsetInfo.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/OleDB/IRowsetInfo.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchQuery.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchQuery.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchQuery.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchQuery.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchResult.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchResult.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchResult.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SearchResult.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManager.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManager.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManagerClass.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManagerClass.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManagerClass.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchCatalogManagerClass.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManager.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManager.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManagerClass.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManagerClass.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManagerClass.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchManagerClass.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelper.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelper.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelperClass.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelperClass.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelperClass.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/CSearchQueryHelperClass.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchCatalogManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchCatalogManager.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchCatalogManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchCatalogManager.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchManager.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchManager.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchQueryHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchQueryHelper.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchQueryHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/SystemSearch/ISearchQueryHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/QueryStringBuilder.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/QueryStringBuilder.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/QueryStringBuilder.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/QueryStringBuilder.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/UrlToFilePathConverter.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/UrlToFilePathConverter.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/UrlToFilePathConverter.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Indexer/Utils/UrlToFilePathConverter.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/IndexerCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/IndexerCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/IndexerCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/IndexerCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Microsoft.CmdPal.Ext.Indexer.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Native/NativeHelpers.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Native/NativeHelpers.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Native/NativeHelpers.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Native/NativeHelpers.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/NativeMethods.txt b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/NativeMethods.txt similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/NativeMethods.txt rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/NativeMethods.txt diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryExplorePage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryExplorePage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryExplorePage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryExplorePage.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryPage.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/DirectoryPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Pages/ExploreListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ExploreListItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Pages/ExploreListItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/ExploreListItem.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Pages/Icons.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/Icons.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Pages/Icons.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/Icons.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Pages/IndexerPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/IndexerPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Indexer/Pages/IndexerPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Pages/IndexerPage.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Indexer/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Assets/Registry.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Assets/Registry.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Assets/Registry.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Assets/Registry.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Assets/Registry.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Assets/Registry.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Assets/Registry.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Assets/Registry.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Classes/RegistryEntry.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Classes/RegistryEntry.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Classes/RegistryEntry.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Classes/RegistryEntry.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Commands/CopyRegistryInfoCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Commands/CopyRegistryInfoCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Commands/CopyRegistryInfoCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Commands/CopyRegistryInfoCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Commands/OpenKeyInEditorCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Commands/OpenKeyInEditorCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Commands/OpenKeyInEditorCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Commands/OpenKeyInEditorCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Constants/KeyName.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Constants/KeyName.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Constants/KeyName.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Constants/KeyName.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Constants/MaxTextLength.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Constants/MaxTextLength.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Constants/MaxTextLength.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Constants/MaxTextLength.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/CopyType.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/CopyType.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/CopyType.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/CopyType.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Enumerations/TruncateSide.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Enumerations/TruncateSide.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Enumerations/TruncateSide.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Enumerations/TruncateSide.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/ContextMenuHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ContextMenuHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/ContextMenuHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ContextMenuHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/QueryHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/QueryHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/QueryHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/QueryHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/RegistryHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ResultHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/ValueHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ValueHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Helpers/ValueHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Helpers/ValueHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Microsoft.CmdPal.Ext.Registry.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Microsoft.CmdPal.Ext.Registry.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Microsoft.CmdPal.Ext.Registry.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Microsoft.CmdPal.Ext.Registry.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Pages/RegistryListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Pages/RegistryListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Pages/RegistryListPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Pages/RegistryListPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/RegistryCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/RegistryCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Registry/RegistryCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Registry/RegistryCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Assets/Run.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Assets/Run.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Assets/Run.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Assets/Run.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Assets/Run.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Assets/Run.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Assets/Run.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Assets/Run.svg diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Shell/Assets/Run_V2_2x.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Assets/Run_V2_2x.svg similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Shell/Assets/Run_V2_2x.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Assets/Run_V2_2x.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Commands/ExecuteItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Commands/ExecuteItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Commands/ExecuteItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Commands/ExecuteItem.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Shell/FallbackExecuteItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/FallbackExecuteItem.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Shell/FallbackExecuteItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/FallbackExecuteItem.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Shell/Helpers/ExecutionShell.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/ExecutionShell.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Shell/Helpers/ExecutionShell.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/ExecutionShell.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Helpers/RunAsType.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/RunAsType.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Helpers/RunAsType.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/RunAsType.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/SettingsManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Helpers/SettingsManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/SettingsManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Helpers/ShellListPageHelpers.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/ShellListPageHelpers.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Helpers/ShellListPageHelpers.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Helpers/ShellListPageHelpers.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Shell/Icons.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Icons.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.Shell/Icons.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Icons.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Microsoft.CmdPal.Ext.Shell.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Microsoft.CmdPal.Ext.Shell.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Microsoft.CmdPal.Ext.Shell.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Microsoft.CmdPal.Ext.Shell.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Pages/ShellListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/ShellListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Pages/ShellListPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Pages/ShellListPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/ShellCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/ShellCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.Shell/ShellCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Shell/ShellCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Assets/SystemCommand.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/EmptyRecycleBinCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/EmptyRecycleBinCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/EmptyRecycleBinCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/EmptyRecycleBinCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/EmptyRecycleBinConfirmation.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/EmptyRecycleBinConfirmation.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/EmptyRecycleBinConfirmation.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/EmptyRecycleBinConfirmation.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/ExecuteCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/ExecuteCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/ExecuteCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/ExecuteCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/ExecuteCommandConfirmation.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/ExecuteCommandConfirmation.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/ExecuteCommandConfirmation.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/ExecuteCommandConfirmation.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/Commands.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Commands.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/Commands.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Commands.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/Icons.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Icons.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/Icons.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Icons.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/MessageBoxHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/MessageBoxHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/MessageBoxHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/MessageBoxHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/Native.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Native.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/Native.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Native.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/NativeMethods.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NativeMethods.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/NativeMethods.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NativeMethods.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/OpenInShellHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/OpenInShellHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/OpenInShellHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/OpenInShellHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/ResultHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/ResultHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/ResultHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/SettingsManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/SettingsManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/SettingsManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/SystemPluginContext.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/SystemPluginContext.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/SystemPluginContext.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/SystemPluginContext.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/Win32Helpers.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Win32Helpers.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Helpers/Win32Helpers.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Win32Helpers.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/OpenInShellCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/OpenInShellCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/OpenInShellCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/OpenInShellCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Pages/SystemCommandPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Pages/SystemCommandPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Pages/SystemCommandPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Pages/SystemCommandPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/SystemCommandExtensionProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/SystemCommandExtensionProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/SystemCommandExtensionProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/SystemCommandExtensionProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/SystemCommandsCache.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/SystemCommandsCache.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.System/SystemCommandsCache.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/SystemCommandsCache.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Assets/TimeDate.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.dark.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.dark.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.dark.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.dark.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.light.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.light.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.light.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Assets/Warning.light.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResult.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResult.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResult.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResult.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/ResultHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/ResultHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/ResultHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/SettingsManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeAndDateHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeAndDateHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeAndDateHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeAndDateHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeDateCalculator.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeDateCalculator.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeDateCalculator.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeDateCalculator.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Microsoft.CmdPal.Ext.TimeDate.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Microsoft.CmdPal.Ext.TimeDate.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Microsoft.CmdPal.Ext.TimeDate.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Microsoft.CmdPal.Ext.TimeDate.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Pages/TimeDateExtensionPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Pages/TimeDateExtensionPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Pages/TimeDateExtensionPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Pages/TimeDateExtensionPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/TimeDateCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/TimeDateCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.TimeDate/TimeDateCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/TimeDateCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Assets/WebSearch.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Commands/OpenURLCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Commands/OpenURLCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Commands/OpenURLCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Commands/OpenURLCommand.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WebSearch/Commands/SearchWebCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Commands/SearchWebCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WebSearch/Commands/SearchWebCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Commands/SearchWebCommand.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WebSearch/FallbackExecuteSearchItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/FallbackExecuteSearchItem.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WebSearch/FallbackExecuteSearchItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/FallbackExecuteSearchItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/FallbackOpenURLItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/FallbackOpenURLItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/FallbackOpenURLItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/FallbackOpenURLItem.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WebSearch/Helpers/DefaultBrowserInfo.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/DefaultBrowserInfo.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WebSearch/Helpers/DefaultBrowserInfo.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/DefaultBrowserInfo.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Helpers/HistoryItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/HistoryItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Helpers/HistoryItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/HistoryItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WebSearch/NativeMethods.txt b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/NativeMethods.txt similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WebSearch/NativeMethods.txt rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/NativeMethods.txt diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Pages/WebSearchListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Pages/WebSearchListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Pages/WebSearchListPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Pages/WebSearchListPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/WebSearchCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/WebSearchCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/WebSearchCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/WebSearchCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/WebSearchTopLevelCommandItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/WebSearchTopLevelCommandItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WebSearch/WebSearchTopLevelCommandItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/WebSearchTopLevelCommandItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Extension.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Store.dark.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/Store.light.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Assets/WinGet.svg diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/NativeMethods.txt b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/NativeMethods.txt similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/NativeMethods.txt rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/NativeMethods.txt diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageCommand.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/InstallPackageListItem.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Pages/WinGetExtensionPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/WinGetExtensionPage.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Pages/WinGetExtensionPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Pages/WinGetExtensionPage.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Properties/Resources.resx diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionCommandsProvider.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionHost.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionHost.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionHost.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetExtensionHost.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WinGetStatics.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetStatics.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WinGetStatics.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WinGetStatics.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassModel.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassModel.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassModel.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassModel.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassesDefinition.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassesDefinition.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassesDefinition.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClassesDefinition.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClsidContext.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClsidContext.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClsidContext.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/ClsidContext.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerFactory.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerFactory.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerFactory.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerFactory.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerStandardFactory.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerStandardFactory.cs similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerStandardFactory.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerStandardFactory.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/app.manifest b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/app.manifest similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WinGet/app.manifest rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/app.manifest diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Assets/WindowWalker.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Commands/CloseWindowCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/CloseWindowCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Commands/CloseWindowCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/CloseWindowCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Commands/ExplorerInfoResultCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/ExplorerInfoResultCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Commands/ExplorerInfoResultCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/ExplorerInfoResultCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Commands/KillProcessCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/KillProcessCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Commands/KillProcessCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/KillProcessCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Commands/SwitchToWindowCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/SwitchToWindowCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Commands/SwitchToWindowCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Commands/SwitchToWindowCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/ContextMenuHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/ContextMenuHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/ContextMenuHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/ContextMenuHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/FuzzyMatching.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/FuzzyMatching.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/FuzzyMatching.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/FuzzyMatching.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/LivePreview.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/LivePreview.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/LivePreview.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/LivePreview.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/OpenWindows.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/OpenWindows.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/OpenWindows.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/OpenWindows.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/ResultHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/ResultHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/ResultHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchController.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchController.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchController.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchController.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchResult.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchResult.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchResult.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchResult.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchString.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchString.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchString.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/SearchString.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/Window.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/Window.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/Window.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/Window.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/WindowProcess.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/WindowProcess.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Components/WindowProcess.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Components/WindowProcess.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/CVirtualDesktopManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/CVirtualDesktopManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/CVirtualDesktopManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/CVirtualDesktopManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/IVirtualDesktopManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/IVirtualDesktopManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/IVirtualDesktopManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/IVirtualDesktopManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/NativeMethods.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/NativeMethods.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/NativeMethods.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/NativeMethods.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/OSVersionHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/OSVersionHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/OSVersionHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/OSVersionHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/SettingsManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/SettingsManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/SettingsManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/ShellCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/ShellCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/ShellCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/ShellCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VDesktop.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VDesktop.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VDesktop.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VDesktop.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/Win32Helpers.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/Win32Helpers.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Helpers/Win32Helpers.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/Win32Helpers.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Microsoft.CmdPal.Ext.WindowWalker.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Microsoft.CmdPal.Ext.WindowWalker.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Microsoft.CmdPal.Ext.WindowWalker.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Microsoft.CmdPal.Ext.WindowWalker.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Pages/WindowWalkerListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Pages/WindowWalkerListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Pages/WindowWalkerListPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Pages/WindowWalkerListPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerListItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerListItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/WindowWalkerListItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Action.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Action.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Action.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Action.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Assets/Services.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Commands/OpenServicesCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Commands/OpenServicesCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Commands/OpenServicesCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Commands/OpenServicesCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Commands/RestartServiceCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Commands/RestartServiceCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Commands/RestartServiceCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Commands/RestartServiceCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Commands/ServiceCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Commands/ServiceCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Commands/ServiceCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Commands/ServiceCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Helpers/ServiceHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Helpers/ServiceHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Helpers/ServiceHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Helpers/ServiceHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Microsoft.CmdPal.Ext.WindowsServices.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Microsoft.CmdPal.Ext.WindowsServices.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Microsoft.CmdPal.Ext.WindowsServices.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Microsoft.CmdPal.Ext.WindowsServices.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Pages/ServicesListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Pages/ServicesListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Pages/ServicesListPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Pages/ServicesListPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/ServiceResult.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/ServiceResult.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/ServiceResult.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/ServiceResult.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/WindowsServicesCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/WindowsServicesCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsServices/WindowsServicesCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/WindowsServicesCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Assets/WindowsSettings.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSetting.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSetting.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSetting.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSetting.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSettings.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSettings.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSettings.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Classes/WindowsSettings.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Commands/CopySettingCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Commands/CopySettingCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Commands/CopySettingCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Commands/CopySettingCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Commands/OpenSettingsCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Commands/OpenSettingsCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Commands/OpenSettingsCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Commands/OpenSettingsCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ContextMenuHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ContextMenuHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ContextMenuHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ContextMenuHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/JsonSettingsListHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/JsonSettingsListHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/JsonSettingsListHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/JsonSettingsListHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ResultHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ResultHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/ResultHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/TranslationHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/TranslationHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/TranslationHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/TranslationHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/UnsupportedSettingsHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/UnsupportedSettingsHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/UnsupportedSettingsHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/UnsupportedSettingsHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/WindowsSettingsPathHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/WindowsSettingsPathHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/WindowsSettingsPathHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/WindowsSettingsPathHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.dark.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.dark.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.dark.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.dark.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.light.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.light.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.light.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Images/WindowsSettings.light.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Pages/WindowsSettingsListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Pages/WindowsSettingsListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Pages/WindowsSettingsListPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Pages/WindowsSettingsListPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.json b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.json similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.json rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.json diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.schema.json b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.schema.json similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.schema.json rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettings.schema.json diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettingsCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettingsCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettingsCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/WindowsSettingsCommandsProvider.cs diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.dark.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.dark.png similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.dark.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.dark.png diff --git a/src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.light.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.light.png similarity index 100% rename from src/modules/cmdpal/exts/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.light.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.light.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.png b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.png similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.png rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.png diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.svg b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.svg similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.svg rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Assets/WindowsTerminal.svg diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileAsAdminCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileAsAdminCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileAsAdminCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileAsAdminCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileCommand.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileCommand.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ApplicationActivationManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ApplicationActivationManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ApplicationActivationManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ApplicationActivationManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/IApplicationActivationManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/IApplicationActivationManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/IApplicationActivationManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/IApplicationActivationManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ITerminalQuery.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ITerminalQuery.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ITerminalQuery.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ITerminalQuery.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/SettingsManager.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/SettingsManager.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/SettingsManager.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalHelper.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalHelper.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalHelper.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalQuery.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalQuery.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalQuery.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/TerminalQuery.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Microsoft.CmdPal.Ext.WindowsTerminal.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Microsoft.CmdPal.Ext.WindowsTerminal.csproj similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Microsoft.CmdPal.Ext.WindowsTerminal.csproj rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Microsoft.CmdPal.Ext.WindowsTerminal.csproj diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Pages/ProfilesListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Pages/ProfilesListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Pages/ProfilesListPage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Pages/ProfilesListPage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.Designer.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.Designer.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.Designer.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.resx similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.resx rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Properties/Resources.resx diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalPackage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalPackage.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalPackage.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalPackage.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalProfile.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalProfile.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalProfile.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalProfile.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalTopLevelCommandItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalTopLevelCommandItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalTopLevelCommandItem.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/TerminalTopLevelCommandItem.cs diff --git a/src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/WindowsTerminalCommandsProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/WindowsTerminalCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/Microsoft.CmdPal.Ext.WindowsTerminal/WindowsTerminalCommandsProvider.cs rename to src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/WindowsTerminalCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/LockScreenLogo.scale-200.png b/src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/LockScreenLogo.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/LockScreenLogo.scale-200.png rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/LockScreenLogo.scale-200.png diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/SplashScreen.scale-200.png b/src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/SplashScreen.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/SplashScreen.scale-200.png rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/SplashScreen.scale-200.png diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/Square150x150Logo.scale-200.png b/src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/Square150x150Logo.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/Square150x150Logo.scale-200.png rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/Square150x150Logo.scale-200.png diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/Square44x44Logo.scale-200.png b/src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/Square44x44Logo.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/Square44x44Logo.scale-200.png rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/Square44x44Logo.scale-200.png diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/StoreLogo.png b/src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/StoreLogo.png similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/StoreLogo.png rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/StoreLogo.png diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/Wide310x150Logo.scale-200.png b/src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/Wide310x150Logo.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Assets/Wide310x150Logo.scale-200.png rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Assets/Wide310x150Logo.scale-200.png diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Package.appxmanifest b/src/modules/cmdpal/ext/ProcessMonitorExtension/Package.appxmanifest similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Package.appxmanifest rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Package.appxmanifest diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/ProcessItem.cs b/src/modules/cmdpal/ext/ProcessMonitorExtension/ProcessItem.cs similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/ProcessItem.cs rename to src/modules/cmdpal/ext/ProcessMonitorExtension/ProcessItem.cs diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/ProcessListPage.cs b/src/modules/cmdpal/ext/ProcessMonitorExtension/ProcessListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/ProcessListPage.cs rename to src/modules/cmdpal/ext/ProcessMonitorExtension/ProcessListPage.cs diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/ProcessMonitorCommandProvider.cs b/src/modules/cmdpal/ext/ProcessMonitorExtension/ProcessMonitorCommandProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/ProcessMonitorCommandProvider.cs rename to src/modules/cmdpal/ext/ProcessMonitorExtension/ProcessMonitorCommandProvider.cs diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/ProcessMonitorExtension.csproj b/src/modules/cmdpal/ext/ProcessMonitorExtension/ProcessMonitorExtension.csproj similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/ProcessMonitorExtension.csproj rename to src/modules/cmdpal/ext/ProcessMonitorExtension/ProcessMonitorExtension.csproj diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Program.cs b/src/modules/cmdpal/ext/ProcessMonitorExtension/Program.cs similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Program.cs rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Program.cs diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Properties/PublishProfiles/win-arm64.pubxml b/src/modules/cmdpal/ext/ProcessMonitorExtension/Properties/PublishProfiles/win-arm64.pubxml similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Properties/PublishProfiles/win-arm64.pubxml rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Properties/PublishProfiles/win-arm64.pubxml diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Properties/PublishProfiles/win-x64.pubxml b/src/modules/cmdpal/ext/ProcessMonitorExtension/Properties/PublishProfiles/win-x64.pubxml similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Properties/PublishProfiles/win-x64.pubxml rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Properties/PublishProfiles/win-x64.pubxml diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/Properties/launchSettings.json b/src/modules/cmdpal/ext/ProcessMonitorExtension/Properties/launchSettings.json similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/Properties/launchSettings.json rename to src/modules/cmdpal/ext/ProcessMonitorExtension/Properties/launchSettings.json diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/SampleExtension.cs b/src/modules/cmdpal/ext/ProcessMonitorExtension/SampleExtension.cs similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/SampleExtension.cs rename to src/modules/cmdpal/ext/ProcessMonitorExtension/SampleExtension.cs diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/SwitchToProcess.cs b/src/modules/cmdpal/ext/ProcessMonitorExtension/SwitchToProcess.cs similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/SwitchToProcess.cs rename to src/modules/cmdpal/ext/ProcessMonitorExtension/SwitchToProcess.cs diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/TerminateProcess.cs b/src/modules/cmdpal/ext/ProcessMonitorExtension/TerminateProcess.cs similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/TerminateProcess.cs rename to src/modules/cmdpal/ext/ProcessMonitorExtension/TerminateProcess.cs diff --git a/src/modules/cmdpal/Exts/ProcessMonitorExtension/app.manifest b/src/modules/cmdpal/ext/ProcessMonitorExtension/app.manifest similarity index 100% rename from src/modules/cmdpal/Exts/ProcessMonitorExtension/app.manifest rename to src/modules/cmdpal/ext/ProcessMonitorExtension/app.manifest diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Assets/LockScreenLogo.scale-200.png b/src/modules/cmdpal/ext/SamplePagesExtension/Assets/LockScreenLogo.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Assets/LockScreenLogo.scale-200.png rename to src/modules/cmdpal/ext/SamplePagesExtension/Assets/LockScreenLogo.scale-200.png diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Assets/SplashScreen.scale-200.png b/src/modules/cmdpal/ext/SamplePagesExtension/Assets/SplashScreen.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Assets/SplashScreen.scale-200.png rename to src/modules/cmdpal/ext/SamplePagesExtension/Assets/SplashScreen.scale-200.png diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Assets/Square150x150Logo.scale-200.png b/src/modules/cmdpal/ext/SamplePagesExtension/Assets/Square150x150Logo.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Assets/Square150x150Logo.scale-200.png rename to src/modules/cmdpal/ext/SamplePagesExtension/Assets/Square150x150Logo.scale-200.png diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Assets/Square44x44Logo.scale-200.png b/src/modules/cmdpal/ext/SamplePagesExtension/Assets/Square44x44Logo.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Assets/Square44x44Logo.scale-200.png rename to src/modules/cmdpal/ext/SamplePagesExtension/Assets/Square44x44Logo.scale-200.png diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/src/modules/cmdpal/ext/SamplePagesExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png rename to src/modules/cmdpal/ext/SamplePagesExtension/Assets/Square44x44Logo.targetsize-24_altform-unplated.png diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Assets/StoreLogo.png b/src/modules/cmdpal/ext/SamplePagesExtension/Assets/StoreLogo.png similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Assets/StoreLogo.png rename to src/modules/cmdpal/ext/SamplePagesExtension/Assets/StoreLogo.png diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Assets/Wide310x150Logo.scale-200.png b/src/modules/cmdpal/ext/SamplePagesExtension/Assets/Wide310x150Logo.scale-200.png similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Assets/Wide310x150Logo.scale-200.png rename to src/modules/cmdpal/ext/SamplePagesExtension/Assets/Wide310x150Logo.scale-200.png diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/EvilSampleListPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/EvilSampleListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/EvilSampleListPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/EvilSampleListPage.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/EvilSamplesPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/EvilSamplesPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/ExplodeInFiveSeconds.cs b/src/modules/cmdpal/ext/SamplePagesExtension/ExplodeInFiveSeconds.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/ExplodeInFiveSeconds.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/ExplodeInFiveSeconds.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Package.appxmanifest b/src/modules/cmdpal/ext/SamplePagesExtension/Package.appxmanifest similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Package.appxmanifest rename to src/modules/cmdpal/ext/SamplePagesExtension/Package.appxmanifest diff --git a/src/modules/cmdpal/exts/SamplePagesExtension/Pages/SampleCommentsPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleCommentsPage.cs similarity index 100% rename from src/modules/cmdpal/exts/SamplePagesExtension/Pages/SampleCommentsPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleCommentsPage.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleContentPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleContentPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleContentPage.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleDynamicListPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleDynamicListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleDynamicListPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleDynamicListPage.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleListPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleListPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleListPage.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleListPageWithDetails.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleListPageWithDetails.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleListPageWithDetails.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleListPageWithDetails.cs diff --git a/src/modules/cmdpal/exts/SamplePagesExtension/Pages/SampleMarkdownDetails.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownDetails.cs similarity index 100% rename from src/modules/cmdpal/exts/SamplePagesExtension/Pages/SampleMarkdownDetails.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownDetails.cs diff --git a/src/modules/cmdpal/exts/SamplePagesExtension/Pages/SampleMarkdownManyBodies.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownManyBodies.cs similarity index 100% rename from src/modules/cmdpal/exts/SamplePagesExtension/Pages/SampleMarkdownManyBodies.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownManyBodies.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleMarkdownPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleMarkdownPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleMarkdownPage.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleSettingsPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleSettingsPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Pages/SampleSettingsPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleSettingsPage.cs diff --git a/src/modules/cmdpal/exts/SamplePagesExtension/Pages/SendMessageCommand.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SendMessageCommand.cs similarity index 100% rename from src/modules/cmdpal/exts/SamplePagesExtension/Pages/SendMessageCommand.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Pages/SendMessageCommand.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Program.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Program.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Program.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/Program.cs diff --git a/src/modules/cmdpal/exts/SamplePagesExtension/Properties/PublishProfiles/win-arm64.pubxml b/src/modules/cmdpal/ext/SamplePagesExtension/Properties/PublishProfiles/win-arm64.pubxml similarity index 100% rename from src/modules/cmdpal/exts/SamplePagesExtension/Properties/PublishProfiles/win-arm64.pubxml rename to src/modules/cmdpal/ext/SamplePagesExtension/Properties/PublishProfiles/win-arm64.pubxml diff --git a/src/modules/cmdpal/exts/SamplePagesExtension/Properties/PublishProfiles/win-x64.pubxml b/src/modules/cmdpal/ext/SamplePagesExtension/Properties/PublishProfiles/win-x64.pubxml similarity index 100% rename from src/modules/cmdpal/exts/SamplePagesExtension/Properties/PublishProfiles/win-x64.pubxml rename to src/modules/cmdpal/ext/SamplePagesExtension/Properties/PublishProfiles/win-x64.pubxml diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/Properties/launchSettings.json b/src/modules/cmdpal/ext/SamplePagesExtension/Properties/launchSettings.json similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/Properties/launchSettings.json rename to src/modules/cmdpal/ext/SamplePagesExtension/Properties/launchSettings.json diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/SampleExtension.cs b/src/modules/cmdpal/ext/SamplePagesExtension/SampleExtension.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/SampleExtension.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/SampleExtension.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/SamplePagesCommandsProvider.cs b/src/modules/cmdpal/ext/SamplePagesExtension/SamplePagesCommandsProvider.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/SamplePagesCommandsProvider.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/SamplePagesCommandsProvider.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/SamplePagesExtension.csproj b/src/modules/cmdpal/ext/SamplePagesExtension/SamplePagesExtension.csproj similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/SamplePagesExtension.csproj rename to src/modules/cmdpal/ext/SamplePagesExtension/SamplePagesExtension.csproj diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/SampleUpdatingItemsPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/SampleUpdatingItemsPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/SampleUpdatingItemsPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/SampleUpdatingItemsPage.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/SamplesListPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/SamplesListPage.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/SamplesListPage.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/SamplesListPage.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/SelfImmolateCommand.cs b/src/modules/cmdpal/ext/SamplePagesExtension/SelfImmolateCommand.cs similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/SelfImmolateCommand.cs rename to src/modules/cmdpal/ext/SamplePagesExtension/SelfImmolateCommand.cs diff --git a/src/modules/cmdpal/Exts/SamplePagesExtension/app.manifest b/src/modules/cmdpal/ext/SamplePagesExtension/app.manifest similarity index 100% rename from src/modules/cmdpal/Exts/SamplePagesExtension/app.manifest rename to src/modules/cmdpal/ext/SamplePagesExtension/app.manifest From d3c4e808d039aed4217d534ebd233211630d2374 Mon Sep 17 00:00:00 2001 From: Clint Rutkas Date: Tue, 15 Apr 2025 18:57:58 +0000 Subject: [PATCH 20/70] Upgrading Boost dependencies (#38782) Upgrading Boost --- .../powerrename/PowerRenameUILib/PowerRenameUI.vcxproj | 8 ++++---- src/modules/powerrename/PowerRenameUILib/packages.config | 4 ++-- src/modules/powerrename/dll/PowerRenameExt.vcxproj | 8 ++++---- src/modules/powerrename/dll/packages.config | 4 ++-- src/modules/powerrename/lib/PowerRenameLib.vcxproj | 8 ++++---- src/modules/powerrename/lib/packages.config | 4 ++-- src/modules/powerrename/testapp/PowerRenameTest.vcxproj | 8 ++++---- src/modules/powerrename/testapp/packages.config | 4 ++-- .../powerrename/unittests/PowerRenameLibUnitTests.vcxproj | 8 ++++---- src/modules/powerrename/unittests/packages.config | 4 ++-- 10 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj b/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj index 1421778986..40bbb7a682 100644 --- a/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj +++ b/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj @@ -204,12 +204,12 @@ - - + + @@ -217,14 +217,14 @@ - - + + diff --git a/src/modules/powerrename/PowerRenameUILib/packages.config b/src/modules/powerrename/PowerRenameUILib/packages.config index 893bd804ad..c8aa0dc6df 100644 --- a/src/modules/powerrename/PowerRenameUILib/packages.config +++ b/src/modules/powerrename/PowerRenameUILib/packages.config @@ -1,7 +1,7 @@  - - + + diff --git a/src/modules/powerrename/dll/PowerRenameExt.vcxproj b/src/modules/powerrename/dll/PowerRenameExt.vcxproj index ead9518f35..32484c75b6 100644 --- a/src/modules/powerrename/dll/PowerRenameExt.vcxproj +++ b/src/modules/powerrename/dll/PowerRenameExt.vcxproj @@ -77,8 +77,8 @@ - - + + @@ -86,7 +86,7 @@ - - + + \ No newline at end of file diff --git a/src/modules/powerrename/dll/packages.config b/src/modules/powerrename/dll/packages.config index ecc3202cd3..dbb70a80f2 100644 --- a/src/modules/powerrename/dll/packages.config +++ b/src/modules/powerrename/dll/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/src/modules/powerrename/lib/PowerRenameLib.vcxproj b/src/modules/powerrename/lib/PowerRenameLib.vcxproj index d55c7b4b77..103eab8e8e 100644 --- a/src/modules/powerrename/lib/PowerRenameLib.vcxproj +++ b/src/modules/powerrename/lib/PowerRenameLib.vcxproj @@ -79,8 +79,8 @@ - - + + @@ -88,7 +88,7 @@ - - + + \ No newline at end of file diff --git a/src/modules/powerrename/lib/packages.config b/src/modules/powerrename/lib/packages.config index ecc3202cd3..dbb70a80f2 100644 --- a/src/modules/powerrename/lib/packages.config +++ b/src/modules/powerrename/lib/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/src/modules/powerrename/testapp/PowerRenameTest.vcxproj b/src/modules/powerrename/testapp/PowerRenameTest.vcxproj index 616f8e70a4..ce2795710a 100644 --- a/src/modules/powerrename/testapp/PowerRenameTest.vcxproj +++ b/src/modules/powerrename/testapp/PowerRenameTest.vcxproj @@ -67,8 +67,8 @@ - - + + @@ -76,7 +76,7 @@ - - + + \ No newline at end of file diff --git a/src/modules/powerrename/testapp/packages.config b/src/modules/powerrename/testapp/packages.config index ecc3202cd3..dbb70a80f2 100644 --- a/src/modules/powerrename/testapp/packages.config +++ b/src/modules/powerrename/testapp/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj b/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj index 56976c1877..4c1b5d26af 100644 --- a/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj +++ b/src/modules/powerrename/unittests/PowerRenameLibUnitTests.vcxproj @@ -77,8 +77,8 @@ - - + + @@ -86,7 +86,7 @@ - - + + \ No newline at end of file diff --git a/src/modules/powerrename/unittests/packages.config b/src/modules/powerrename/unittests/packages.config index ecc3202cd3..dbb70a80f2 100644 --- a/src/modules/powerrename/unittests/packages.config +++ b/src/modules/powerrename/unittests/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file From f15bed5323f6b0f022a960c188444c2dbc606fb9 Mon Sep 17 00:00:00 2001 From: Clint Rutkas Date: Tue, 15 Apr 2025 18:58:33 +0000 Subject: [PATCH 21/70] upgrading toolkit + suppressing warnings (#38746) * upgrade toolkit to latest * supressing warnings * Update expect.txt making generic * Update suppression comments for AOT compatibility * Fix case for 'MVVMTK' in spell-check file * Update NOTICE.md --- Directory.Packages.props | 16 ++++++++-------- NOTICE.md | 16 ++++++++-------- src/codeAnalysis/GlobalSuppressions.cs | 12 ++++++++++-- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 8df1437546..4393655dab 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,14 +10,14 @@ - - - - - - - - + + + + + + + + diff --git a/NOTICE.md b/NOTICE.md index b8bd5ae8e5..83a24ef185 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1400,14 +1400,14 @@ SOFTWARE. - Azure.AI.OpenAI 1.0.0-beta.17 - CommunityToolkit.Common 8.4.0 - CommunityToolkit.Mvvm 8.4.0 -- CommunityToolkit.WinUI.Animations 8.2.250129-preview2 -- CommunityToolkit.WinUI.Collections 8.2.250129-preview2 -- CommunityToolkit.WinUI.Controls.Primitives 8.2.250129-preview2 -- CommunityToolkit.WinUI.Controls.Segmented 8.2.250129-preview2 -- CommunityToolkit.WinUI.Controls.SettingsControls 8.2.250129-preview2 -- CommunityToolkit.WinUI.Controls.Sizers 8.2.250129-preview2 -- CommunityToolkit.WinUI.Converters 8.2.250129-preview2 -- CommunityToolkit.WinUI.Extensions 8.2.250129-preview2 +- CommunityToolkit.WinUI.Animations 8.2.250402 +- CommunityToolkit.WinUI.Collections 8.2.250402 +- CommunityToolkit.WinUI.Controls.Primitives 8.2.250402 +- CommunityToolkit.WinUI.Controls.Segmented 8.2.250402 +- CommunityToolkit.WinUI.Controls.SettingsControls 8.2.250402 +- CommunityToolkit.WinUI.Controls.Sizers 8.2.250402 +- CommunityToolkit.WinUI.Converters 8.2.250402 +- CommunityToolkit.WinUI.Extensions 8.2.250402 - CommunityToolkit.WinUI.UI.Controls.DataGrid 7.1.2 - CommunityToolkit.WinUI.UI.Controls.Markdown 7.1.2 - ControlzEx 6.0.0 diff --git a/src/codeAnalysis/GlobalSuppressions.cs b/src/codeAnalysis/GlobalSuppressions.cs index c05e5f8820..d5ff98e548 100644 --- a/src/codeAnalysis/GlobalSuppressions.cs +++ b/src/codeAnalysis/GlobalSuppressions.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation +// 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. @@ -63,8 +63,16 @@ using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "", Scope = "namespaceanddescendants", Target = "MouseWithoutBorders")] [assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "", Scope = "namespaceanddescendants", Target = "MouseWithoutBorders")] -// AOT +// AOT MVVMTK0045 +[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "AdvancedPaste.ViewModels")] [assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "HostsUILib")] +[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "EnvironmentVariablesUILib")] +[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.FilePreviewer")] [assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.UI")] [assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.UI.Views")] +[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0045:Using [ObservableProperty] on fields is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib")] + +// AOT MVVMTK0049 +[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.FilePreviewer")] [assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.INotifyPropertyChangedGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "type", Target = "~T:Peek.UI.Views.TitleBar")] +[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib")] From 0e98cbd57e5d03221ff8dabecaca78d6db40c87b Mon Sep 17 00:00:00 2001 From: Carlos Zamora Date: Tue, 15 Apr 2025 19:14:23 -0700 Subject: [PATCH 22/70] [CNF] Only enable experimental features if they exist (#37690) --- .../Assets/Settings/Scripts/EnableModule.ps1 | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/EnableModule.ps1 b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/EnableModule.ps1 index a2943e4d4e..af6632f98e 100644 --- a/src/settings-ui/Settings.UI/Assets/Settings/Scripts/EnableModule.ps1 +++ b/src/settings-ui/Settings.UI/Assets/Settings/Scripts/EnableModule.ps1 @@ -4,10 +4,17 @@ Param( [string]$scriptPath ) -Write-Host "Enabling experimental feature: PSFeedbackProvider" -Enable-ExperimentalFeature PSFeedbackProvider -Write-Host "Enabling experimental feature: PSCommandNotFoundSuggestion" -Enable-ExperimentalFeature PSCommandNotFoundSuggestion +$experimentalFeatures = Get-ExperimentalFeature; +if ($experimentalFeatures.Name -contains "PSFeedbackProvider") +{ + Write-Host "Enabling experimental feature: PSFeedbackProvider" + Enable-ExperimentalFeature PSFeedbackProvider +} +if ($experimentalFeatures.Name -contains "PSCommandNotFoundSuggestion") +{ + Write-Host "Enabling experimental feature: PSCommandNotFoundSuggestion" + Enable-ExperimentalFeature PSCommandNotFoundSuggestion +} $wingetModules = Get-Module -ListAvailable -Name Microsoft.WinGet.Client if ($wingetModules) { From 4e0db267dc233ad83273d384b5d3dda045231c15 Mon Sep 17 00:00:00 2001 From: Abhyudit <64366765+bitmap4@users.noreply.github.com> Date: Wed, 16 Apr 2025 07:45:03 +0530 Subject: [PATCH 23/70] [PowerRename] Add 12-hour time format patterns with AM/PM support (#30703) (#38723) * [PowerRename][Feature] Add new date/time formatting patterns to GetDatedFileName * [PowerRename][UI] Add date/time shortcut patterns to cheat sheet * [PowerRename][Tests] Add tests for new date/time formatting patterns * [PowerRename] [Refactor] Simplify AM/PM string handling in time patterns --- .../PowerRenameXAML/MainWindow.xaml.cpp | 11 ++++- .../Strings/en-us/Resources.resw | 20 ++++++-- src/modules/powerrename/lib/Helpers.cpp | 32 ++++++++++++- .../unittests/PowerRenameRegExBoostTests.cpp | 48 +++++++++++++++++++ .../unittests/PowerRenameRegExTests.cpp | 48 +++++++++++++++++++ 5 files changed, 152 insertions(+), 7 deletions(-) diff --git a/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/MainWindow.xaml.cpp b/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/MainWindow.xaml.cpp index 9d5d8497d3..1a6269a8bf 100644 --- a/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/MainWindow.xaml.cpp +++ b/src/modules/powerrename/PowerRenameUILib/PowerRenameXAML/MainWindow.xaml.cpp @@ -195,8 +195,15 @@ namespace winrt::PowerRenameUI::implementation m_dateTimeShortcuts.Append(winrt::make(L"$DDD", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_DayNameAbbr").ValueAsString())); m_dateTimeShortcuts.Append(winrt::make(L"$DD", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_DayDigitLZero").ValueAsString())); m_dateTimeShortcuts.Append(winrt::make(L"$D", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_DayDigit").ValueAsString())); - m_dateTimeShortcuts.Append(winrt::make(L"$hh", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_HoursLZero").ValueAsString())); - m_dateTimeShortcuts.Append(winrt::make(L"$h", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_Hours").ValueAsString())); + + m_dateTimeShortcuts.Append(winrt::make(L"$HH", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_Hours12LZero").ValueAsString())); + m_dateTimeShortcuts.Append(winrt::make(L"$H", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_Hours12").ValueAsString())); + m_dateTimeShortcuts.Append(winrt::make(L"$TT", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_AMPMUpperCase").ValueAsString())); + m_dateTimeShortcuts.Append(winrt::make(L"$tt", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_AMPMLowerCase").ValueAsString())); + + m_dateTimeShortcuts.Append(winrt::make(L"$hh", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_Hours24LZero").ValueAsString())); + m_dateTimeShortcuts.Append(winrt::make(L"$h", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_Hours24").ValueAsString())); + m_dateTimeShortcuts.Append(winrt::make(L"$mm", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_MinutesLZero").ValueAsString())); m_dateTimeShortcuts.Append(winrt::make(L"$m", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_Minutes").ValueAsString())); m_dateTimeShortcuts.Append(winrt::make(L"$ss", manager.MainResourceMap().GetValue(L"Resources/DateTimeCheatSheet_SecondsLZero").ValueAsString())); diff --git a/src/modules/powerrename/PowerRenameUILib/Strings/en-us/Resources.resw b/src/modules/powerrename/PowerRenameUILib/Strings/en-us/Resources.resw index c1d55917f7..d528961148 100644 --- a/src/modules/powerrename/PowerRenameUILib/Strings/en-us/Resources.resw +++ b/src/modules/powerrename/PowerRenameUILib/Strings/en-us/Resources.resw @@ -219,11 +219,23 @@ Day of the month as digits without leading zeros for single-digit days. - - Hours with leading zeros for single-digit hours. + + Hours in 12-hour format (01-12) with leading zero. - - Hours without leading zeros for single-digit hours. + + Hours in 12-hour format (1-12) without leading zero. + + + AM/PM indicator in uppercase (AM or PM). + + + AM/PM indicator in lowercase (am or pm). + + + Hours in 24-hour format (00-23) with leading zero. + + + Hours in 24-hour format (0-23) without leading zero. Minutes with leading zeros for single-digit minutes. diff --git a/src/modules/powerrename/lib/Helpers.cpp b/src/modules/powerrename/lib/Helpers.cpp index aeadd8b683..2b6527593e 100644 --- a/src/modules/powerrename/lib/Helpers.cpp +++ b/src/modules/powerrename/lib/Helpers.cpp @@ -248,7 +248,19 @@ HRESULT GetTransformedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR sour bool isFileTimeUsed(_In_ PCWSTR source) { bool used = false; - static const std::array patterns = { std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$Y" }, std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$M" }, std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$D" }, std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$h" }, std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$m" }, std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$s" }, std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$f" } }; + static const std::array patterns = { + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$Y" }, + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$M" }, + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$D" }, + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$h" }, + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$m" }, + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$s" }, + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$f" }, + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$H" }, + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$T" }, + std::wregex{ L"(([^\\$]|^)(\\$\\$)*)\\$t" } + }; + for (size_t i = 0; !used && i < patterns.size(); i++) { if (std::regex_search(source, patterns[i])) @@ -275,6 +287,12 @@ HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SY StringCchCopy(localeName, LOCALE_NAME_MAX_LENGTH, L"en_US"); } + int hour12 = (fileTime.wHour % 12); + if (hour12 == 0) + { + hour12 = 12; + } + StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%04d"), L"$01", fileTime.wYear); res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$YYYY"), replaceTerm); @@ -316,6 +334,18 @@ HRESULT GetDatedFileName(_Out_ PWSTR result, UINT cchMax, _In_ PCWSTR source, SY StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", fileTime.wDay); res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$D"), replaceTerm); + StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", hour12); + res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$HH"), replaceTerm); + + StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%d"), L"$01", hour12); + res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$H"), replaceTerm); + + StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", (fileTime.wHour < 12) ? L"AM" : L"PM"); + res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$TT"), replaceTerm); + + StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%s"), L"$01", (fileTime.wHour < 12) ? L"am" : L"pm"); + res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$tt"), replaceTerm); + StringCchPrintf(replaceTerm, MAX_PATH, TEXT("%s%02d"), L"$01", fileTime.wHour); res = regex_replace(res, std::wregex(L"(([^\\$]|^)(\\$\\$)*)\\$hh"), replaceTerm); diff --git a/src/modules/powerrename/unittests/PowerRenameRegExBoostTests.cpp b/src/modules/powerrename/unittests/PowerRenameRegExBoostTests.cpp index 2bff1a4b9c..491852ff88 100644 --- a/src/modules/powerrename/unittests/PowerRenameRegExBoostTests.cpp +++ b/src/modules/powerrename/unittests/PowerRenameRegExBoostTests.cpp @@ -127,5 +127,53 @@ TEST_METHOD(VerifyLookbehind) CoTaskMemFree(result); } } + +TEST_METHOD (Verify12and24HourTimeFormats) +{ + CComPtr renameRegEx; + Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK); + DWORD flags = MatchAllOccurrences | UseRegularExpressions; + Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK); + + struct TimeTestCase { + SYSTEMTIME time; // Input time + PCWSTR formatString; // Format pattern + PCWSTR expectedResult; // Expected output + PCWSTR description; // Description of what we're testing + }; + + struct TimeTestCase testCases[] = { + // Midnight (00:00 / 12:00 AM) + { { 2025, 4, 4, 10, 0, 0, 0, 0 }, L"[$hh:$mm] [$H:$mm $tt]", L"[00:00] [12:00 am]", L"Midnight formatting" }, + + // Noon (12:00 / 12:00 PM) + { { 2025, 4, 4, 10, 12, 0, 0, 0 }, L"[$hh:$mm] [$H:$mm $tt]", L"[12:00] [12:00 pm]", L"Noon formatting" }, + + // 1:05 AM + { { 2025, 4, 4, 10, 1, 5, 0, 0 }, L"[$h:$m] [$H:$m $tt] [$hh:$mm] [$HH:$mm $TT]", + L"[1:5] [1:5 am] [01:05] [01:05 AM]", L"1 AM with various formats" }, + + // 11 PM + { { 2025, 4, 4, 10, 23, 45, 0, 0 }, L"[$h:$m] [$H:$m $tt] [$hh:$mm] [$HH:$mm $TT]", + L"[23:45] [11:45 pm] [23:45] [11:45 PM]", L"11 PM with various formats" }, + + // Mixed formats in complex pattern + { { 2025, 4, 4, 10, 14, 30, 0, 0 }, L"Date: $YYYY-$MM-$DD Time: $hh:$mm (24h) / $H:$mm $tt (12h)", + L"Date: 2025-04-10 Time: 14:30 (24h) / 2:30 pm (12h)", L"Complex combined format" }, + }; + + for (int i = 0; i < ARRAYSIZE(testCases); i++) + { + PWSTR result = nullptr; + Assert::IsTrue(renameRegEx->PutSearchTerm(L"test") == S_OK); + Assert::IsTrue(renameRegEx->PutReplaceTerm(testCases[i].formatString) == S_OK); + Assert::IsTrue(renameRegEx->PutFileTime(testCases[i].time) == S_OK); + unsigned long index = {}; + Assert::IsTrue(renameRegEx->Replace(L"test", &result, index) == S_OK); + Assert::IsTrue(wcscmp(result, testCases[i].expectedResult) == 0, + (std::wstring(L"Failed test case: ") + testCases[i].description).c_str()); + CoTaskMemFree(result); + } +} }; } diff --git a/src/modules/powerrename/unittests/PowerRenameRegExTests.cpp b/src/modules/powerrename/unittests/PowerRenameRegExTests.cpp index 5270f193e2..18a679995a 100644 --- a/src/modules/powerrename/unittests/PowerRenameRegExTests.cpp +++ b/src/modules/powerrename/unittests/PowerRenameRegExTests.cpp @@ -207,5 +207,53 @@ TEST_METHOD(VerifyLookbehindFails) } } +TEST_METHOD (Verify12and24HourTimeFormats) +{ + CComPtr renameRegEx; + Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK); + DWORD flags = MatchAllOccurrences | UseRegularExpressions; + Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK); + + struct TimeTestCase { + SYSTEMTIME time; // Input time + PCWSTR formatString; // Format pattern + PCWSTR expectedResult; // Expected output + PCWSTR description; // Description of what we're testing + }; + + struct TimeTestCase testCases[] = { + // Midnight (00:00 / 12:00 AM) + { { 2025, 4, 4, 10, 0, 0, 0, 0 }, L"[$hh:$mm] [$H:$mm $tt]", L"[00:00] [12:00 am]", L"Midnight formatting" }, + + // Noon (12:00 / 12:00 PM) + { { 2025, 4, 4, 10, 12, 0, 0, 0 }, L"[$hh:$mm] [$H:$mm $tt]", L"[12:00] [12:00 pm]", L"Noon formatting" }, + + // 1:05 AM + { { 2025, 4, 4, 10, 1, 5, 0, 0 }, L"[$h:$m] [$H:$m $tt] [$hh:$mm] [$HH:$mm $TT]", + L"[1:5] [1:5 am] [01:05] [01:05 AM]", L"1 AM with various formats" }, + + // 11 PM + { { 2025, 4, 4, 10, 23, 45, 0, 0 }, L"[$h:$m] [$H:$m $tt] [$hh:$mm] [$HH:$mm $TT]", + L"[23:45] [11:45 pm] [23:45] [11:45 PM]", L"11 PM with various formats" }, + + // Mixed formats in complex pattern + { { 2025, 4, 4, 10, 14, 30, 0, 0 }, L"Date: $YYYY-$MM-$DD Time: $hh:$mm (24h) / $H:$mm $tt (12h)", + L"Date: 2025-04-10 Time: 14:30 (24h) / 2:30 pm (12h)", L"Complex combined format" }, + }; + + for (int i = 0; i < ARRAYSIZE(testCases); i++) + { + PWSTR result = nullptr; + Assert::IsTrue(renameRegEx->PutSearchTerm(L"test") == S_OK); + Assert::IsTrue(renameRegEx->PutReplaceTerm(testCases[i].formatString) == S_OK); + Assert::IsTrue(renameRegEx->PutFileTime(testCases[i].time) == S_OK); + unsigned long index = {}; + Assert::IsTrue(renameRegEx->Replace(L"test", &result, index) == S_OK); + Assert::IsTrue(wcscmp(result, testCases[i].expectedResult) == 0, + (std::wstring(L"Failed test case: ") + testCases[i].description).c_str()); + CoTaskMemFree(result); + } +} + }; } From a16f784011df079b3b4fa0e89b3cdf5b8b9317ce Mon Sep 17 00:00:00 2001 From: Yu Leng <42196638+moooyo@users.noreply.github.com> Date: Wed, 16 Apr 2025 10:17:43 +0800 Subject: [PATCH 24/70] [cmdpal] Fix empty file name issue when create new ext in "Create New Extension" command. (#38864) Co-authored-by: Yu Leng (from Dev Box) --- .../Commands/NewExtensionForm.cs | 37 +++++++++++-------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs index 326b7ac2b3..698faf0335 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.IO.Compression; +using System.Text.Json; using System.Text.Json.Nodes; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; @@ -28,69 +29,69 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase "body": [ { "type": "TextBlock", - "text": "{{Properties.Resources.builtin_create_extension_page_title}}", + "text": {{FormatJsonString(Properties.Resources.builtin_create_extension_page_title)}}, "size": "large" }, { "type": "TextBlock", - "text": "{{Properties.Resources.builtin_create_extension_page_text}}", + "text": {{FormatJsonString(Properties.Resources.builtin_create_extension_page_text)}}, "wrap": true }, { "type": "TextBlock", - "text": "{{Properties.Resources.builtin_create_extension_name_header}}", + "text": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_header)}}, "weight": "bolder", "size": "default" }, { "type": "TextBlock", - "text": "{{Properties.Resources.builtin_create_extension_name_description}}", + "text": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_description)}}, "wrap": true }, { "type": "Input.Text", - "label": "{{Properties.Resources.builtin_create_extension_name_label}}", + "label": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_label)}}, "isRequired": true, - "errorMessage": "{{Properties.Resources.builtin_create_extension_name_required}}", + "errorMessage": {{FormatJsonString(Properties.Resources.builtin_create_extension_name_required)}}, "id": "ExtensionName", "placeholder": "ExtensionName", "regex": "^[^\\s]+$" }, { "type": "TextBlock", - "text": "{{Properties.Resources.builtin_create_extension_display_name_header}}", + "text": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_header)}}, "weight": "bolder", "size": "default" }, { "type": "TextBlock", - "text": "{{Properties.Resources.builtin_create_extension_display_name_description}}", + "text": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_description)}}, "wrap": true }, { "type": "Input.Text", - "label": "{{Properties.Resources.builtin_create_extension_display_name_label}}", + "label": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_label)}}, "isRequired": true, - "errorMessage": "{{Properties.Resources.builtin_create_extension_display_name_required}}", + "errorMessage": {{FormatJsonString(Properties.Resources.builtin_create_extension_display_name_required)}}, "id": "DisplayName", "placeholder": "My new extension" }, { "type": "TextBlock", - "text": "{{Properties.Resources.builtin_create_extension_directory_header}}", + "text": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_header)}}, "weight": "bolder", "size": "default" }, { "type": "TextBlock", - "text": "{{Properties.Resources.builtin_create_extension_directory_description}}", + "text": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_description)}}, "wrap": true }, { "type": "Input.Text", - "label": "{{Properties.Resources.builtin_create_extension_directory_label}}", + "label": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_label)}}, "isRequired": true, - "errorMessage": "{{Properties.Resources.builtin_create_extension_directory_required}}", + "errorMessage": {{FormatJsonString(Properties.Resources.builtin_create_extension_directory_required)}}, "id": "OutputPath", "placeholder": "C:\\users\\me\\dev" } @@ -98,7 +99,7 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase "actions": [ { "type": "Action.Submit", - "title": "{{Properties.Resources.builtin_create_extension_submit}}", + "title": {{FormatJsonString(Properties.Resources.builtin_create_extension_submit)}}, "associatedInputs": "auto" } ] @@ -192,4 +193,10 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase // Delete the temp dir Directory.Delete(tempDir, true); } + + private string FormatJsonString(string str) + { + // Escape the string for JSON + return JsonSerializer.Serialize(str); + } } From e700f86acecb5da0821fc1950bd31869c89e76d3 Mon Sep 17 00:00:00 2001 From: Davide Giacometti <25966642+davidegiacometti@users.noreply.github.com> Date: Wed, 16 Apr 2025 05:08:43 +0200 Subject: [PATCH 25/70] [QuickAccent] Fix on-screen keyboard activation (#37581) * fix on-screen keyboard activation * cleanup --- .../KeyboardListener.cpp | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.cpp b/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.cpp index 6969d7dd58..93fb5c0230 100644 --- a/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.cpp +++ b/src/modules/poweraccent/PowerAccentKeyboardService/KeyboardListener.cpp @@ -169,6 +169,14 @@ namespace winrt::PowerToys::PowerAccentKeyboardService::implementation if (std::find(letters.begin(), letters.end(), letterKey) != cend(letters) && m_isLanguageLetterCb(letterKey)) { + if (m_toolbarVisible && letterPressed == letterKey) + { + // On-screen keyboard continuously sends WM_KEYDOWN when a key is held down + // If Quick Accent is visible, prevent the letter key from being processed + // https://github.com/microsoft/PowerToys/issues/36853 + return true; + } + m_stopwatch.reset(); letterPressed = letterKey; } @@ -282,12 +290,11 @@ namespace winrt::PowerToys::PowerAccentKeyboardService::implementation LRESULT KeyboardListener::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { + if (nCode == HC_ACTION && s_instance != nullptr) { - if (nCode == HC_ACTION && s_instance != nullptr) + KBDLLHOOKSTRUCT* key = reinterpret_cast(lParam); + switch (wParam) { - KBDLLHOOKSTRUCT* key = reinterpret_cast(lParam); - switch (wParam) - { case WM_KEYDOWN: { if (s_instance->OnKeyDown(*key)) @@ -304,10 +311,9 @@ namespace winrt::PowerToys::PowerAccentKeyboardService::implementation } } break; - } } - - return CallNextHookEx(NULL, nCode, wParam, lParam); } + + return CallNextHookEx(NULL, nCode, wParam, lParam); } } From c7789abf044ab85fbfc8379330382f215c8aa5cd Mon Sep 17 00:00:00 2001 From: Stefan Markovic <57057282+stefansjfw@users.noreply.github.com> Date: Wed, 16 Apr 2025 12:36:01 +0200 Subject: [PATCH 26/70] CmdPal: Add low-level keyboard hook for global hotkey (#38250) Adds the ability to make the global CmdPal hotkey a low-level hook. This is needed for `win+space`, `win+r`, et al. I've only added this to the root hotkey. Other hotkeys will still use the normal `RegisterHotkey` ones. We can re-evaluate this for 0.2+. Originally: https://github.com/zadjii-msft/PowerToys/issues/349 Solves: https://github.com/microsoft/PowerToys/issues/38297 --------- Co-authored-by: Mike Griese --- PowerToys.sln | 15 +- .../CmdPalKeyboardService.def | 3 + .../CmdPalKeyboardService.rc | 40 ++++ .../CmdPalKeyboardService.vcxproj | 187 ++++++++++++++++++ .../CmdPalKeyboardService.vcxproj.filters | 36 ++++ .../KeyboardListener.cpp | 165 ++++++++++++++++ .../CmdPalKeyboardService/KeyboardListener.h | 67 +++++++ .../KeyboardListener.idl | 16 ++ .../CmdPalKeyboardService/PropertySheet.props | 17 ++ .../CmdPalKeyboardService/packages.config | 4 + .../cmdpal/CmdPalKeyboardService/pch.cpp | 1 + .../cmdpal/CmdPalKeyboardService/pch.h | 4 + .../cmdpal/CmdPalKeyboardService/resource.h | 13 ++ .../SettingsModel.cs | 2 + .../SettingsViewModel.cs | 11 ++ .../Microsoft.CmdPal.UI/MainWindow.xaml.cs | 90 ++++++--- .../Microsoft.CmdPal.UI.csproj | 8 +- .../Settings/GeneralPage.xaml | 13 +- .../Strings/en-us/Resources.resw | 6 + 19 files changed, 667 insertions(+), 31 deletions(-) create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.def create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.rc create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj.filters create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.cpp create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.h create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.idl create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/PropertySheet.props create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/packages.config create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/pch.cpp create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/pch.h create mode 100644 src/modules/cmdpal/CmdPalKeyboardService/resource.h diff --git a/PowerToys.sln b/PowerToys.sln index 401ba6d598..9fca8d2a3a 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -706,6 +706,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RegistryPreview.FuzzTests", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System", "src\modules\cmdpal\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj", "{64B88F02-CD88-4ED8-9624-989A800230F9}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "src\modules\cmdpal\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj", "{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM64 = Debug|ARM64 @@ -2574,14 +2576,18 @@ Global {64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|ARM64.Build.0 = Debug|ARM64 {64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.ActiveCfg = Debug|x64 {64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x64.Build.0 = Debug|x64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x86.ActiveCfg = Debug|x64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Debug|x86.Build.0 = Debug|x64 {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.ActiveCfg = Release|ARM64 {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|ARM64.Build.0 = Release|ARM64 {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.ActiveCfg = Release|x64 {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x64.Build.0 = Release|x64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x86.ActiveCfg = Release|x64 - {64B88F02-CD88-4ED8-9624-989A800230F9}.Release|x86.Build.0 = Release|x64 + {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|ARM64.Build.0 = Debug|ARM64 + {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.ActiveCfg = Debug|x64 + {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Debug|x64.Build.0 = Debug|x64 + {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.ActiveCfg = Release|ARM64 + {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|ARM64.Build.0 = Release|ARM64 + {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.ActiveCfg = Release|x64 + {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2852,6 +2858,7 @@ Global {4E0AE3A4-2EE0-44D7-A2D0-8769977254A0} = {F05E590D-AD46-42BE-9C25-6A63ADD2E3EA} {5702B3CC-8575-48D5-83D8-15BB42269CD3} = {929C1324-22E8-4412-A9A8-80E85F3985A5} {64B88F02-CD88-4ED8-9624-989A800230F9} = {ECB8E0D1-7603-4E5C-AB10-D1E545E6F8E2} + {5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2} = {3846508C-77EB-4034-A702-F8BB263C4F79} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0} diff --git a/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.def b/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.def new file mode 100644 index 0000000000..24e7c1235c --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.rc b/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.rc new file mode 100644 index 0000000000..5fa3c8b90d --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.rc @@ -0,0 +1,40 @@ +#include +#include "resource.h" +#include "../../../common/version/version.h" + +#define APSTUDIO_READONLY_SYMBOLS +#include "winres.h" +#undef APSTUDIO_READONLY_SYMBOLS + +1 VERSIONINFO +FILEVERSION FILE_VERSION +PRODUCTVERSION PRODUCT_VERSION +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG +FILEFLAGS VS_FF_DEBUG +#else +FILEFLAGS 0x0L +#endif +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset + BEGIN + VALUE "CompanyName", COMPANY_NAME + VALUE "FileDescription", FILE_DESCRIPTION + VALUE "FileVersion", FILE_VERSION_STRING + VALUE "InternalName", INTERNAL_NAME + VALUE "LegalCopyright", COPYRIGHT_NOTE + VALUE "OriginalFilename", ORIGINAL_FILENAME + VALUE "ProductName", PRODUCT_NAME + VALUE "ProductVersion", PRODUCT_VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset + END +END diff --git a/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj b/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj new file mode 100644 index 0000000000..e110d736ae --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj @@ -0,0 +1,187 @@ + + + + + true + true + {5f63c743-f6ce-4dba-a200-2b3f8a14e8c2} + CmdPalKeyboardService + CmdPalKeyboardService + false + + + + + true + false + + + + + true + true + en-US + 17.0 + 10.0 + + + true + true + true + Windows Store + false + + + + <_VC_Target_Library_Platform>Desktop + <_NoWinAPIFamilyApp>true + + + + + + DynamicLibrary + v143 + Unicode + false + + + true + true + + + false + true + false + + + + + + + + + + + + + + + + + CmdPalKeyboardService + ..\..\..\..\$(Platform)\$(Configuration)\ + + + + $(IntDir)pch.pch + Level4 + %(AdditionalOptions) /bigobj + _WINRT_DLL;WINRT_LEAN_AND_MEAN;%(PreprocessorDefinitions) + ../../..;%(AdditionalIncludeDirectories) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + false + CmdPalKeyboardService.def + Shell32.lib;user32.lib;%(AdditionalDependencies) + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + true + true + + + + + + KeyboardListener.idl + + + + + + Create + + + KeyboardListener.idl + + + + + + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + + + + MultiThreadedDebug + + + + %(IgnoreSpecificDefaultLibraries);libucrtd.lib + %(AdditionalOptions) /defaultlib:ucrtd.lib + + + + + + MultiThreaded + + + + %(IgnoreSpecificDefaultLibraries);libucrt.lib + %(AdditionalOptions) /defaultlib:ucrt.lib + + + + + \ No newline at end of file diff --git a/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj.filters b/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj.filters new file mode 100644 index 0000000000..301ac57f3a --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/CmdPalKeyboardService.vcxproj.filters @@ -0,0 +1,36 @@ + + + + + accd3aa8-1ba0-4223-9bbe-0c431709210b + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + {926ab91d-31b4-48c3-b9a4-e681349f27f0} + + + + + + + + + + + + + + + + + + + + + + + Resources + + + \ No newline at end of file diff --git a/src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.cpp b/src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.cpp new file mode 100644 index 0000000000..cf52fe1863 --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.cpp @@ -0,0 +1,165 @@ +#include "pch.h" +#include "KeyboardListener.h" +#include "KeyboardListener.g.cpp" + +// #include +// #include +#include + +namespace +{ +} + +namespace winrt::CmdPalKeyboardService::implementation +{ + KeyboardListener::KeyboardListener() + { + s_instance = this; + } + + void KeyboardListener::Start() + { +#if defined(DISABLE_LOWLEVEL_HOOKS_WHEN_DEBUGGED) + const bool hook_disabled = IsDebuggerPresent(); +#else + const bool hook_disabled = false; +#endif + if (!hook_disabled) + { + if (!s_llKeyboardHook) + { + s_llKeyboardHook = SetWindowsHookExW(WH_KEYBOARD_LL, LowLevelKeyboardProc, NULL, NULL); + if (!s_llKeyboardHook) + { + DWORD errorCode = GetLastError(); + show_last_error_message(L"SetWindowsHookEx", errorCode, L"CmdPalKeyboardService"); + } + } + } + } + + void KeyboardListener::Stop() + { + if (s_llKeyboardHook && UnhookWindowsHookEx(s_llKeyboardHook)) + { + s_llKeyboardHook = NULL; + } + } + + void KeyboardListener::SetHotkeyAction(bool win, bool ctrl, bool shift, bool alt, uint8_t key, hstring const& id) + { + Hotkey hotkey = { .win = win, .ctrl = ctrl, .shift = shift, .alt = alt, .key = key }; + std::unique_lock lock{ mutex }; + + HotkeyDescriptor desc = { .hotkey = hotkey, .id = std::wstring(id) }; + hotkeyDescriptors.insert(desc); + } + + void KeyboardListener::ClearHotkey(hstring const& id) + { + { + std::unique_lock lock{ mutex }; + auto it = hotkeyDescriptors.begin(); + while (it != hotkeyDescriptors.end()) + { + if (it->id == id) + { + it = hotkeyDescriptors.erase(it); + } + else + { + ++it; + } + } + } + } + + void KeyboardListener::ClearHotkeys() + { + { + std::unique_lock lock{ mutex }; + auto it = hotkeyDescriptors.begin(); + while (it != hotkeyDescriptors.end()) + { + it = hotkeyDescriptors.erase(it); + } + } + } + + void KeyboardListener::SetProcessCommand(ProcessCommand processCommand) + { + m_processCommandCb = [trigger = std::move(processCommand)](hstring const& id) { + trigger(id); + }; + } + + LRESULT KeyboardListener::DoLowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) + { + const auto& keyPressInfo = *reinterpret_cast(lParam); + + if ((wParam != WM_KEYDOWN) && (wParam != WM_SYSKEYDOWN)) + { + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + Hotkey hotkey{ + .win = (GetAsyncKeyState(VK_LWIN) & 0x8000) || (GetAsyncKeyState(VK_RWIN) & 0x8000), + .ctrl = static_cast(GetAsyncKeyState(VK_CONTROL) & 0x8000), + .shift = static_cast(GetAsyncKeyState(VK_SHIFT) & 0x8000), + .alt = static_cast(GetAsyncKeyState(VK_MENU) & 0x8000), + .key = static_cast(keyPressInfo.vkCode) + }; + + if (hotkey == Hotkey{}) + { + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + bool do_action = false; + std::wstring actionId{}; + + { + // Hold the lock for the shortest possible duration + std::unique_lock lock{ mutex }; + HotkeyDescriptor dummy{ .hotkey = hotkey }; + auto it = hotkeyDescriptors.find(dummy); + if (it != hotkeyDescriptors.end()) + { + do_action = true; + actionId = it->id; + } + } + + if (do_action) + { + m_processCommandCb(hstring{ actionId }); + + // After invoking the hotkey send a dummy key to prevent Start Menu from activating + INPUT dummyEvent[1] = {}; + dummyEvent[0].type = INPUT_KEYBOARD; + dummyEvent[0].ki.wVk = 0xFF; + dummyEvent[0].ki.dwFlags = KEYEVENTF_KEYUP; + SendInput(1, dummyEvent, sizeof(INPUT)); + + // Swallow the key press + return 1; + } + + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + LRESULT KeyboardListener::LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) + { + if (s_instance == nullptr) + { + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + if (nCode < 0) + { + return CallNextHookEx(NULL, nCode, wParam, lParam); + } + + return s_instance->DoLowLevelKeyboardProc(nCode, wParam, lParam); + } +} diff --git a/src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.h b/src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.h new file mode 100644 index 0000000000..7cd82ba77c --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.h @@ -0,0 +1,67 @@ +#pragma once + +#include "KeyboardListener.g.h" +#include +#include +#include + +namespace winrt::CmdPalKeyboardService::implementation +{ + struct KeyboardListener : KeyboardListenerT + { + struct Hotkey + { + bool win = false; + bool ctrl = false; + bool shift = false; + bool alt = false; + unsigned char key = 0; + + std::strong_ordering operator<=>(const Hotkey&) const = default; + }; + + struct HotkeyDescriptor + { + Hotkey hotkey; + std::wstring id; + + bool operator<(const HotkeyDescriptor& other) const + { + return hotkey < other.hotkey; + }; + }; + + KeyboardListener(); + + void Start(); + void Stop(); + void SetHotkeyAction(bool win, bool ctrl, bool shift, bool alt, uint8_t key, hstring const& id); + void ClearHotkey(hstring const& id); + void ClearHotkeys(); + void SetProcessCommand(ProcessCommand processCommand); + + static LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); + + private: + LRESULT CALLBACK DoLowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); + + static inline KeyboardListener* s_instance; + HHOOK s_llKeyboardHook = nullptr; + + // Max DWORD for key code to disable keys. + const DWORD VK_DISABLED = 0x100; + DWORD vkCodePressed = VK_DISABLED; + + std::multiset hotkeyDescriptors; + std::mutex mutex; + + std::function m_processCommandCb; + }; +} + +namespace winrt::CmdPalKeyboardService::factory_implementation +{ + struct KeyboardListener : KeyboardListenerT + { + }; +} diff --git a/src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.idl b/src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.idl new file mode 100644 index 0000000000..8d808e386c --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/KeyboardListener.idl @@ -0,0 +1,16 @@ + +namespace CmdPalKeyboardService +{ + [version(1.0), uuid(78ab07cd-e128-4e73-86aa-e48e6b6d01ff)] delegate void ProcessCommand(String id); + + [default_interface] runtimeclass KeyboardListener { + KeyboardListener(); + void Start(); + void Stop(); + + void SetHotkeyAction(Boolean win, Boolean ctrl, Boolean shift, Boolean alt, UInt8 key, String id); + void ClearHotkey(String id); + void ClearHotkeys(); + void SetProcessCommand(ProcessCommand processCommand); + } +} diff --git a/src/modules/cmdpal/CmdPalKeyboardService/PropertySheet.props b/src/modules/cmdpal/CmdPalKeyboardService/PropertySheet.props new file mode 100644 index 0000000000..27ad40e537 --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/PropertySheet.props @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/src/modules/cmdpal/CmdPalKeyboardService/packages.config b/src/modules/cmdpal/CmdPalKeyboardService/packages.config new file mode 100644 index 0000000000..09bfc449e2 --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/modules/cmdpal/CmdPalKeyboardService/pch.cpp b/src/modules/cmdpal/CmdPalKeyboardService/pch.cpp new file mode 100644 index 0000000000..bcb5590be1 --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/src/modules/cmdpal/CmdPalKeyboardService/pch.h b/src/modules/cmdpal/CmdPalKeyboardService/pch.h new file mode 100644 index 0000000000..b10d0155ca --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/pch.h @@ -0,0 +1,4 @@ +#pragma once +#include +#include +#include diff --git a/src/modules/cmdpal/CmdPalKeyboardService/resource.h b/src/modules/cmdpal/CmdPalKeyboardService/resource.h new file mode 100644 index 0000000000..f99c3adb95 --- /dev/null +++ b/src/modules/cmdpal/CmdPalKeyboardService/resource.h @@ -0,0 +1,13 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by PowerToys.MeasureToolCore.rc + +////////////////////////////// +// Non-localizable + +#define FILE_DESCRIPTION "CmdPalKeyboardService" +#define INTERNAL_NAME "CmdPalKeyboardService" +#define ORIGINAL_FILENAME "CmdPalKeyboardService.dll" + +// Non-localizable +////////////////////////////// diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs index 86612e83aa..891c45ace9 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs @@ -26,6 +26,8 @@ public partial class SettingsModel : ObservableObject public HotkeySettings? Hotkey { get; set; } = DefaultActivationShortcut; + public bool UseLowLevelGlobalHotkey { get; set; } + public bool ShowAppDetails { get; set; } public bool HotkeyGoesHome { get; set; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs index c66c07c47b..b6c5214890 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsViewModel.cs @@ -27,6 +27,17 @@ public partial class SettingsViewModel : INotifyPropertyChanged } } + public bool UseLowLevelGlobalHotkey + { + get => _settings.UseLowLevelGlobalHotkey; + set + { + _settings.UseLowLevelGlobalHotkey = value; + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Hotkey))); + Save(); + } + } + public bool ShowAppDetails { get => _settings.ShowAppDetails; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index 2ec74b37f2..c99543f9e1 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Runtime.InteropServices; +using CmdPalKeyboardService; using CommunityToolkit.Mvvm.Messaging; using Microsoft.CmdPal.Common.Helpers; using Microsoft.CmdPal.Common.Messages; @@ -52,6 +53,8 @@ public sealed partial class MainWindow : Window, #pragma warning restore SA1306 // Field names should begin with lower-case letter #pragma warning restore SA1310 // Field names should not contain underscore + private readonly KeyboardListener _keyboardListener; + // Notification Area ("Tray") icon data private NOTIFYICONDATAW? _trayIconData; private DestroyIconSafeHandle? _largeIcon; @@ -66,6 +69,11 @@ public sealed partial class MainWindow : Window, _hwnd = new HWND(WinRT.Interop.WindowNative.GetWindowHandle(this).ToInt32()); CommandPaletteHost.SetHostHwnd((ulong)_hwnd.Value); + _keyboardListener = new KeyboardListener(); + _keyboardListener.Start(); + + _keyboardListener.SetProcessCommand(new CmdPalKeyboardService.ProcessCommand(HandleSummon)); + // TaskbarCreated is the message that's broadcast when explorer.exe // restarts. We need to know when that happens to be able to bring our // notification area icon back @@ -304,6 +312,8 @@ public sealed partial class MainWindow : Window, // Workaround by turning it off before shutdown. App.Current.DebugSettings.FailFastOnErrors = false; DisposeAcrylic(); + + _keyboardListener.Stop(); } private void DisposeAcrylic() @@ -398,6 +408,8 @@ public sealed partial class MainWindow : Window, private void UnregisterHotkeys() { + _keyboardListener.ClearHotkeys(); + while (_hotkeys.Count > 0) { PInvoke.UnregisterHotKey(_hwnd, _hotkeys.Count - 1); @@ -412,19 +424,28 @@ public sealed partial class MainWindow : Window, var globalHotkey = settings.Hotkey; if (globalHotkey != null) { - var vk = globalHotkey.Code; - var modifiers = - (globalHotkey.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) | - (globalHotkey.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) | - (globalHotkey.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) | - (globalHotkey.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0) - ; - - var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk); - if (success) + if (settings.UseLowLevelGlobalHotkey) { + _keyboardListener.SetHotkeyAction(globalHotkey.Win, globalHotkey.Ctrl, globalHotkey.Shift, globalHotkey.Alt, (byte)globalHotkey.Code, string.Empty); + _hotkeys.Add(new(globalHotkey, string.Empty)); } + else + { + var vk = globalHotkey.Code; + var modifiers = + (globalHotkey.Alt ? HOT_KEY_MODIFIERS.MOD_ALT : 0) | + (globalHotkey.Ctrl ? HOT_KEY_MODIFIERS.MOD_CONTROL : 0) | + (globalHotkey.Shift ? HOT_KEY_MODIFIERS.MOD_SHIFT : 0) | + (globalHotkey.Win ? HOT_KEY_MODIFIERS.MOD_WIN : 0) + ; + + var success = PInvoke.RegisterHotKey(_hwnd, _hotkeys.Count, modifiers, (uint)vk); + if (success) + { + _hotkeys.Add(new(globalHotkey, string.Empty)); + } + } } foreach (var commandHotkey in settings.CommandHotkeys) @@ -450,6 +471,26 @@ public sealed partial class MainWindow : Window, } } + private void HandleSummon(string commandId) + { + var isRootHotkey = string.IsNullOrEmpty(commandId); + PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey)); + + // Note to future us: the wParam will have the index of the hotkey we registered. + // We can use that in the future to differentiate the hotkeys we've pressed + // so that we can bind hotkeys to individual commands + if (!this.Visible || !isRootHotkey) + { + Activate(); + + Summon(commandId); + } + else if (isRootHotkey) + { + PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE); + } + } + private LRESULT HotKeyPrc( HWND hwnd, uint uMsg, @@ -464,22 +505,23 @@ public sealed partial class MainWindow : Window, if (hotkeyIndex < _hotkeys.Count) { var hotkey = _hotkeys[hotkeyIndex]; - var isRootHotkey = string.IsNullOrEmpty(hotkey.CommandId); - PowerToysTelemetry.Log.WriteEvent(new CmdPalHotkeySummoned(isRootHotkey)); + HandleSummon(hotkey.CommandId); - // Note to future us: the wParam will have the index of the hotkey we registered. - // We can use that in the future to differentiate the hotkeys we've pressed - // so that we can bind hotkeys to individual commands - if (!this.Visible || !isRootHotkey) - { - Activate(); + // var isRootHotkey = string.IsNullOrEmpty(hotkey.CommandId); - Summon(hotkey.CommandId); - } - else if (isRootHotkey) - { - PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_HIDE); - } + // // Note to future us: the wParam will have the index of the hotkey we registered. + // // We can use that in the future to differentiate the hotkeys we've pressed + // // so that we can bind hotkeys to individual commands + // if (!this.Visible || !isRootHotkey) + // { + // Activate(); + + // Summon(hotkey.CommandId); + // } + // else if (isRootHotkey) + // { + // PInvoke.ShowWindow(hwnd, SHOW_WINDOW_CMD.SW_HIDE); + // } } return (LRESULT)IntPtr.Zero; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj b/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj index 80fbc58a5e..670382ecd8 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj @@ -29,7 +29,7 @@ - Microsoft.Terminal.UI + Microsoft.Terminal.UI;CmdPalKeyboardService $(OutDir) @@ -123,6 +123,12 @@ True True + + + True + True + True + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml index 8494bed1e1..68763ed5bb 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Settings/GeneralPage.xaml @@ -36,9 +36,18 @@ - + - + + + + + + + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw index 0a4000997a..642b3dcc11 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw @@ -322,6 +322,12 @@ Right-click to remove the key combination, thereby deactivating the shortcut. This key will open the Command Palette. + + Use low-level keyboard hook + + + Try this if there are issues with the shortcut (Command Palette might not get focus when triggered from an elevated window) + Go home when activated From f65a3fc06f309b544df0ad2a452edd65ac12ca50 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 16 Apr 2025 12:04:46 -0500 Subject: [PATCH 27/70] Adds support for JUMBO thumbnails in the helper (#38539) Adds a parameter to `Toolkit.ThumbnailHelper.GetThumbnail` to retrieve the largest possible icon from the file. For most use cases, the normal icon size will be good for list items and page icons. But for details, you'll want to use the JUMBO icons, and to retrieve them, we need to get the icon from a different API. As a drive-by, I also have us fetching the highest-res app icon for UWP's rather than the lowest-res icon. Solves #38238 Screenshots: | before | after | | ------ | ----- | | ![image](https://github.com/user-attachments/assets/8aebf163-2f71-45c5-9bee-052ef5528c58) | ![image](https://github.com/user-attachments/assets/7d7b417a-d8d0-4234-ad2b-446a4ca804ba) | | ![image](https://github.com/user-attachments/assets/3aa21305-2d5f-40a5-a091-fbe5ca5f332c) | ![image](https://github.com/user-attachments/assets/beb5e62f-c649-4cbc-8f6e-8d2c1655cac0) | --- .github/actions/spell-check/expect.txt | 5 ++ .../Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs | 38 ++++++---- .../Microsoft.CmdPal.Ext.Apps/AppListItem.cs | 46 ++++++++---- .../Programs/UWPApplication.cs | 9 ++- .../NativeMethods.cs | 6 ++ .../ThumbnailHelper.cs | 73 +++++++++++++++---- 6 files changed, 129 insertions(+), 48 deletions(-) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 59ec830124..7ed61d6173 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -678,6 +678,7 @@ IGo iid Iindex Ijwhost +ILD IMAGEHLP IMAGERESIZERCONTEXTMENU IMAGERESIZEREXT @@ -1453,6 +1454,9 @@ SHELLDLL shellex SHELLEXECUTEINFO SHELLEXECUTEINFOW +SHELLEXTENSION +SHELLICONSIZE +SHELLNEWVALUE SHFILEINFO SHFILEOPSTRUCT SHGDN @@ -1460,6 +1464,7 @@ SHGDNF SHGFI SHGFIICON SHGFILARGEICON +SHIL shinfo shlwapi shobjidl diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs index ed724794fd..f271d4d556 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AllAppsPage.cs @@ -57,7 +57,7 @@ public sealed partial class AllAppsPage : ListPage Stopwatch stopwatch = new(); stopwatch.Start(); - List apps = GetPrograms(); + var apps = GetPrograms(); this.allAppsSection = apps .Select((app) => new AppListItem(app, true)) @@ -73,26 +73,15 @@ public sealed partial class AllAppsPage : ListPage internal List GetPrograms() { - IEnumerable uwpResults = AppCache.Instance.Value.UWPs + var uwpResults = AppCache.Instance.Value.UWPs .Where((application) => application.Enabled) - .Select(app => - new AppItem() - { - Name = app.Name, - Subtitle = app.Description, - Type = UWPApplication.Type(), - IcoPath = app.LogoType != LogoType.Error ? app.LogoPath : string.Empty, - DirPath = app.Location, - UserModelId = app.UserModelId, - IsPackaged = true, - Commands = app.GetCommands(), - }); + .Select(UwpToAppItem); - IEnumerable win32Results = AppCache.Instance.Value.Win32s + var win32Results = AppCache.Instance.Value.Win32s .Where((application) => application.Enabled && application.Valid) .Select(app => { - string icoPath = string.IsNullOrEmpty(app.IcoPath) ? + var icoPath = string.IsNullOrEmpty(app.IcoPath) ? (app.AppType == Win32Program.ApplicationType.InternetShortcutApplication ? app.IcoPath : app.FullPath) : @@ -116,4 +105,21 @@ public sealed partial class AllAppsPage : ListPage return uwpResults.Concat(win32Results).OrderBy(app => app.Name).ToList(); } + + private AppItem UwpToAppItem(UWPApplication app) + { + var iconPath = app.LogoType != LogoType.Error ? app.LogoPath : string.Empty; + var item = new AppItem() + { + Name = app.Name, + Subtitle = app.Description, + Type = UWPApplication.Type(), + IcoPath = iconPath, + DirPath = app.Location, + UserModelId = app.UserModelId, + IsPackaged = true, + Commands = app.GetCommands(), + }; + return item; + } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs index 1ab8df76ef..57c9175d4d 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/AppListItem.cs @@ -32,7 +32,13 @@ internal sealed partial class AppListItem : ListItem Tags = [_appTag]; MoreCommands = _app.Commands!.ToArray(); - _details = new Lazy
(() => BuildDetails()); + _details = new Lazy
(() => + { + var t = BuildDetails(); + t.Wait(); + return t.Result; + }); + _icon = new Lazy(() => { var t = FetchIcon(useThumbnails); @@ -41,8 +47,9 @@ internal sealed partial class AppListItem : ListItem }); } - private Details BuildDetails() + private async Task
BuildDetails() { + // Build metadata, with app type, path, etc. var metadata = new List(); metadata.Add(new DetailsElement() { Key = "Type", Data = new DetailsTags() { Tags = [new Tag(_app.Type)] } }); if (!_app.IsPackaged) @@ -50,10 +57,33 @@ internal sealed partial class AppListItem : ListItem metadata.Add(new DetailsElement() { Key = "Path", Data = new DetailsLink() { Text = _app.ExePath } }); } + // Icon + IconInfo? heroImage = null; + if (_app.IsPackaged) + { + heroImage = new IconInfo(_app.IcoPath); + } + else + { + try + { + var stream = await ThumbnailHelper.GetThumbnail(_app.ExePath, true); + if (stream != null) + { + heroImage = IconInfo.FromStream(stream); + } + } + catch (Exception) + { + // do nothing if we fail to load an icon. + // Logging it would be too NOISY, there's really no need. + } + } + return new Details() { Title = this.Title, - HeroImage = this.Icon ?? new IconInfo(string.Empty), + HeroImage = heroImage ?? this.Icon ?? new IconInfo(string.Empty), Metadata = metadata.ToArray(), }; } @@ -64,11 +94,6 @@ internal sealed partial class AppListItem : ListItem if (_app.IsPackaged) { icon = new IconInfo(_app.IcoPath); - if (_details.IsValueCreated) - { - _details.Value.HeroImage = icon; - } - return icon; } @@ -94,11 +119,6 @@ internal sealed partial class AppListItem : ListItem icon = new IconInfo(_app.IcoPath); } - if (_details.IsValueCreated) - { - _details.Value.HeroImage = icon; - } - return icon; } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs index 6a4cf94480..7a35400a7a 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/UWPApplication.cs @@ -6,13 +6,11 @@ using System; using System.Collections.Generic; using System.IO.Abstractions; using System.Linq; -using System.Runtime.InteropServices; using System.Text; using System.Xml; using Microsoft.CmdPal.Ext.Apps.Commands; using Microsoft.CmdPal.Ext.Apps.Properties; using Microsoft.CmdPal.Ext.Apps.Utils; -using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; using static Microsoft.CmdPal.Ext.Apps.Utils.Native; using PackageVersion = Microsoft.CmdPal.Ext.Apps.Programs.UWP.PackageVersion; @@ -314,7 +312,12 @@ public class UWPApplication : IProgram } } - var selectedIconPath = paths.FirstOrDefault(File.Exists); + // By working from the highest resolution to the lowest, we make + // sure that we use the highest quality possible icon for the app. + // + // FirstOrDefault would result in us using the 1x scaled icon + // always, which is usually too small for our needs. + var selectedIconPath = paths.LastOrDefault(File.Exists); if (!string.IsNullOrEmpty(selectedIconPath)) { LogoPath = selectedIconPath; diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/NativeMethods.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/NativeMethods.cs index 73e8b0cd1c..99db456619 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/NativeMethods.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/NativeMethods.cs @@ -27,4 +27,10 @@ internal sealed class NativeMethods [DllImport("user32.dll", CharSet = CharSet.Unicode)] internal static extern bool DestroyIcon(IntPtr hIcon); + + [DllImport("Shell32.dll", CharSet = CharSet.Unicode)] + internal static extern int SHGetImageList(int iImageList, ref Guid riid, out IntPtr ppv); + + [DllImport("comctl32.dll", SetLastError = true)] + internal static extern int ImageList_GetIcon(IntPtr himl, int i, int flags); } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ThumbnailHelper.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ThumbnailHelper.cs index e71360bcd4..cf7c5c2073 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ThumbnailHelper.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ThumbnailHelper.cs @@ -24,19 +24,12 @@ public class ThumbnailHelper ".ico", ]; - public static Task GetThumbnail(string path) + public static Task GetThumbnail(string path, bool jumbo = false) { var extension = Path.GetExtension(path).ToLower(CultureInfo.InvariantCulture); try { - if (ImageExtensions.Contains(extension)) - { - return GetImageThumbnailAsync(path); - } - else - { - return GetFileIconStream(path); - } + return ImageExtensions.Contains(extension) ? GetImageThumbnailAsync(path) : GetFileIconStream(path, jumbo); } catch (Exception) { @@ -45,9 +38,19 @@ public class ThumbnailHelper return Task.FromResult(null); } - private const uint SHGFIICON = 0x000000100; - private const uint SHGFILARGEICON = 0x000000000; + // these are windows constants and mangling them is goofy +#pragma warning disable SA1310 // Field names should not contain underscore +#pragma warning disable SA1306 // Field names should begin with lower-case letter + private const uint SHGFI_ICON = 0x000000100; + private const uint SHGFI_SHELLICONSIZE = 0x000000004; + private const int SHGFI_SYSICONINDEX = 0x000004000; + private const int SHIL_JUMBO = 4; + private const int ILD_TRANSPARENT = 1; +#pragma warning restore SA1306 // Field names should begin with lower-case letter +#pragma warning restore SA1310 // Field names should not contain underscore + // This will call DestroyIcon on the hIcon passed in. + // Duplicate it if you need it again after this. private static MemoryStream GetMemoryStreamFromIcon(IntPtr hIcon) { var memoryStream = new MemoryStream(); @@ -65,19 +68,40 @@ public class ThumbnailHelper return memoryStream; } - private static async Task GetFileIconStream(string filePath) + private static async Task GetFileIconStream(string filePath, bool jumbo) { - var shinfo = default(NativeMethods.SHFILEINFO); - var hr = NativeMethods.SHGetFileInfo(filePath, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFIICON | SHGFILARGEICON); + nint hIcon = 0; - if (hr == 0 || shinfo.hIcon == 0) + // If requested, look up the Jumbo icon + if (jumbo) + { + hIcon = GetLargestIcon(filePath); + } + + // If we didn't want the JUMBO icon, or didn't find it, fall back to + // the normal icon lookup + if (hIcon == 0) + { + var shinfo = default(NativeMethods.SHFILEINFO); + + var hr = NativeMethods.SHGetFileInfo(filePath, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_SHELLICONSIZE); + + if (hr == 0 || shinfo.hIcon == 0) + { + return null; + } + + hIcon = shinfo.hIcon; + } + + if (hIcon == 0) { return null; } var stream = new InMemoryRandomAccessStream(); - using var memoryStream = GetMemoryStreamFromIcon(shinfo.hIcon); + using var memoryStream = GetMemoryStreamFromIcon(hIcon); // this will DestroyIcon hIcon using var outputStream = stream.GetOutputStreamAt(0); using (var dataWriter = new DataWriter(outputStream)) { @@ -95,4 +119,21 @@ public class ThumbnailHelper var thumbnail = await file.GetThumbnailAsync(ThumbnailMode.PicturesView); return thumbnail; } + + private static nint GetLargestIcon(string path) + { + var shinfo = default(NativeMethods.SHFILEINFO); + NativeMethods.SHGetFileInfo(path, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | SHGFI_SYSICONINDEX); + + var hIcon = IntPtr.Zero; + var iID_IImageList = new Guid("46EB5926-582E-4017-9FDF-E8998DAA0950"); + IntPtr imageListPtr; + + if (NativeMethods.SHGetImageList(SHIL_JUMBO, ref iID_IImageList, out imageListPtr) == 0 && imageListPtr != IntPtr.Zero) + { + hIcon = NativeMethods.ImageList_GetIcon(imageListPtr, shinfo.iIcon, ILD_TRANSPARENT); + } + + return hIcon; + } } From cb27874805ca042526f2513d38bb93c7d9e5547b Mon Sep 17 00:00:00 2001 From: Heiko <61519853+htcfreek@users.noreply.github.com> Date: Wed, 16 Apr 2025 20:51:20 +0200 Subject: [PATCH 28/70] [PowerToysRun] Add version info to plugin error messages (#38491) * changes * fix resx --- .../PowerLauncher/Plugin/PluginManager.cs | 5 +++-- .../Properties/Resources.Designer.cs | 2 +- .../PowerLauncher/Properties/Resources.resx | 2 +- .../launcher/PowerLauncher/SettingsReader.cs | 3 +-- .../launcher/Wox.Plugin/PluginMetadata.cs | 20 +++++++++++++++++++ src/modules/launcher/Wox.Plugin/PluginPair.cs | 5 +++-- .../Properties/Resources.Designer.cs | 2 +- .../Wox.Plugin/Properties/Resources.resx | 2 +- 8 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/modules/launcher/PowerLauncher/Plugin/PluginManager.cs b/src/modules/launcher/PowerLauncher/Plugin/PluginManager.cs index ad01b7eba4..f12359c528 100644 --- a/src/modules/launcher/PowerLauncher/Plugin/PluginManager.cs +++ b/src/modules/launcher/PowerLauncher/Plugin/PluginManager.cs @@ -185,9 +185,10 @@ namespace PowerLauncher.Plugin if (!failedPlugins.IsEmpty) { - var failed = string.Join(", ", failedPlugins.Select(x => x.Metadata.Name)); + string title = Resources.FailedToInitializePluginsTitle.ToString().Replace("{0}", Constant.Version); + var failed = string.Join(", ", failedPlugins.Select(x => $"{x.Metadata.Name} ({x.Metadata.ExecuteFileVersion})")); var description = $"{string.Format(CultureInfo.CurrentCulture, FailedToInitializePluginsDescription, failed)}\n\n{Resources.FailedToInitializePluginsDescriptionPartTwo}"; - Application.Current.Dispatcher.InvokeAsync(() => API.ShowMsg(Resources.FailedToInitializePluginsTitle, description, string.Empty, false)); + Application.Current.Dispatcher.InvokeAsync(() => API.ShowMsg(title, description, string.Empty, false)); } } diff --git a/src/modules/launcher/PowerLauncher/Properties/Resources.Designer.cs b/src/modules/launcher/PowerLauncher/Properties/Resources.Designer.cs index d4c435a900..b67d172e2f 100644 --- a/src/modules/launcher/PowerLauncher/Properties/Resources.Designer.cs +++ b/src/modules/launcher/PowerLauncher/Properties/Resources.Designer.cs @@ -160,7 +160,7 @@ namespace PowerLauncher.Properties { } /// - /// Looks up a localized string similar to PowerToys Run - Plugin Initialization Error. + /// Looks up a localized string similar to PowerToys Run {0} - Plugin Initialization Error. /// public static string FailedToInitializePluginsTitle { get { diff --git a/src/modules/launcher/PowerLauncher/Properties/Resources.resx b/src/modules/launcher/PowerLauncher/Properties/Resources.resx index 421919bb13..e3a64a6fdd 100644 --- a/src/modules/launcher/PowerLauncher/Properties/Resources.resx +++ b/src/modules/launcher/PowerLauncher/Properties/Resources.resx @@ -189,7 +189,7 @@ Fail to initialize plugins: {0} - PowerToys Run - Plugin Initialization Error + PowerToys Run {0} - Plugin Initialization Error Don't translate "PowerToys Run". This is a product name. diff --git a/src/modules/launcher/PowerLauncher/SettingsReader.cs b/src/modules/launcher/PowerLauncher/SettingsReader.cs index 7d03e4cb27..41d0524f69 100644 --- a/src/modules/launcher/PowerLauncher/SettingsReader.cs +++ b/src/modules/launcher/PowerLauncher/SettingsReader.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.IO.Abstractions; using System.Linq; @@ -252,7 +251,7 @@ namespace PowerLauncher Id = x.Metadata.ID, Name = x.Plugin == null ? x.Metadata.Name : x.Plugin.Name, Description = x.Plugin?.Description, - Version = FileVersionInfo.GetVersionInfo(x.Metadata.ExecuteFilePath).FileVersion, + Version = x.Metadata.ExecuteFileVersion, Author = x.Metadata.Author, Website = x.Metadata.Website, Disabled = x.Metadata.Disabled, diff --git a/src/modules/launcher/Wox.Plugin/PluginMetadata.cs b/src/modules/launcher/Wox.Plugin/PluginMetadata.cs index 9a22fa485a..4596e7da4a 100644 --- a/src/modules/launcher/Wox.Plugin/PluginMetadata.cs +++ b/src/modules/launcher/Wox.Plugin/PluginMetadata.cs @@ -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.Diagnostics; +using System.IO; using System.IO.Abstractions; using System.Text.Json.Serialization; @@ -42,6 +44,9 @@ namespace Wox.Plugin public string ExecuteFileName { get; set; } + [JsonIgnore] + public string ExecuteFileVersion { get; private set; } + public string PluginDirectory { get @@ -53,6 +58,7 @@ namespace Wox.Plugin { _pluginDirectory = value; ExecuteFilePath = Path.Combine(value, ExecuteFileName); + SetExecutableVersion(); } } @@ -84,5 +90,19 @@ namespace Wox.Plugin [JsonIgnore] public int QueryCount { get; set; } + + private void SetExecutableVersion() + { + // Using version from plugin metadata json as fallback + try + { + var v = FileVersionInfo.GetVersionInfo(ExecuteFilePath).FileVersion; + ExecuteFileVersion = (v is null or "0.0.0.0") ? Version : v; + } + catch (FileNotFoundException) + { + ExecuteFileVersion = Version; + } + } } } diff --git a/src/modules/launcher/Wox.Plugin/PluginPair.cs b/src/modules/launcher/Wox.Plugin/PluginPair.cs index d31970d16d..01daf9fb22 100644 --- a/src/modules/launcher/Wox.Plugin/PluginPair.cs +++ b/src/modules/launcher/Wox.Plugin/PluginPair.cs @@ -82,8 +82,9 @@ namespace Wox.Plugin if (!IsPluginInitialized) { - string description = $"{Resources.FailedToLoadPluginDescription} {Metadata.Name}\n\n{Resources.FailedToLoadPluginDescriptionPartTwo}"; - Application.Current.Dispatcher.InvokeAsync(() => api.ShowMsg(Resources.FailedToLoadPluginTitle, description, string.Empty, false)); + string title = Resources.FailedToLoadPluginTitle.ToString().Replace("{0}", Constant.Version); + string description = $"{Resources.FailedToLoadPluginDescription} {Metadata.Name} ({Metadata.ExecuteFileVersion})\n\n{Resources.FailedToLoadPluginDescriptionPartTwo}"; + Application.Current.Dispatcher.InvokeAsync(() => api.ShowMsg(title, description, string.Empty, false)); } } else diff --git a/src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs b/src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs index b90d429f40..6e08434dfc 100644 --- a/src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs +++ b/src/modules/launcher/Wox.Plugin/Properties/Resources.Designer.cs @@ -79,7 +79,7 @@ namespace Wox.Plugin.Properties { } /// - /// Looks up a localized string similar to PowerToys Run - Plugin Loading Error. + /// Looks up a localized string similar to PowerToys Run {0} - Plugin Loading Error. /// public static string FailedToLoadPluginTitle { get { diff --git a/src/modules/launcher/Wox.Plugin/Properties/Resources.resx b/src/modules/launcher/Wox.Plugin/Properties/Resources.resx index c8b8b2e9a7..1286bea532 100644 --- a/src/modules/launcher/Wox.Plugin/Properties/Resources.resx +++ b/src/modules/launcher/Wox.Plugin/Properties/Resources.resx @@ -125,7 +125,7 @@ "https://aka.ms/powerToysReportBug" is a web uri. - PowerToys Run - Plugin Loading Error + PowerToys Run {0} - Plugin Loading Error Don't translate "PowerToys Run". This is a product name. From e95a570d4887e2cbf81e098fdec8cce57eaa0324 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 16 Apr 2025 14:47:33 -0500 Subject: [PATCH 29/70] Don't auto-hide when an MSAL dialog is opened on us (#38850) Apps that want to show MSAL dialogs on the Command Palette would explode if they passed CmdPal's HWND to WithParentActivityOrWindow. It's not entirely clear why, but MSAL would explode if the parent HWND is hidden. When the MSAL dialog opened, we'd hide ourselves, and badda bing, badda boom, the extension would crash. MSAL dialogs will set us to WS_DISABLED right before the dialog is opened. Easy solution. Don't hide ourselves, if we're disabled. Helps some friends not depend on the existence of Teams :P --- .github/actions/spell-check/expect.txt | 1 + .../Microsoft.CmdPal.UI/MainWindow.xaml.cs | 28 +++++++++---------- .../Microsoft.CmdPal.UI/NativeMethods.txt | 1 + 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 7ed61d6173..de92227692 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -939,6 +939,7 @@ mpmc MRM MRT mru +MSAL msc mscorlib msctls diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs index c99543f9e1..be28b0edc3 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/MainWindow.xaml.cs @@ -286,16 +286,12 @@ public sealed partial class MainWindow : Window, ShowHwnd(message.Hwnd, settings.SummonOn); } - public void Receive(HideWindowMessage message) - { - PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE); - } + public void Receive(HideWindowMessage message) => PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE); + + public void Receive(QuitMessage message) => - public void Receive(QuitMessage message) - { // This might come in on a background thread DispatcherQueue.TryEnqueue(() => Close()); - } public void Receive(DismissMessage message) => PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE); @@ -378,12 +374,17 @@ public sealed partial class MainWindow : Window, // ... then don't hide the window when it loses focus. return; } - else - { - PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE); - PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnLostFocus()); + // Are we disabled? If we are, then we don't want to dismiss on focus lost. + // This can happen if an extension wanted to show a modal dialog on top of our + // window i.e. in the case of an MSAL auth window. + if (PInvoke.IsWindowEnabled(_hwnd) == 0) + { + return; } + + PInvoke.ShowWindow(_hwnd, SHOW_WINDOW_CMD.SW_HIDE); + PowerToysTelemetry.Log.WriteEvent(new CmdPalDismissedOnLostFocus()); } if (_configurationSource != null) @@ -392,14 +393,13 @@ public sealed partial class MainWindow : Window, } } - public void Summon(string commandId) - { + public void Summon(string commandId) => + // The actual showing and hiding of the window will be done by the // ShellPage. This is because we don't want to show the window if the // user bound a hotkey to just an invokable command, which we can't // know till the message is being handled. WeakReferenceMessenger.Default.Send(new(commandId, _hwnd)); - } #pragma warning disable SA1310 // Field names should not contain underscore private const uint DOT_KEY = 0xBE; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/NativeMethods.txt b/src/modules/cmdpal/Microsoft.CmdPal.UI/NativeMethods.txt index 566f459c65..4db59d7070 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/NativeMethods.txt +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/NativeMethods.txt @@ -15,6 +15,7 @@ CallWindowProc ShowWindow SetForegroundWindow EnableWindow +IsWindowEnabled SetFocus SetActiveWindow MonitorFromWindow From 67463abf98f3ca3969cf3923ccc8ebcac98aa252 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 16 Apr 2025 14:47:55 -0500 Subject: [PATCH 30/70] Immediately select search text on opening page (#38842) closes #38712 closes #38315 related to #38379 (and might sufficiently close that too) This immediately selects the search text when a page is loaded. ![38712-select-search-text-000](https://github.com/user-attachments/assets/9db8b455-9afb-4b11-9a30-8ddaa23cdb64) --- .../ListViewModel.cs | 33 +++++++++-------- .../Controls/SearchBar.xaml.cs | 35 +++++++++++++------ .../Properties/Resources.Designer.cs | 4 +-- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ListViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ListViewModel.cs index f1c6aa4695..c448745743 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ListViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ListViewModel.cs @@ -52,6 +52,8 @@ public partial class ListViewModel : PageViewModel, IDisposable public string SearchText { get; private set; } = string.Empty; + public string InitialSearchText { get; private set; } = string.Empty; + public CommandItemViewModel EmptyContent { get; private set; } private bool _isDynamic; @@ -128,7 +130,7 @@ public partial class ListViewModel : PageViewModel, IDisposable try { - IListItem[] newItems = _model.Unsafe!.GetItems(); + var newItems = _model.Unsafe!.GetItems(); // Collect all the items into new viewmodels Collection newViewModels = []; @@ -136,7 +138,7 @@ public partial class ListViewModel : PageViewModel, IDisposable // TODO we can probably further optimize this by also keeping a // HashSet of every ExtensionObject we currently have, and only // building new viewmodels for the ones we haven't already built. - foreach (IListItem? item in newItems) + foreach (var item in newItems) { ListItemViewModel viewModel = new(item, new(this)); @@ -147,8 +149,8 @@ public partial class ListViewModel : PageViewModel, IDisposable } } - IEnumerable firstTwenty = newViewModels.Take(20); - foreach (ListItemViewModel? item in firstTwenty) + var firstTwenty = newViewModels.Take(20); + foreach (var item in firstTwenty) { item?.SafeInitializeProperties(); } @@ -233,7 +235,7 @@ public partial class ListViewModel : PageViewModel, IDisposable iterable = Items.ToArray(); } - foreach (ListItemViewModel item in iterable) + foreach (var item in iterable) { ct.ThrowIfCancellationRequested(); @@ -266,8 +268,8 @@ public partial class ListViewModel : PageViewModel, IDisposable return 1; } - MatchResult nameMatch = StringMatcher.FuzzySearch(query, listItem.Title); - MatchResult descriptionMatch = StringMatcher.FuzzySearch(query, listItem.Subtitle); + var nameMatch = StringMatcher.FuzzySearch(query, listItem.Title); + var descriptionMatch = StringMatcher.FuzzySearch(query, listItem.Subtitle); return new[] { nameMatch.Score, (descriptionMatch.Score - 4) / 2, 0 }.Max(); } @@ -280,7 +282,7 @@ public partial class ListViewModel : PageViewModel, IDisposable // Similarly stolen from ListHelpers.FilterList public static IEnumerable FilterList(IEnumerable items, string query) { - IOrderedEnumerable scores = items + var scores = items .Where(i => !i.IsInErrorState) .Select(li => new ScoredListItemViewModel() { ViewModel = li, Score = ScoreListItem(query, li) }) .Where(score => score.Score > 0) @@ -359,7 +361,7 @@ public partial class ListViewModel : PageViewModel, IDisposable { base.InitializeProperties(); - IListPage? model = _model.Unsafe; + var model = _model.Unsafe; if (model == null) { return; // throw? @@ -373,8 +375,9 @@ public partial class ListViewModel : PageViewModel, IDisposable _modelPlaceholderText = model.PlaceholderText; UpdateProperty(nameof(PlaceholderText)); - SearchText = model.SearchText; + InitialSearchText = SearchText = model.SearchText; UpdateProperty(nameof(SearchText)); + UpdateProperty(nameof(InitialSearchText)); EmptyContent = new(new(model.EmptyContent), PageContext); EmptyContent.SlowInitializeProperties(); @@ -385,7 +388,7 @@ public partial class ListViewModel : PageViewModel, IDisposable public void LoadMoreIfNeeded() { - IListPage? model = this._model.Unsafe; + var model = this._model.Unsafe; if (model == null) { return; @@ -412,7 +415,7 @@ public partial class ListViewModel : PageViewModel, IDisposable { base.FetchProperty(propertyName); - IListPage? model = this._model.Unsafe; + var model = this._model.Unsafe; if (model == null) { return; // throw? @@ -475,13 +478,13 @@ public partial class ListViewModel : PageViewModel, IDisposable lock (_listLock) { - foreach (ListItemViewModel item in Items) + foreach (var item in Items) { item.SafeCleanup(); } Items.Clear(); - foreach (ListItemViewModel item in FilteredItems) + foreach (var item in FilteredItems) { item.SafeCleanup(); } @@ -489,7 +492,7 @@ public partial class ListViewModel : PageViewModel, IDisposable FilteredItems.Clear(); } - IListPage? model = _model.Unsafe; + var model = _model.Unsafe; if (model != null) { model.ItemsChanged -= Model_ItemsChanged; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs index f41ac98ea3..c318f264c0 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs @@ -250,18 +250,31 @@ public sealed partial class SearchBar : UserControl, private void Page_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) { var property = e.PropertyName; - if (CurrentPageViewModel is ListViewModel list && - property == nameof(ListViewModel.SearchText)) - { - // Only if the text actually changed... - // (sometimes this triggers on a round-trip of the SearchText) - if (FilterBox.Text != list.SearchText) - { - // ... Update our displayed text, and... - FilterBox.Text = list.SearchText; - // ... Move the cursor to the end of the input - FilterBox.Select(FilterBox.Text.Length, 0); + if (CurrentPageViewModel is ListViewModel list) + { + if (property == nameof(ListViewModel.SearchText)) + { + // Only if the text actually changed... + // (sometimes this triggers on a round-trip of the SearchText) + if (FilterBox.Text != list.SearchText) + { + // ... Update our displayed text, and... + FilterBox.Text = list.SearchText; + + // ... Move the cursor to the end of the input + FilterBox.Select(FilterBox.Text.Length, 0); + } + } + else if (property == nameof(ListViewModel.InitialSearchText)) + { + // GH #38712: + // The ListPage will notify us of the `InitialSearchText` when + // we first load the viewmodel. We can use that as an + // opportunity to immediately select the search text. That lets + // the user start typing a new search without manually + // selecting the old one. + SelectSearch(); } } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.Designer.cs index c20800d1c1..ce71199763 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.Designer.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsServices/Properties/Resources.Designer.cs @@ -88,7 +88,7 @@ namespace Microsoft.CmdPal.Ext.WindowsServices.Properties { } /// - /// Looks up a localized string similar to Open services (Ctrl+O). + /// Looks up a localized string similar to Open services. /// internal static string wox_plugin_service_open_services { get { @@ -133,7 +133,7 @@ namespace Microsoft.CmdPal.Ext.WindowsServices.Properties { } /// - /// Looks up a localized string similar to Restart (Ctrl+R). + /// Looks up a localized string similar to Restart. /// internal static string wox_plugin_service_restart { get { From 01584f33e1ce682be81e796a8e33fc70092097d4 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Wed, 16 Apr 2025 14:50:56 -0500 Subject: [PATCH 31/70] Update the settings form when ext settings are saved (#38851) This one was subtle - the Settings class in the toolkit didn't ever change the items for a SettingsContentPage. For the main settings window, this was problematic. It would only ever hang onto one instance of that CommandSettings.SettingsContentPage, and never re-retrieve the value from it. This fixes that issue, by making sure to raise an ItemsChanged in the settings changed handler, so that we automatically pull down the new settings forms. For settings that were added to commands, as a context item, this wasn't an issue. They were always returning new forms to the host, with the current settings values in it. Closes #38191 --- .../Microsoft.CommandPalette.Extensions.Toolkit/Settings.cs | 4 ++++ .../SettingsForm.cs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Settings.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Settings.cs index 39d3b1f855..7f877664bd 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Settings.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/Settings.cs @@ -118,6 +118,10 @@ public sealed partial class Settings : ICommandSettings _settings = settings; Name = "Settings"; Icon = new IconInfo("\uE713"); // Settings icon + + // When our settings change, make sure to let CmdPal know to + // retrieve the new forms + _settings.SettingsChanged += (s, e) => RaiseItemsChanged(); } } diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/SettingsForm.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/SettingsForm.cs index fa23cd8f0d..79f548bf56 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/SettingsForm.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/SettingsForm.cs @@ -24,6 +24,12 @@ public partial class SettingsForm : FormContent return CommandResult.KeepOpen(); } + // Re-render the current value of the settings to a card. The + // SettingsContentPage will raise an ItemsChanged in its own + // SettingsChange handler, so we need to be prepared to return the + // current settings value. + TemplateJson = _settings.ToFormJson(); + _settings.Update(inputs); _settings.RaiseSettingsChanged(); From 397d5cf6554bd74d91249c8410fa6a0c7f3cfa89 Mon Sep 17 00:00:00 2001 From: Ved Nig Date: Thu, 17 Apr 2025 03:56:36 +0530 Subject: [PATCH 32/70] Powertoys for Linear plugin added (#38883) * Update thirdPartyRunPlugins.md * Update names.txt --------- Co-authored-by: Clint Rutkas --- .github/actions/spell-check/allow/names.txt | 1 + doc/thirdPartyRunPlugins.md | 1 + 2 files changed, 2 insertions(+) diff --git a/.github/actions/spell-check/allow/names.txt b/.github/actions/spell-check/allow/names.txt index 289da43b14..eeda5b9ae1 100644 --- a/.github/actions/spell-check/allow/names.txt +++ b/.github/actions/spell-check/allow/names.txt @@ -189,6 +189,7 @@ Zoltan Zykova Sameerjs ruslanlap +vednig # OTHERS diff --git a/doc/thirdPartyRunPlugins.md b/doc/thirdPartyRunPlugins.md index 7070086bc9..ec8ffc69a4 100644 --- a/doc/thirdPartyRunPlugins.md +++ b/doc/thirdPartyRunPlugins.md @@ -68,3 +68,4 @@ Below are community created plugins that target a website or software. They are | [Bilibili](https://github.com/Whuihuan/PowerToysRun-Bilibili) | [Whuihuan](https://github.com/Whuihuan) | Use AVID or BVID to parse and jump to Bilibili | | [YubicoOauthOTP](https://github.com/dlnilsson/Community.PowerToys.Run.Plugin.YubicoOauthOTP) | [dlnilsson](https://github.com/dlnilsson) | Display generated codes from OATH accounts stored on the YubiKey in powerToys Run | | [Firefox Bookmark](https://github.com/8LWXpg/PowerToysRun-FirefoxBookmark) | [8LWXpg](https://github.com/8LWXpg) | Open bookmarks in Firefox based browser | +[Linear](https://github.com/vednig/powertoys-linear) | [vednig](https://github.com/vednig) | Create Linear Issues directly from Powertoys Run | From 4f9e829155506756ba680a6b9a7d4ba606e669dc Mon Sep 17 00:00:00 2001 From: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Thu, 17 Apr 2025 11:53:22 +0800 Subject: [PATCH 33/70] [cmdpal] Run cmdpalette from runner locally (#38725) * empowering users to maximize OOBE to their heart desire (#37823) empowering users to maximize to their heart desire * resume main * Trust selfsign cert in localmachine\root to make msix available * minor fix * retry signing --------- Co-authored-by: Clint Rutkas --- .github/actions/spell-check/expect.txt | 3 + .../cmdpal/CmdPalModuleInterface/dllmain.cpp | 8 +- .../Microsoft.CmdPal.UI.csproj | 2 +- tools/build/self-sign.ps1 | 179 ++++++++++++++++++ 4 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 tools/build/self-sign.ps1 diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index de92227692..8eba793e1b 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -173,6 +173,7 @@ CContext CDeclaration CElems CENTERALIGN +cer certlm certmgr cfp @@ -343,6 +344,7 @@ DEVMODE DEVMODEW devpal DIALOGEX +digicert dimm DISABLEASACTIONKEY DISABLENOSCROLL @@ -1497,6 +1499,7 @@ SIDs siex sigdn SIGNINGSCENARIO +signtool Signtool SINGLEKEY sipolicy diff --git a/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp b/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp index aceadabdd8..134249f049 100644 --- a/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp +++ b/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp @@ -207,12 +207,16 @@ public: try { - if (!package::GetRegisteredPackage(L"Microsoft.CommandPalette", false).has_value()) + std::wstring packageName = L"Microsoft.CommandPalette"; +#ifdef _DEBUG + packageName = L"Microsoft.CommandPalette.Dev"; +#endif + if (!package::GetRegisteredPackage(packageName, false).has_value()) { Logger::info(L"CmdPal not installed. Installing..."); std::wstring installationFolder = get_module_folderpath(); -#if _DEBUG +#ifdef _DEBUG std::wstring archSubdir = L"x64"; #ifdef _M_ARM64 archSubdir = L"ARM64"; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj b/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj index 670382ecd8..c79669e714 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Microsoft.CmdPal.UI.csproj @@ -23,7 +23,7 @@ false - + true diff --git a/tools/build/self-sign.ps1 b/tools/build/self-sign.ps1 new file mode 100644 index 0000000000..43085ae851 --- /dev/null +++ b/tools/build/self-sign.ps1 @@ -0,0 +1,179 @@ +#https://learn.microsoft.com/en-us/windows/msix/package/signing-known-issues +# 1. Build the powertoys as usual. +# 2. Call this script to sign the msix package. +# First time run needs admin permission to trust the certificate. + +param ( + [string]$architecture = "x64", # Default to x64 if not provided + [string]$buildConfiguration = "Debug" # Default to Debug if not provided +) + +$signToolPath = $null +$kitsRootPaths = @( + "C:\Program Files (x86)\Windows Kits\10\bin", + "C:\Program Files\Windows Kits\10\bin" +) + +$signToolAvailable = Get-Command "signtool" -ErrorAction SilentlyContinue +if ($signToolAvailable) { + Write-Host "SignTool is available in the system PATH." + $signToolPath = "signtool" +} +else { + Write-Host "Searching for latest SignTool matching architecture: $architecture" + + foreach ($root in $kitsRootPaths) { + if (Test-Path $root) { + $versions = Get-ChildItem -Path $root -Directory | Where-Object { + $_.Name -match '^\d+\.\d+\.\d+\.\d+$' + } | Sort-Object Name -Descending + + foreach ($version in $versions) { + $candidatePath = Join-Path -Path $version.FullName -ChildPath "x86" + $exePath = Join-Path -Path $candidatePath -ChildPath "signtool.exe" + if (Test-Path $exePath) { + Write-Host "Found SignTool at: $exePath" + $signToolPath = $exePath + break + } + } + + if ($signToolPath) { break } + } + } + + if (!$signToolPath) { + Write-Host "SignTool not found. Please ensure Windows SDK is installed." + exit 1 + } +} + +Write-Host "`nUsing SignTool: $signToolPath" + +# Set the certificate subject and the ECDSA curve +$certSubject = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" + +# Check if the certificate already exists in the current user's certificate store +$existingCert = Get-ChildItem -Path Cert:\CurrentUser\My | +Where-Object { $_.Subject -eq $certSubject } | +Sort-Object NotAfter -Descending | +Select-Object -First 1 + +if ($existingCert) { + # If the certificate exists, use the existing certificate + Write-Host "Certificate already exists, using the existing certificate" + $cert = $existingCert +} +else { + # If the certificate doesn't exist, create a new self-signed certificate + Write-Host "Certificate does not exist, creating a new certificate..." + $cert = New-SelfSignedCertificate -Subject $certSubject ` + -CertStoreLocation "Cert:\CurrentUser\My" ` + -KeyAlgorithm RSA ` + -Type CodeSigningCert ` + -HashAlgorithm SHA256 +} + +function Import-And-VerifyCertificate { + param ( + [string]$cerPath, + [string]$storePath + ) + + $thumbprint = (Get-PfxCertificate -FilePath $cerPath).Thumbprint + + # ✅ Step 1: Check if already exists in store + $existingCert = Get-ChildItem -Path $storePath | Where-Object { $_.Thumbprint -eq $thumbprint } + + if ($existingCert) { + Write-Host "✅ Certificate already exists in $storePath" + return $true + } + + # 🚀 Step 2: Try to import if not already there + try { + $null = Import-Certificate -FilePath $cerPath -CertStoreLocation $storePath -ErrorAction Stop + } + catch { + Write-Warning "❌ Failed to import certificate to $storePath : $_" + return $false + } + + # 🔁 Step 3: Verify again + $imported = Get-ChildItem -Path $storePath | Where-Object { $_.Thumbprint -eq $thumbprint } + + if ($imported) { + Write-Host "✅ Certificate successfully imported to $storePath" + return $true + } + else { + Write-Warning "❌ Certificate not found in $storePath after import" + return $false + } +} + +$cerPath = "$env:TEMP\temp_cert.cer" +Export-Certificate -Cert $cert -FilePath $cerPath -Force +# used for sign code/msix +# CurrentUser\TrustedPeople +if (-not (Import-And-VerifyCertificate -cerPath $cerPath -storePath "Cert:\CurrentUser\TrustedPeople")) { + exit 1 +} + +# CurrentUser\Root +if (-not (Import-And-VerifyCertificate -cerPath $cerPath -storePath "Cert:\CurrentUser\Root")) { + exit 1 +} + +# LocalMachine\Root +if (-not (Import-And-VerifyCertificate -cerPath $cerPath -storePath "Cert:\LocalMachine\Root")) { + Write-Warning "⚠️ Failed to import to LocalMachine\Root (admin may be required)" + exit 1 +} + + +# Output the thumbprint of the certificate (to confirm which certificate is being used) +Write-Host "Using certificate with thumbprint: $($cert.Thumbprint)" + + +$rootDirectory = (Split-Path -Parent(Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path))) + +# Dynamically build the directory path based on architecture and build configuration +# $directoryPath = Join-Path $rootDirectory "$architecture\$buildConfiguration\WinUI3Apps\CmdPal\" +$directoryPath = Join-Path $rootDirectory "$architecture\$buildConfiguration\WinUI3Apps\CmdPal\" + +if (-not (Test-Path $directoryPath)) { + Write-Error "Path to search for msix files does not exist: $directoryPath" + exit 1 +} + +Write-Host "Directory path to search for .msix and .appx files: $directoryPath" + +# Get all .msix and .appx files from the specified directory +$filePaths = Get-ChildItem -Path $directoryPath -Recurse | Where-Object { + ($_.Extension -eq ".msix" -or $_.Extension -eq ".appx") -and + ($_.Name -like "*$architecture*") +} + +if ($filePaths.Count -eq 0) { + Write-Host "No .msix or .appx files found in the directory." +} +else { + # Iterate through each file and sign it + foreach ($file in $filePaths) { + Write-Host "Signing file: $($file.FullName)" + + # Use SignTool to sign the file + $signToolCommand = "& `"$signToolPath`" sign /sha1 $($cert.Thumbprint) /fd SHA256 /t http://timestamp.digicert.com `"$($file.FullName)`"" + + # Execute the sign command + try { + Invoke-Expression $signToolCommand + } + catch { + Write-Host "Error signing file $($file.Name): $_" + } + } +} + +Write-Host "Signing process completed." From 6cf73ce839b16ea0ade07bc0b8052d63e77bea9b Mon Sep 17 00:00:00 2001 From: Yu Leng <42196638+moooyo@users.noreply.github.com> Date: Thu, 17 Apr 2025 14:59:10 +0800 Subject: [PATCH 34/70] [cmdpal] Port v1 calculator extension (#38629) * init * update * Remove duplicated cp command * Change the long desc * Update notice.md * Use the same icon for fallback item * Add Rappl to expect list * update notice.md * Move the original order back. * Make Radians become default choice * Fix empty result * Remove unused settings. Move history back. Refactory the query logic * fix typo * merge main * CmdPal: minor calc updates (#38914) A bunch of calc updates * maintain the visibility of the history * add other formats to the context menu #38708 * some other icon tidying --------- Co-authored-by: Yu Leng (from Dev Box) Co-authored-by: Mike Griese --- .github/actions/spell-check/expect.txt | 1 + NOTICE.md | 34 ++ .../CalculatorCommandProvider.cs | 166 +-------- .../Helper/BracketHelper.cs | 86 +++++ .../Helper/CalculateEngine.cs | 127 +++++++ .../Helper/CalculateHelper.cs | 328 ++++++++++++++++++ .../Helper/CalculateResult.cs | 39 +++ .../Helper/CalculatorIcons.cs | 18 + .../Helper/ErrorHandler.cs | 53 +++ .../Helper/NumberTranslator.cs | 144 ++++++++ .../Helper/QueryHelper.cs | 77 ++++ .../Helper/ResultHelper.cs | 103 ++++++ .../Helper/SaveCommand.cs | 31 ++ .../Helper/SettingsManager.cs | 98 ++++++ .../Microsoft.CmdPal.Ext.Calc.csproj | 5 + .../Pages/CalculatorListPage.cs | 127 +++++++ .../Pages/FallbackCalculatorItem.cs | 52 +++ .../Properties/Resources.Designer.cs | 171 +++++++++ .../Properties/Resources.resx | 59 ++++ 19 files changed, 1565 insertions(+), 154 deletions(-) create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/BracketHelper.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateEngine.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateHelper.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateResult.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculatorIcons.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ErrorHandler.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/NumberTranslator.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/QueryHelper.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SaveCommand.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SettingsManager.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 8eba793e1b..46432105d0 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1299,6 +1299,7 @@ QUNS QXZ RAII RAlt +Rappl randi Rasterization Rasterize diff --git a/NOTICE.md b/NOTICE.md index 83a24ef185..92bdf5fe39 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -75,6 +75,40 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to ``` +## Utility: Command Palette Built-in Extensions + +### Calculator + +#### Mages + +We use the Mages NuGet package for calculating the result of expression. + +**Source**: [https://github.com/FlorianRappl/Mages](https://github.com/FlorianRappl/Mages) + +``` +The MIT License (MIT) + +Copyright (c) 2016 - 2025 Florian Rappl + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` + ## Utility: File Explorer Add-ins ### Monaco Editor diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/CalculatorCommandProvider.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/CalculatorCommandProvider.cs index 04d474a31a..1478dbbd45 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/CalculatorCommandProvider.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/CalculatorCommandProvider.cs @@ -2,176 +2,34 @@ // 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.Collections.Generic; -using System.Data; -using System.Globalization; -using System.Text; +using Microsoft.CmdPal.Ext.Calc.Helper; +using Microsoft.CmdPal.Ext.Calc.Pages; using Microsoft.CmdPal.Ext.Calc.Properties; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; -using Windows.Foundation; namespace Microsoft.CmdPal.Ext.Calc; public partial class CalculatorCommandProvider : CommandProvider { - private readonly ListItem _listItem = new(new CalculatorListPage()) { Subtitle = Resources.calculator_top_level_subtitle }; - private readonly FallbackCalculatorItem _fallback = new(); + private readonly ListItem _listItem = new(new CalculatorListPage(settings)) + { + Subtitle = Resources.calculator_top_level_subtitle, + MoreCommands = [new CommandContextItem(settings.Settings.SettingsPage)], + }; + + private readonly FallbackCalculatorItem _fallback = new(settings); + private static SettingsManager settings = new(); public CalculatorCommandProvider() { Id = "Calculator"; DisplayName = Resources.calculator_display_name; - Icon = IconHelpers.FromRelativePath("Assets\\Calculator.svg"); + Icon = CalculatorIcons.ProviderIcon; + Settings = settings.Settings; } public override ICommandItem[] TopLevelCommands() => [_listItem]; public override IFallbackCommandItem[] FallbackCommands() => [_fallback]; } - -// The calculator page is a dynamic list page -// * The first command is where we display the results. Title=result, Subtitle=query -// - The default command is `SaveCommand`. -// - When you save, insert into list at spot 1 -// - change SearchText to the result -// - MoreCommands: a single `CopyCommand` to copy the result to the clipboard -// * The rest of the items are previously saved results -// - Command is a CopyCommand -// - Each item also sets the TextToSuggest to the result -[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "This is sample code")] -public sealed partial class CalculatorListPage : DynamicListPage -{ - private readonly List _items = []; - private readonly SaveCommand _saveCommand = new(); - private readonly CopyTextCommand _copyContextCommand; - private readonly CommandContextItem _copyContextMenuItem; - private static readonly CompositeFormat ErrorMessage = System.Text.CompositeFormat.Parse(Properties.Resources.calculator_error); - - public CalculatorListPage() - { - Icon = IconHelpers.FromRelativePath("Assets\\Calculator.svg"); - Name = Resources.calculator_title; - PlaceholderText = Resources.calculator_placeholder_text; - Id = "com.microsoft.cmdpal.calculator"; - - _copyContextCommand = new CopyTextCommand(string.Empty); - _copyContextMenuItem = new CommandContextItem(_copyContextCommand); - - _items.Add(new(_saveCommand) { Icon = new IconInfo("\uE94E") }); - - UpdateSearchText(string.Empty, string.Empty); - - _saveCommand.SaveRequested += HandleSave; - } - - private void HandleSave(object sender, object args) - { - var lastResult = _items[0].Title; - if (!string.IsNullOrEmpty(lastResult)) - { - var li = new ListItem(new CopyTextCommand(lastResult)) - { - Title = _items[0].Title, - Subtitle = _items[0].Subtitle, - TextToSuggest = lastResult, - }; - _items.Insert(1, li); - _items[0].Subtitle = string.Empty; - SearchText = lastResult; - this.RaiseItemsChanged(this._items.Count); - } - } - - public override void UpdateSearchText(string oldSearch, string newSearch) - { - var firstItem = _items[0]; - if (string.IsNullOrEmpty(newSearch)) - { - firstItem.Title = Resources.calculator_placeholder_text; - firstItem.Subtitle = string.Empty; - firstItem.MoreCommands = []; - } - else - { - _copyContextCommand.Text = ParseQuery(newSearch, out var result) ? result : string.Empty; - firstItem.Title = result; - firstItem.Subtitle = newSearch; - firstItem.MoreCommands = [_copyContextMenuItem]; - } - } - - internal static bool ParseQuery(string equation, out string result) - { - try - { - var resultNumber = new DataTable().Compute(equation, null); - result = resultNumber.ToString() ?? string.Empty; - return true; - } - catch (Exception e) - { - result = string.Format(CultureInfo.CurrentCulture, ErrorMessage, e.Message); - return false; - } - } - - public override IListItem[] GetItems() => _items.ToArray(); -} - -[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "This is sample code")] -public sealed partial class SaveCommand : InvokableCommand -{ - public event TypedEventHandler SaveRequested; - - public SaveCommand() - { - Name = Resources.calculator_save_command_name; - } - - public override ICommandResult Invoke() - { - SaveRequested?.Invoke(this, this); - return CommandResult.KeepOpen(); - } -} - -[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "This is sample code")] -internal sealed partial class FallbackCalculatorItem : FallbackCommandItem -{ - private readonly CopyTextCommand _copyCommand = new(string.Empty); - private static readonly IconInfo _cachedIcon = IconHelpers.FromRelativePath("Assets\\Calculator.svg"); - - public FallbackCalculatorItem() - : base(new NoOpCommand(), Resources.calculator_title) - { - Command = _copyCommand; - _copyCommand.Name = string.Empty; - Title = string.Empty; - Subtitle = Resources.calculator_placeholder_text; - Icon = _cachedIcon; - } - - public override void UpdateQuery(string query) - { - if (CalculatorListPage.ParseQuery(query, out var result)) - { - _copyCommand.Text = result; - _copyCommand.Name = string.IsNullOrWhiteSpace(query) ? string.Empty : Resources.calculator_copy_command_name; - Title = result; - - // we have to make the subtitle the equation, - // so that we will still string match the original query - // Otherwise, something like 1+2 will have a title of "3" and not match - Subtitle = query; - } - else - { - _copyCommand.Text = string.Empty; - _copyCommand.Name = string.Empty; - Title = string.Empty; - Subtitle = string.Empty; - } - } -} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/BracketHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/BracketHelper.cs new file mode 100644 index 0000000000..67d8940ed4 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/BracketHelper.cs @@ -0,0 +1,86 @@ +// 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.Collections.Generic; +using System.Linq; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +public static class BracketHelper +{ + public static bool IsBracketComplete(string query) + { + if (string.IsNullOrWhiteSpace(query)) + { + return true; + } + + var valueTuples = query + .Select(BracketTrail) + .Where(r => r != default); + + var trailTest = new Stack(); + + foreach (var (direction, type) in valueTuples) + { + switch (direction) + { + case TrailDirection.Open: + trailTest.Push(type); + break; + case TrailDirection.Close: + // Try to get item out of stack + if (!trailTest.TryPop(out var popped)) + { + return false; + } + + if (type != popped) + { + return false; + } + + continue; + default: + { + throw new ArgumentOutOfRangeException($"Can't process value (Parameter direction: {direction})"); + } + } + } + + return trailTest.Count == 0; + } + + private static (TrailDirection Direction, TrailType Type) BracketTrail(char @char) + { + switch (@char) + { + case '(': + return (TrailDirection.Open, TrailType.Round); + case ')': + return (TrailDirection.Close, TrailType.Round); + case '[': + return (TrailDirection.Open, TrailType.Bracket); + case ']': + return (TrailDirection.Close, TrailType.Bracket); + default: + return default; + } + } + + private enum TrailDirection + { + None, + Open, + Close, + } + + private enum TrailType + { + None, + Bracket, + Round, + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateEngine.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateEngine.cs new file mode 100644 index 0000000000..0d6f9536db --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateEngine.cs @@ -0,0 +1,127 @@ +// 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.Collections.Generic; +using System.Globalization; +using System.Text.RegularExpressions; + +using Mages.Core; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +public static class CalculateEngine +{ + private static readonly Engine _magesEngine = new Engine(new Configuration + { + Scope = new Dictionary + { + { "e", Math.E }, // e is not contained in the default mages engine + }, + }); + + public const int RoundingDigits = 10; + + public enum TrigMode + { + Radians, + Degrees, + Gradians, + } + + /// + /// Interpret + /// + /// Use CultureInfo.CurrentCulture if something is user facing + public static CalculateResult Interpret(SettingsManager settings, string input, CultureInfo cultureInfo, out string error) + { + error = default; + + if (!CalculateHelper.InputValid(input)) + { + return default; + } + + // check for division by zero + // We check if the string contains a slash followed by space (optional) and zero. Whereas the zero must not be followed by a dot, comma, 'b', 'o' or 'x' as these indicate a number with decimal digits or a binary/octal/hexadecimal value respectively. The zero must also not be followed by other digits. + if (new Regex("\\/\\s*0(?!(?:[,\\.0-9]|[box]0*[1-9a-f]))", RegexOptions.IgnoreCase).Match(input).Success) + { + error = Properties.Resources.calculator_division_by_zero; + return default; + } + + // mages has quirky log representation + // mage has log == ln vs log10 + input = input. + Replace("log(", "log10(", true, CultureInfo.CurrentCulture). + Replace("ln(", "log(", true, CultureInfo.CurrentCulture); + + input = CalculateHelper.FixHumanMultiplicationExpressions(input); + + // Get the user selected trigonometry unit + TrigMode trigMode = settings.TrigUnit; + + // Modify trig functions depending on angle unit setting + input = CalculateHelper.UpdateTrigFunctions(input, trigMode); + + // Expand conversions between trig units + input = CalculateHelper.ExpandTrigConversions(input, trigMode); + + var result = _magesEngine.Interpret(input); + + // This could happen for some incorrect queries, like pi(2) + if (result == null) + { + error = Properties.Resources.calculator_expression_not_complete; + return default; + } + + result = TransformResult(result); + if (result is string) + { + error = result as string; + return default; + } + + if (string.IsNullOrEmpty(result?.ToString())) + { + return default; + } + + var decimalResult = Convert.ToDecimal(result, cultureInfo); + var roundedResult = Round(decimalResult); + + return new CalculateResult() + { + Result = decimalResult, + RoundedResult = roundedResult, + }; + } + + public static decimal Round(decimal value) + { + return Math.Round(value, RoundingDigits, MidpointRounding.AwayFromZero); + } + + private static dynamic TransformResult(object result) + { + if (result.ToString() == "NaN") + { + return Properties.Resources.calculator_not_a_number; + } + + if (result is Function) + { + return Properties.Resources.calculator_expression_not_complete; + } + + if (result is double[,]) + { + // '[10,10]' is interpreted as array by mages engine + return Properties.Resources.calculator_double_array_returned; + } + + return result; + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateHelper.cs new file mode 100644 index 0000000000..acab3d7b96 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateHelper.cs @@ -0,0 +1,328 @@ +// 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.Text.RegularExpressions; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +public static class CalculateHelper +{ + private static readonly Regex RegValidExpressChar = new Regex( + @"^(" + + @"%|" + + @"ceil\s*\(|floor\s*\(|exp\s*\(|max\s*\(|min\s*\(|abs\s*\(|log(?:2|10)?\s*\(|ln\s*\(|sqrt\s*\(|pow\s*\(|" + + @"factorial\s*\(|sign\s*\(|round\s*\(|rand\s*\(\)|randi\s*\([^\)]|" + + @"sin\s*\(|cos\s*\(|tan\s*\(|arcsin\s*\(|arccos\s*\(|arctan\s*\(|" + + @"sinh\s*\(|cosh\s*\(|tanh\s*\(|arsinh\s*\(|arcosh\s*\(|artanh\s*\(|" + + @"rad\s*\(|deg\s*\(|grad\s*\(|" + /* trigonometry unit conversion macros */ + @"pi|" + + @"==|~=|&&|\|\||" + + @"((-?(\d+(\.\d*)?)|-?(\.\d+))[Ee](-?\d+))|" + /* expression from CheckScientificNotation between parenthesis */ + @"e|[0-9]|0[xX][0-9a-fA-F]+|0[bB][01]+|0[oO][0-7]+|[\+\-\*\/\^\., ""]|[\(\)\|\!\[\]]" + + @")+$", + RegexOptions.Compiled); + + private const string DegToRad = "(pi / 180) * "; + private const string DegToGrad = "(10 / 9) * "; + private const string GradToRad = "(pi / 200) * "; + private const string GradToDeg = "(9 / 10) * "; + private const string RadToDeg = "(180 / pi) * "; + private const string RadToGrad = "(200 / pi) * "; + + public static bool InputValid(string input) + { + if (string.IsNullOrWhiteSpace(input)) + { + throw new ArgumentNullException(paramName: nameof(input)); + } + + if (!RegValidExpressChar.IsMatch(input)) + { + return false; + } + + if (!BracketHelper.IsBracketComplete(input)) + { + return false; + } + + // If the input ends with a binary operator then it is not a valid input to mages and the Interpret function would throw an exception. Because we expect here that the user has not finished typing we block those inputs. + var trimmedInput = input.TrimEnd(); + if (trimmedInput.EndsWith('+') || trimmedInput.EndsWith('-') || trimmedInput.EndsWith('*') || trimmedInput.EndsWith('|') || trimmedInput.EndsWith('\\') || trimmedInput.EndsWith('^') || trimmedInput.EndsWith('=') || trimmedInput.EndsWith('&') || trimmedInput.EndsWith('/') || trimmedInput.EndsWith('%')) + { + return false; + } + + return true; + } + + public static string FixHumanMultiplicationExpressions(string input) + { + var output = CheckScientificNotation(input); + output = CheckNumberOrConstantThenParenthesisExpr(output); + output = CheckNumberOrConstantThenFunc(output); + output = CheckParenthesisExprThenFunc(output); + output = CheckParenthesisExprThenParenthesisExpr(output); + output = CheckNumberThenConstant(output); + output = CheckConstantThenConstant(output); + return output; + } + + private static string CheckScientificNotation(string input) + { + /** + * NOTE: By the time the expression gets to us, it's already in English format. + * + * Regex explanation: + * (-?(\d+({0}\d*)?)|-?({0}\d+)): Used to capture one of two types: + * -?(\d+({0}\d*)?): Captures a decimal number starting with a number (e.g. "-1.23") + * -?({0}\d+): Captures a decimal number without leading number (e.g. ".23") + * e: Captures 'e' or 'E' + * (-?\d+): Captures an integer number (e.g. "-1" or "23") + */ + var p = @"(-?(\d+(\.\d*)?)|-?(\.\d+))e(-?\d+)"; + return Regex.Replace(input, p, "($1 * 10^($5))", RegexOptions.IgnoreCase); + } + + /* + * num (exp) + * const (exp) + */ + private static string CheckNumberOrConstantThenParenthesisExpr(string input) + { + var output = input; + do + { + input = output; + output = Regex.Replace(input, @"(\d+|pi|e)\s*(\()", m => + { + if (m.Index > 0 && char.IsLetter(input[m.Index - 1])) + { + return m.Value; + } + + return $"{m.Groups[1].Value} * {m.Groups[2].Value}"; + }); + } + while (output != input); + + return output; + } + + /* + * num func + * const func + */ + private static string CheckNumberOrConstantThenFunc(string input) + { + var output = input; + do + { + input = output; + output = Regex.Replace(input, @"(\d+|pi|e)\s*([a-zA-Z]+[0-9]*\s*\()", m => + { + if (input[m.Index] == 'e' && input[m.Index + 1] == 'x' && input[m.Index + 2] == 'p') + { + return m.Value; + } + + if (m.Index > 0 && char.IsLetter(input[m.Index - 1])) + { + return m.Value; + } + + return $"{m.Groups[1].Value} * {m.Groups[2].Value}"; + }); + } + while (output != input); + + return output; + } + + /* + * (exp) func + * func func + */ + private static string CheckParenthesisExprThenFunc(string input) + { + var p = @"(\))\s*([a-zA-Z]+[0-9]*\s*\()"; + var r = "$1 * $2"; + return Regex.Replace(input, p, r); + } + + /* + * (exp) (exp) + * func (exp) + */ + private static string CheckParenthesisExprThenParenthesisExpr(string input) + { + var p = @"(\))\s*(\()"; + var r = "$1 * $2"; + return Regex.Replace(input, p, r); + } + + /* + * num const + */ + private static string CheckNumberThenConstant(string input) + { + var output = input; + do + { + input = output; + output = Regex.Replace(input, @"(\d+)\s*(pi|e)", m => + { + if (m.Index > 0 && char.IsLetter(input[m.Index - 1])) + { + return m.Value; + } + + return $"{m.Groups[1].Value} * {m.Groups[2].Value}"; + }); + } + while (output != input); + + return output; + } + + /* + * const const + */ + private static string CheckConstantThenConstant(string input) + { + var output = input; + do + { + input = output; + output = Regex.Replace(input, @"(pi|e)\s*(pi|e)", m => + { + if (m.Index > 0 && char.IsLetter(input[m.Index - 1])) + { + return m.Value; + } + + return $"{m.Groups[1].Value} * {m.Groups[2].Value}"; + }); + } + while (output != input); + + return output; + } + + // Gets the index of the closing bracket of a function + private static int FindClosingBracketIndex(string input, int start) + { + var bracketCount = 0; // Set count to zero + for (var i = start; i < input.Length; i++) + { + if (input[i] == '(') + { + bracketCount++; + } + else if (input[i] == ')') + { + bracketCount--; + if (bracketCount == 0) + { + return i; + } + } + } + + return -1; // Unmatched brackets + } + + private static string ModifyTrigFunction(string input, string function, string modification) + { + // Get the RegEx pattern to match, depending on whether the function is inverse or normal + var pattern = function.StartsWith("arc", StringComparison.Ordinal) ? string.Empty : @"(? +{ + public decimal? Result { get; set; } + + public decimal? RoundedResult { get; set; } + + public bool Equals(CalculateResult other) + { + return Result == other.Result && RoundedResult == other.RoundedResult; + } + + public override bool Equals(object obj) + { + return obj is CalculateResult other && Equals(other); + } + + public override int GetHashCode() + { + return HashCode.Combine(Result, RoundedResult); + } + + public static bool operator ==(CalculateResult left, CalculateResult right) + { + return left.Equals(right); + } + + public static bool operator !=(CalculateResult left, CalculateResult right) + { + return !(left == right); + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculatorIcons.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculatorIcons.cs new file mode 100644 index 0000000000..e3be5f2149 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculatorIcons.cs @@ -0,0 +1,18 @@ +// 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 Microsoft.CommandPalette.Extensions.Toolkit; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +public static class CalculatorIcons +{ + public static IconInfo ResultIcon => new("\uE94E"); + + public static IconInfo SaveIcon => new("\uE74E"); + + public static IconInfo ErrorIcon => new("\uE783"); + + public static IconInfo ProviderIcon => IconHelpers.FromRelativePath("Assets\\Calculator.svg"); +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ErrorHandler.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ErrorHandler.cs new file mode 100644 index 0000000000..b3948dc854 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ErrorHandler.cs @@ -0,0 +1,53 @@ +// 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.CommandPalette.Extensions.Toolkit; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +internal static class ErrorHandler +{ + /// + /// Method to handles errors while calculating + /// + /// Bool to indicate if it is a fallback query. + /// User input as string including the action keyword. + /// Error message if applicable. + /// Exception if applicable. + /// List of results to show. Either an error message or an empty list. + /// Thrown if and are both filled with their default values. + internal static ListItem OnError(bool isFallbackSearch, string queryInput, string errorMessage, Exception exception = default) + { + string userMessage; + + if (errorMessage != default) + { + Logger.LogError($"Failed to calculate <{queryInput}>: {errorMessage}"); + userMessage = errorMessage; + } + else if (exception != default) + { + Logger.LogError($"Exception when query for <{queryInput}>", exception); + userMessage = exception.Message; + } + else + { + throw new ArgumentException("The arguments error and exception have default values. One of them has to be filled with valid error data (error message/exception)!"); + } + + return isFallbackSearch ? null : CreateErrorResult(userMessage); + } + + private static ListItem CreateErrorResult(string errorMessage) + { + return new ListItem(new NoOpCommand()) + { + Title = Properties.Resources.calculator_calculation_failed_title, + Subtitle = errorMessage, + Icon = CalculatorIcons.ErrorIcon, + }; + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/NumberTranslator.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/NumberTranslator.cs new file mode 100644 index 0000000000..8de77ebdae --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/NumberTranslator.cs @@ -0,0 +1,144 @@ +// 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.Globalization; +using System.Text; +using System.Text.RegularExpressions; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +/// +/// Tries to convert all numbers in a text from one culture format to another. +/// +public class NumberTranslator +{ + private readonly CultureInfo sourceCulture; + private readonly CultureInfo targetCulture; + private readonly Regex splitRegexForSource; + private readonly Regex splitRegexForTarget; + + private NumberTranslator(CultureInfo sourceCulture, CultureInfo targetCulture) + { + this.sourceCulture = sourceCulture; + this.targetCulture = targetCulture; + + splitRegexForSource = GetSplitRegex(this.sourceCulture); + splitRegexForTarget = GetSplitRegex(this.targetCulture); + } + + /// + /// Create a new . + /// + /// source culture + /// target culture + /// Number translator for target culture + public static NumberTranslator Create(CultureInfo sourceCulture, CultureInfo targetCulture) + { + ArgumentNullException.ThrowIfNull(sourceCulture); + + ArgumentNullException.ThrowIfNull(targetCulture); + + return new NumberTranslator(sourceCulture, targetCulture); + } + + /// + /// Translate from source to target culture. + /// + /// input string to translate + /// translated string + public string Translate(string input) + { + return Translate(input, sourceCulture, targetCulture, splitRegexForSource); + } + + /// + /// Translate from target to source culture. + /// + /// input string to translate back to source culture + /// source culture string + public string TranslateBack(string input) + { + return Translate(input, targetCulture, sourceCulture, splitRegexForTarget); + } + + private static string Translate(string input, CultureInfo cultureFrom, CultureInfo cultureTo, Regex splitRegex) + { + var outputBuilder = new StringBuilder(); + var hexRegex = new Regex(@"(?:(0x[\da-fA-F]+))"); + + var hexTokens = hexRegex.Split(input); + + foreach (var hexToken in hexTokens) + { + if (hexToken.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase)) + { + // Mages engine has issues processing large hex number (larger than 7 hex digits + 0x prefix = 9 characters). So we convert it to decimal and pass it to the engine. + if (hexToken.Length > 9) + { + try + { + var num = Convert.ToInt64(hexToken, 16); + var numStr = num.ToString(cultureFrom); + outputBuilder.Append(numStr); + } + catch (Exception) + { + outputBuilder.Append(hexToken); + } + } + else + { + outputBuilder.Append(hexToken); + } + + continue; + } + + var tokens = splitRegex.Split(hexToken); + foreach (var token in tokens) + { + var leadingZeroCount = 0; + + // Count leading zero characters. + foreach (var c in token) + { + if (c != '0') + { + break; + } + + leadingZeroCount++; + } + + // number is all zero characters. no need to add zero characters at the end. + if (token.Length == leadingZeroCount) + { + leadingZeroCount = 0; + } + + decimal number; + + outputBuilder.Append( + decimal.TryParse(token, NumberStyles.Number, cultureFrom, out number) + ? (new string('0', leadingZeroCount) + number.ToString(cultureTo)) + : token.Replace(cultureFrom.TextInfo.ListSeparator, cultureTo.TextInfo.ListSeparator)); + } + } + + return outputBuilder.ToString(); + } + + private static Regex GetSplitRegex(CultureInfo culture) + { + var splitPattern = $"((?:\\d|{Regex.Escape(culture.NumberFormat.NumberDecimalSeparator)}"; + if (!string.IsNullOrEmpty(culture.NumberFormat.NumberGroupSeparator)) + { + splitPattern += $"|{Regex.Escape(culture.NumberFormat.NumberGroupSeparator)}"; + } + + splitPattern += ")+)"; + return new Regex(splitPattern); + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/QueryHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/QueryHelper.cs new file mode 100644 index 0000000000..6b1e62ae03 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/QueryHelper.cs @@ -0,0 +1,77 @@ +// 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.Globalization; +using System.Text; +using Microsoft.CommandPalette.Extensions.Toolkit; +using Windows.Foundation; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +public static partial class QueryHelper +{ + public static ListItem Query(string query, SettingsManager settings, bool isFallbackSearch, TypedEventHandler handleSave = null) + { + ArgumentNullException.ThrowIfNull(query); + if (!isFallbackSearch) + { + ArgumentNullException.ThrowIfNull(handleSave); + } + + CultureInfo inputCulture = settings.InputUseEnglishFormat ? new CultureInfo("en-us") : CultureInfo.CurrentCulture; + CultureInfo outputCulture = settings.OutputUseEnglishFormat ? new CultureInfo("en-us") : CultureInfo.CurrentCulture; + + // Happens if the user has only typed the action key so far + if (string.IsNullOrEmpty(query)) + { + return null; + } + + NumberTranslator translator = NumberTranslator.Create(inputCulture, new CultureInfo("en-US")); + var input = translator.Translate(query.Normalize(NormalizationForm.FormKC)); + + if (!CalculateHelper.InputValid(input)) + { + return null; + } + + try + { + // Using CurrentUICulture since this is user facing + var result = CalculateEngine.Interpret(settings, input, outputCulture, out var errorMessage); + + // This could happen for some incorrect queries, like pi(2) + if (result.Equals(default(CalculateResult))) + { + // If errorMessage is not default then do error handling + return errorMessage == default ? null : ErrorHandler.OnError(isFallbackSearch, query, errorMessage); + } + + if (isFallbackSearch) + { + // Fallback search + return ResultHelper.CreateResult(result.RoundedResult, inputCulture, outputCulture, query); + } + + return ResultHelper.CreateResult(result.RoundedResult, inputCulture, outputCulture, query, handleSave); + } + catch (Mages.Core.ParseException) + { + // Invalid input + return ErrorHandler.OnError(isFallbackSearch, query, Properties.Resources.calculator_expression_not_complete); + } + catch (OverflowException) + { + // Result to big to convert to decimal + return ErrorHandler.OnError(isFallbackSearch, query, Properties.Resources.calculator_not_covert_to_decimal); + } + catch (Exception e) + { + // Any other crash occurred + // We want to keep the process alive if any the mages library throws any exceptions. + return ErrorHandler.OnError(isFallbackSearch, query, default, e); + } + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs new file mode 100644 index 0000000000..0fab0a8245 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/ResultHelper.cs @@ -0,0 +1,103 @@ +// 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.Collections.Generic; +using System.Globalization; +using ManagedCommon; +using Microsoft.CommandPalette.Extensions.Toolkit; +using Windows.Foundation; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +public static class ResultHelper +{ + public static ListItem CreateResult(decimal? roundedResult, CultureInfo inputCulture, CultureInfo outputCulture, string query, TypedEventHandler handleSave) + { + // Return null when the expression is not a valid calculator query. + if (roundedResult == null) + { + return null; + } + + var result = roundedResult?.ToString(outputCulture); + + // Create a SaveCommand and subscribe to the SaveRequested event + // This can append the result to the history list. + var saveCommand = new SaveCommand(result); + saveCommand.SaveRequested += handleSave; + + var copyCommandItem = CreateResult(roundedResult, inputCulture, outputCulture, query); + + return new ListItem(saveCommand) + { + // Using CurrentCulture since this is user facing + Icon = CalculatorIcons.ResultIcon, + Title = result, + Subtitle = query, + TextToSuggest = result, + MoreCommands = [ + new CommandContextItem(copyCommandItem.Command) + { + Icon = copyCommandItem.Icon, + Title = copyCommandItem.Title, + Subtitle = copyCommandItem.Subtitle, + }, + ..copyCommandItem.MoreCommands, + ], + }; + } + + public static ListItem CreateResult(decimal? roundedResult, CultureInfo inputCulture, CultureInfo outputCulture, string query) + { + // Return null when the expression is not a valid calculator query. + if (roundedResult == null) + { + return null; + } + + var decimalResult = roundedResult?.ToString(outputCulture); + + List context = []; + + if (decimal.IsInteger((decimal)roundedResult)) + { + var i = decimal.ToInt64((decimal)roundedResult); + try + { + var hexResult = "0x" + i.ToString("X", outputCulture); + context.Add(new CommandContextItem(new CopyTextCommand(hexResult) { Name = Properties.Resources.calculator_copy_hex }) + { + Title = hexResult, + }); + } + catch (Exception ex) + { + Logger.LogError("Error parsing hex format", ex); + } + + try + { + var binaryResult = "0b" + i.ToString("B", outputCulture); + context.Add(new CommandContextItem(new CopyTextCommand(binaryResult) { Name = Properties.Resources.calculator_copy_binary }) + { + Title = binaryResult, + }); + } + catch (Exception ex) + { + Logger.LogError("Error parsing binary format", ex); + } + } + + return new ListItem(new CopyTextCommand(decimalResult)) + { + // Using CurrentCulture since this is user facing + Title = decimalResult, + Subtitle = query, + TextToSuggest = decimalResult, + MoreCommands = context.ToArray(), + }; + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SaveCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SaveCommand.cs new file mode 100644 index 0000000000..850f8511e3 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SaveCommand.cs @@ -0,0 +1,31 @@ +// 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 Microsoft.CmdPal.Ext.Calc.Properties; +using Microsoft.CommandPalette.Extensions; +using Microsoft.CommandPalette.Extensions.Toolkit; +using Windows.Foundation; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +public sealed partial class SaveCommand : InvokableCommand +{ + private readonly string _result; + + public event TypedEventHandler SaveRequested; + + public SaveCommand(string result) + { + Name = Resources.calculator_save_command_name; + Icon = CalculatorIcons.SaveIcon; + _result = result; + } + + public override ICommandResult Invoke() + { + SaveRequested?.Invoke(this, this); + ClipboardHelper.SetText(_result); + return CommandResult.KeepOpen(); + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SettingsManager.cs new file mode 100644 index 0000000000..e106123f5e --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/SettingsManager.cs @@ -0,0 +1,98 @@ +// 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.Collections.Generic; +using System.IO; +using Microsoft.CommandPalette.Extensions.Toolkit; + +namespace Microsoft.CmdPal.Ext.Calc.Helper; + +public class SettingsManager : JsonSettingsManager +{ + private static readonly string _namespace = "calculator"; + + private static string Namespaced(string propertyName) => $"{_namespace}.{propertyName}"; + + private static readonly List _trigUnitChoices = new() + { + new ChoiceSetSetting.Choice(Properties.Resources.calculator_settings_trig_unit_radians, "0"), + new ChoiceSetSetting.Choice(Properties.Resources.calculator_settings_trig_unit_degrees, "1"), + new ChoiceSetSetting.Choice(Properties.Resources.calculator_settings_trig_unit_gradians, "2"), + }; + + private readonly ChoiceSetSetting _trigUnit = new( + Namespaced(nameof(TrigUnit)), + Properties.Resources.calculator_settings_trig_unit_mode, + Properties.Resources.calculator_settings_trig_unit_mode_description, + _trigUnitChoices); + + private readonly ToggleSetting _inputUseEnNumberFormat = new( + Namespaced(nameof(InputUseEnglishFormat)), + Properties.Resources.calculator_settings_in_en_format, + Properties.Resources.calculator_settings_in_en_format_description, + false); + + private readonly ToggleSetting _outputUseEnNumberFormat = new( + Namespaced(nameof(OutputUseEnglishFormat)), + Properties.Resources.calculator_settings_out_en_format, + Properties.Resources.calculator_settings_out_en_format_description, + false); + + public CalculateEngine.TrigMode TrigUnit + { + get + { + if (_trigUnit.Value == null || string.IsNullOrEmpty(_trigUnit.Value)) + { + return CalculateEngine.TrigMode.Radians; + } + + var success = int.TryParse(_trigUnit.Value, out var result); + + if (!success) + { + return CalculateEngine.TrigMode.Radians; + } + + switch (result) + { + case 0: + return CalculateEngine.TrigMode.Radians; + case 1: + return CalculateEngine.TrigMode.Degrees; + case 2: + return CalculateEngine.TrigMode.Gradians; + default: + return CalculateEngine.TrigMode.Radians; + } + } + } + + public bool InputUseEnglishFormat => _inputUseEnNumberFormat.Value; + + public bool OutputUseEnglishFormat => _outputUseEnNumberFormat.Value; + + internal static string SettingsJsonPath() + { + var directory = Utilities.BaseSettingsPath("Microsoft.CmdPal"); + Directory.CreateDirectory(directory); + + // now, the state is just next to the exe + return Path.Combine(directory, "settings.json"); + } + + public SettingsManager() + { + FilePath = SettingsJsonPath(); + + Settings.Add(_trigUnit); + Settings.Add(_inputUseEnNumberFormat); + Settings.Add(_outputUseEnNumberFormat); + + // Load settings from file upon initialization + LoadSettings(); + + Settings.SettingsChanged += (s, a) => this.SaveSettings(); + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj index 68a38c1ca2..85f06768ce 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Microsoft.CmdPal.Ext.Calc.csproj @@ -9,9 +9,14 @@ Microsoft.CmdPal.Ext.Calc.pri + + + + + Resources.resx diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs new file mode 100644 index 0000000000..24f26646c5 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/CalculatorListPage.cs @@ -0,0 +1,127 @@ +// 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.Collections.Generic; +using System.Threading; +using Microsoft.CmdPal.Ext.Calc.Helper; +using Microsoft.CmdPal.Ext.Calc.Properties; +using Microsoft.CommandPalette.Extensions; +using Microsoft.CommandPalette.Extensions.Toolkit; + +namespace Microsoft.CmdPal.Ext.Calc.Pages; + +// The calculator page is a dynamic list page +// * The first command is where we display the results. Title=result, Subtitle=query +// - The default command is `SaveCommand`. +// - When you save, insert into list at spot 1 +// - change SearchText to the result +// - MoreCommands: a single `CopyCommand` to copy the result to the clipboard +// * The rest of the items are previously saved results +// - Command is a CopyCommand +// - Each item also sets the TextToSuggest to the result +public sealed partial class CalculatorListPage : DynamicListPage +{ + private readonly Lock _resultsLock = new(); + private readonly SettingsManager _settingsManager; + private readonly List _items = []; + private readonly List history = []; + private readonly ListItem _emptyItem; + + // This is the text that saved when the user click the result. + // We need to avoid the double calculation. This may cause some wierd behaviors. + private string skipQuerySearchText = string.Empty; + + public CalculatorListPage(SettingsManager settings) + { + _settingsManager = settings; + Icon = CalculatorIcons.ProviderIcon; + Name = Resources.calculator_title; + PlaceholderText = Resources.calculator_placeholder_text; + Id = "com.microsoft.cmdpal.calculator"; + + _emptyItem = new ListItem(new NoOpCommand()) + { + Title = Resources.calculator_placeholder_text, + Icon = CalculatorIcons.ResultIcon, + }; + EmptyContent = new CommandItem(new NoOpCommand()) + { + Icon = CalculatorIcons.ProviderIcon, + Title = Resources.calculator_placeholder_text, + }; + + UpdateSearchText(string.Empty, string.Empty); + } + + public override void UpdateSearchText(string oldSearch, string newSearch) + { + if (oldSearch == newSearch) + { + return; + } + + if (!string.IsNullOrEmpty(skipQuerySearchText) && newSearch == skipQuerySearchText) + { + // only skip once. + skipQuerySearchText = string.Empty; + return; + } + + skipQuerySearchText = string.Empty; + + _emptyItem.Subtitle = newSearch; + + var result = QueryHelper.Query(newSearch, _settingsManager, false, HandleSave); + UpdateResult(result); + } + + private void UpdateResult(ListItem result) + { + lock (_resultsLock) + { + this._items.Clear(); + + if (result != null) + { + this._items.Add(result); + } + else + { + _items.Add(_emptyItem); + } + + this._items.AddRange(history); + } + + RaiseItemsChanged(this._items.Count); + } + + private void HandleSave(object sender, object args) + { + var lastResult = _items[0].Title; + if (!string.IsNullOrEmpty(lastResult)) + { + var li = new ListItem(new CopyTextCommand(lastResult)) + { + Title = _items[0].Title, + Subtitle = _items[0].Subtitle, + TextToSuggest = lastResult, + }; + + history.Insert(0, li); + _items.Insert(1, li); + + // Why we need to clean the query record? Removed, but if necessary, please move it back. + // _items[0].Subtitle = string.Empty; + + // this change will call the UpdateSearchText again. + // We need to avoid it. + skipQuerySearchText = lastResult; + SearchText = lastResult; + this.RaiseItemsChanged(this._items.Count); + } + } + + public override IListItem[] GetItems() => _items.ToArray(); +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs new file mode 100644 index 0000000000..b309f4ed3a --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Pages/FallbackCalculatorItem.cs @@ -0,0 +1,52 @@ +// 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 Microsoft.CmdPal.Ext.Calc.Helper; +using Microsoft.CmdPal.Ext.Calc.Properties; +using Microsoft.CommandPalette.Extensions.Toolkit; + +namespace Microsoft.CmdPal.Ext.Calc.Pages; + +public sealed partial class FallbackCalculatorItem : FallbackCommandItem +{ + private readonly CopyTextCommand _copyCommand = new(string.Empty); + private readonly SettingsManager _settings; + + public FallbackCalculatorItem(SettingsManager settings) + : base(new NoOpCommand(), Resources.calculator_title) + { + Command = _copyCommand; + _copyCommand.Name = string.Empty; + Title = string.Empty; + Subtitle = Resources.calculator_placeholder_text; + Icon = CalculatorIcons.ProviderIcon; + _settings = settings; + } + + public override void UpdateQuery(string query) + { + var result = QueryHelper.Query(query, _settings, true, null); + + if (result == null) + { + _copyCommand.Text = string.Empty; + _copyCommand.Name = string.Empty; + Title = string.Empty; + Subtitle = string.Empty; + MoreCommands = []; + return; + } + + _copyCommand.Text = result.Title; + _copyCommand.Name = string.IsNullOrWhiteSpace(query) ? string.Empty : Resources.calculator_copy_command_name; + Title = result.Title; + + // we have to make the subtitle the equation, + // so that we will still string match the original query + // Otherwise, something like 1+2 will have a title of "3" and not match + Subtitle = query; + + MoreCommands = result.MoreCommands; + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.Designer.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.Designer.cs index 72fdb55d3b..8cd385be32 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.Designer.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.Designer.cs @@ -60,6 +60,24 @@ namespace Microsoft.CmdPal.Ext.Calc.Properties { } } + /// + /// Looks up a localized string similar to Failed to calculate the input. + /// + public static string calculator_calculation_failed_title { + get { + return ResourceManager.GetString("calculator_calculation_failed_title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Copy binary. + /// + public static string calculator_copy_binary { + get { + return ResourceManager.GetString("calculator_copy_binary", resourceCulture); + } + } + /// /// Looks up a localized string similar to Copy. /// @@ -69,6 +87,15 @@ namespace Microsoft.CmdPal.Ext.Calc.Properties { } } + /// + /// Looks up a localized string similar to Copy hexadecimal. + /// + public static string calculator_copy_hex { + get { + return ResourceManager.GetString("calculator_copy_hex", resourceCulture); + } + } + /// /// Looks up a localized string similar to Calculator. /// @@ -78,6 +105,24 @@ namespace Microsoft.CmdPal.Ext.Calc.Properties { } } + /// + /// Looks up a localized string similar to Expression contains division by zero. + /// + public static string calculator_division_by_zero { + get { + return ResourceManager.GetString("calculator_division_by_zero", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unsupported use of square brackets. + /// + public static string calculator_double_array_returned { + get { + return ResourceManager.GetString("calculator_double_array_returned", resourceCulture); + } + } + /// /// Looks up a localized string similar to Error: {0}. /// @@ -87,6 +132,33 @@ namespace Microsoft.CmdPal.Ext.Calc.Properties { } } + /// + /// Looks up a localized string similar to Expression wrong or incomplete. + /// + public static string calculator_expression_not_complete { + get { + return ResourceManager.GetString("calculator_expression_not_complete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Calculation result is not a valid number (NaN). + /// + public static string calculator_not_a_number { + get { + return ResourceManager.GetString("calculator_not_a_number", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Result value was either too large or too small for a decimal number. + /// + public static string calculator_not_covert_to_decimal { + get { + return ResourceManager.GetString("calculator_not_covert_to_decimal", resourceCulture); + } + } + /// /// Looks up a localized string similar to Type an equation.... /// @@ -105,6 +177,105 @@ namespace Microsoft.CmdPal.Ext.Calc.Properties { } } + /// + /// Looks up a localized string similar to Use English (United States) number format for input. + /// + public static string calculator_settings_in_en_format { + get { + return ResourceManager.GetString("calculator_settings_in_en_format", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ignores your system setting and expects numbers in the format '{0}'.. + /// + public static string calculator_settings_in_en_format_description { + get { + return ResourceManager.GetString("calculator_settings_in_en_format_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use English (United States) number format for output. + /// + public static string calculator_settings_out_en_format { + get { + return ResourceManager.GetString("calculator_settings_out_en_format", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Ignores your system setting and returns numbers in the format '{0}'.. + /// + public static string calculator_settings_out_en_format_description { + get { + return ResourceManager.GetString("calculator_settings_out_en_format_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Replace input if query ends with '='. + /// + public static string calculator_settings_replace_input { + get { + return ResourceManager.GetString("calculator_settings_replace_input", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to When using direct activation, appending '=' to the expression will replace the input with the calculated result (e.g. '=5*3-2=' will change the query to '=13').. + /// + public static string calculator_settings_replace_input_description { + get { + return ResourceManager.GetString("calculator_settings_replace_input_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Degrees. + /// + public static string calculator_settings_trig_unit_degrees { + get { + return ResourceManager.GetString("calculator_settings_trig_unit_degrees", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Gradians. + /// + public static string calculator_settings_trig_unit_gradians { + get { + return ResourceManager.GetString("calculator_settings_trig_unit_gradians", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Trigonometry Unit. + /// + public static string calculator_settings_trig_unit_mode { + get { + return ResourceManager.GetString("calculator_settings_trig_unit_mode", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specifies the angle unit to use for trigonometry operations. + /// + public static string calculator_settings_trig_unit_mode_description { + get { + return ResourceManager.GetString("calculator_settings_trig_unit_mode_description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Radians. + /// + public static string calculator_settings_trig_unit_radians { + get { + return ResourceManager.GetString("calculator_settings_trig_unit_radians", resourceCulture); + } + } + /// /// Looks up a localized string similar to Calculator. /// diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.resx b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.resx index 580f704433..3c50d3a1c5 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.resx +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Properties/Resources.resx @@ -140,4 +140,63 @@ Copy + + Failed to calculate the input + + + Expression contains division by zero + + + Expression wrong or incomplete + + + Calculation result is not a valid number (NaN) + + + Unsupported use of square brackets + + + Gradians + + + Degrees + + + Radians + + + Trigonometry Unit + + + Specifies the angle unit to use for trigonometry operations + + + Use English (United States) number format for output + + + Ignores your system setting and returns numbers in the format '{0}'. + {0} is a placeholder and will be replaced in code. + + + Use English (United States) number format for input + + + Ignores your system setting and expects numbers in the format '{0}'. + {0} is a placeholder and will be replaced in code. + + + Replace input if query ends with '=' + + + When using direct activation, appending '=' to the expression will replace the input with the calculated result (e.g. '=5*3-2=' will change the query to '=13'). + + + Result value was either too large or too small for a decimal number + + + Copy hexadecimal + + + Copy binary + \ No newline at end of file From 05218e8af6bfc24709dba8ca184e346b81bb3a36 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Thu, 17 Apr 2025 06:13:11 -0500 Subject: [PATCH 35/70] Add the list item requested shortcuts back (#38573) * [x] Re-adds the context menu shortcut text * [x] Hooks up the keybindings to the search box so that you can just press the keys while you have an item selected, and do a context command * [x] Hook these keybindings up to the context flyout itself * [x] Adds a sample for testing Solves #38271 --- .../CommandBarViewModel.cs | 29 +++++- .../CommandContextItemViewModel.cs | 7 ++ .../CommandItemViewModel.cs | 17 ++++ .../ListViewModel.cs | 2 + .../Messages/PerformCommandMessage.cs | 6 ++ .../Messages/UpdateItemKeybindingsMessage.cs | 9 ++ .../Controls/CommandBar.xaml | 5 +- .../Controls/CommandBar.xaml.cs | 22 +++++ .../Controls/SearchBar.xaml.cs | 28 +++++- .../Pages/ShellPage.xaml.cs | 4 +- .../SamplePagesExtension/NativeMethods.txt | 3 + .../Pages/SampleListPage.cs | 94 ++++++++++++++++++- .../SamplePagesExtension.csproj | 6 ++ .../KeyChordHelpers.cs | 20 +++- 14 files changed, 243 insertions(+), 9 deletions(-) create mode 100644 src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/UpdateItemKeybindingsMessage.cs create mode 100644 src/modules/cmdpal/ext/SamplePagesExtension/NativeMethods.txt diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandBarViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandBarViewModel.cs index 9b5be8a973..420f41f49f 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandBarViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandBarViewModel.cs @@ -7,11 +7,15 @@ using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CommunityToolkit.Mvvm.Messaging; using Microsoft.CmdPal.UI.ViewModels.Messages; +using Microsoft.CommandPalette.Extensions; +using Microsoft.CommandPalette.Extensions.Toolkit; +using Windows.System; namespace Microsoft.CmdPal.UI.ViewModels; public partial class CommandBarViewModel : ObservableObject, - IRecipient + IRecipient, + IRecipient { public ICommandBarContext? SelectedItem { @@ -49,13 +53,18 @@ public partial class CommandBarViewModel : ObservableObject, [ObservableProperty] public partial ObservableCollection ContextCommands { get; set; } = []; + private Dictionary? _contextKeybindings; + public CommandBarViewModel() { WeakReferenceMessenger.Default.Register(this); + WeakReferenceMessenger.Default.Register(this); } public void Receive(UpdateCommandBarMessage message) => SelectedItem = message.ViewModel; + public void Receive(UpdateItemKeybindingsMessage message) => _contextKeybindings = message.Keys; + private void SetSelectedItem(ICommandBarContext? value) { if (value != null) @@ -131,4 +140,22 @@ public partial class CommandBarViewModel : ObservableObject, WeakReferenceMessenger.Default.Send(new(SecondaryCommand.Command.Model, SecondaryCommand.Model)); } } + + public bool CheckKeybinding(bool ctrl, bool alt, bool shift, bool win, VirtualKey key) + { + if (_contextKeybindings != null) + { + // Does the pressed key match any of the keybindings? + var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrl, alt, shift, win, key, 0); + if (_contextKeybindings.TryGetValue(pressedKeyChord, out var item)) + { + // TODO GH #245: This is a bit of a hack, but we need to make sure that the keybindings are updated before we send the message + // so that the correct item is activated. + WeakReferenceMessenger.Default.Send(new(item)); + return true; + } + } + + return false; + } } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandContextItemViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandContextItemViewModel.cs index f3475fd964..dfbb1a982a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandContextItemViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandContextItemViewModel.cs @@ -9,12 +9,16 @@ namespace Microsoft.CmdPal.UI.ViewModels; public partial class CommandContextItemViewModel(ICommandContextItem contextItem, WeakReference context) : CommandItemViewModel(new(contextItem), context) { + private readonly KeyChord nullKeyChord = new(0, 0, 0); + public new ExtensionObject Model { get; } = new(contextItem); public bool IsCritical { get; private set; } public KeyChord? RequestedShortcut { get; private set; } + public bool HasRequestedShortcut => RequestedShortcut != null && (RequestedShortcut.Value != nullKeyChord); + public override void InitializeProperties() { if (IsInitialized) @@ -31,6 +35,9 @@ public partial class CommandContextItemViewModel(ICommandContextItem contextItem } IsCritical = contextItem.IsCritical; + + // I actually don't think this will ever actually be null, because + // KeyChord is a struct, which isn't nullable in WinRT if (contextItem.RequestedShortcut != null) { RequestedShortcut = new( diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandItemViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandItemViewModel.cs index 37d223b000..8634b63278 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandItemViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/CommandItemViewModel.cs @@ -398,6 +398,23 @@ public partial class CommandItemViewModel : ExtensionObjectViewModel, ICommandBa base.SafeCleanup(); Initialized |= InitializedState.CleanedUp; } + + /// + /// Generates a mapping of key -> command item for this particular item's + /// MoreCommands. (This won't include the primary Command, but it will + /// include the secondary one). This map can be used to quickly check if a + /// shortcut key was pressed + /// + /// a dictionary of KeyChord -> Context commands, for all commands + /// that have a shortcut key set. + internal Dictionary Keybindings() + { + return MoreCommands + .Where(c => c.HasRequestedShortcut) + .ToDictionary( + c => c.RequestedShortcut ?? new KeyChord(0, 0, 0), + c => c); + } } [Flags] diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ListViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ListViewModel.cs index c448745743..b45ea08f54 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ListViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ListViewModel.cs @@ -344,6 +344,8 @@ public partial class ListViewModel : PageViewModel, IDisposable { WeakReferenceMessenger.Default.Send(new(item)); + WeakReferenceMessenger.Default.Send(new(item.Keybindings())); + if (ShowDetails && item.HasDetails) { WeakReferenceMessenger.Default.Send(new(item.Details)); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/PerformCommandMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/PerformCommandMessage.cs index 9bc0c730e8..b0e5e4829a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/PerformCommandMessage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/PerformCommandMessage.cs @@ -51,6 +51,12 @@ public record PerformCommandMessage Context = context.Unsafe; } + public PerformCommandMessage(CommandContextItemViewModel contextCommand) + { + Command = contextCommand.Command.Model; + Context = contextCommand.Model.Unsafe; + } + public PerformCommandMessage(ConfirmResultViewModel vm) { Command = vm.PrimaryCommand.Model; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/UpdateItemKeybindingsMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/UpdateItemKeybindingsMessage.cs new file mode 100644 index 0000000000..2054d3d8fd --- /dev/null +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Messages/UpdateItemKeybindingsMessage.cs @@ -0,0 +1,9 @@ +// 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 Microsoft.CommandPalette.Extensions; + +namespace Microsoft.CmdPal.UI.ViewModels.Messages; + +public record UpdateItemKeybindingsMessage(Dictionary? Keys); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml index 9f7b4d4071..4a692fcc20 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml @@ -53,14 +53,14 @@ Grid.Column="1" VerticalAlignment="Center" Text="{x:Bind Title, Mode=OneWay}" /> - + Text="{x:Bind RequestedShortcut, Mode=OneWay, Converter={StaticResource KeyChordToStringConverter}}" /> @@ -263,6 +263,7 @@ ItemClick="CommandsDropdown_ItemClick" ItemTemplate="{StaticResource ContextMenuViewModelTemplate}" ItemsSource="{x:Bind ViewModel.ContextCommands, Mode=OneWay}" + KeyDown="CommandsDropdown_KeyDown" SelectionMode="None"> - - - - - + + + + + + + + + + + + + + + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml.cs index e8ca659097..f079f4b513 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/CommandBar.xaml.cs @@ -18,9 +18,10 @@ namespace Microsoft.CmdPal.UI.Controls; public sealed partial class CommandBar : UserControl, IRecipient, + IRecipient, ICurrentPageAware { - public CommandBarViewModel ViewModel { get; set; } = new(); + public CommandBarViewModel ViewModel { get; } = new(); public PageViewModel? CurrentPageViewModel { @@ -38,6 +39,9 @@ public sealed partial class CommandBar : UserControl, // RegisterAll isn't AOT compatible WeakReferenceMessenger.Default.Register(this); + WeakReferenceMessenger.Default.Register(this); + + ViewModel.PropertyChanged += ViewModel_PropertyChanged; } public void Receive(OpenContextMenuMessage message) @@ -52,8 +56,41 @@ public sealed partial class CommandBar : UserControl, ShowMode = FlyoutShowMode.Standard, }; MoreCommandsButton.Flyout.ShowAt(MoreCommandsButton, options); - CommandsDropdown.SelectedIndex = 0; - CommandsDropdown.Focus(FocusState.Programmatic); + UpdateUiForStackChange(); + } + + public void Receive(TryCommandKeybindingMessage msg) + { + if (!ViewModel.ShouldShowContextMenu) + { + return; + } + + var result = ViewModel?.CheckKeybinding(msg.Ctrl, msg.Alt, msg.Shift, msg.Win, msg.Key); + + if (result == ContextKeybindingResult.Hide) + { + msg.Handled = true; + } + else if (result == ContextKeybindingResult.KeepOpen) + { + if (!MoreCommandsButton.Flyout.IsOpen) + { + var options = new FlyoutShowOptions + { + ShowMode = FlyoutShowMode.Standard, + }; + MoreCommandsButton.Flyout.ShowAt(MoreCommandsButton, options); + } + + UpdateUiForStackChange(); + + msg.Handled = true; + } + else if (result == ContextKeybindingResult.Unhandled) + { + msg.Handled = false; + } } [System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0051:Remove unused private members", Justification = "VS has a tendency to delete XAML bound methods over-aggressively")] @@ -88,8 +125,14 @@ public sealed partial class CommandBar : UserControl, { if (e.ClickedItem is CommandContextItemViewModel item) { - ViewModel?.InvokeItemCommand.Execute(item); - MoreCommandsButton.Flyout.Hide(); + if (ViewModel?.InvokeItem(item) == ContextKeybindingResult.Hide) + { + MoreCommandsButton.Flyout.Hide(); + } + else + { + UpdateUiForStackChange(); + } } } @@ -106,9 +149,136 @@ public sealed partial class CommandBar : UserControl, var winPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.LeftWindows).HasFlag(CoreVirtualKeyStates.Down) || InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.RightWindows).HasFlag(CoreVirtualKeyStates.Down); - if (ViewModel?.CheckKeybinding(ctrlPressed, altPressed, shiftPressed, winPressed, e.Key) ?? false) + var result = ViewModel?.CheckKeybinding(ctrlPressed, altPressed, shiftPressed, winPressed, e.Key); + + if (result == ContextKeybindingResult.Hide) + { + e.Handled = true; + MoreCommandsButton.Flyout.Hide(); + WeakReferenceMessenger.Default.Send(); + } + else if (result == ContextKeybindingResult.KeepOpen) { e.Handled = true; } + else if (result == ContextKeybindingResult.Unhandled) + { + e.Handled = false; + } + } + + private void Flyout_Opened(object sender, object e) + { + UpdateUiForStackChange(); + } + + private void Flyout_Closing(FlyoutBase sender, FlyoutBaseClosingEventArgs args) + { + ViewModel?.ClearContextStack(); + WeakReferenceMessenger.Default.Send(); + } + + private void ViewModel_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) + { + var prop = e.PropertyName; + if (prop == nameof(ViewModel.ContextMenu)) + { + UpdateUiForStackChange(); + } + } + + private void ContextFilterBox_TextChanged(object sender, TextChangedEventArgs e) + { + ViewModel.ContextMenu?.SetSearchText(ContextFilterBox.Text); + + if (CommandsDropdown.SelectedIndex == -1) + { + CommandsDropdown.SelectedIndex = 0; + } + } + + private void ContextFilterBox_KeyDown(object sender, KeyRoutedEventArgs e) + { + var ctrlPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Control).HasFlag(CoreVirtualKeyStates.Down); + var altPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Menu).HasFlag(CoreVirtualKeyStates.Down); + var shiftPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.Shift).HasFlag(CoreVirtualKeyStates.Down); + var winPressed = InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.LeftWindows).HasFlag(CoreVirtualKeyStates.Down) || + InputKeyboardSource.GetKeyStateForCurrentThread(VirtualKey.RightWindows).HasFlag(CoreVirtualKeyStates.Down); + + if (e.Key == VirtualKey.Enter) + { + if (CommandsDropdown.SelectedItem is CommandContextItemViewModel item) + { + if (ViewModel?.InvokeItem(item) == ContextKeybindingResult.Hide) + { + MoreCommandsButton.Flyout.Hide(); + WeakReferenceMessenger.Default.Send(); + } + else + { + UpdateUiForStackChange(); + } + + e.Handled = true; + } + } + else if (e.Key == VirtualKey.Escape || + (e.Key == VirtualKey.Left && altPressed)) + { + if (ViewModel.CanPopContextStack()) + { + ViewModel.PopContextStack(); + UpdateUiForStackChange(); + } + else + { + MoreCommandsButton.Flyout.Hide(); + WeakReferenceMessenger.Default.Send(); + } + + e.Handled = true; + } + + CommandsDropdown_KeyDown(sender, e); + } + + private void ContextFilterBox_PreviewKeyDown(object sender, KeyRoutedEventArgs e) + { + if (e.Key == VirtualKey.Up) + { + // navigate previous + if (CommandsDropdown.SelectedIndex > 0) + { + CommandsDropdown.SelectedIndex--; + } + else + { + CommandsDropdown.SelectedIndex = CommandsDropdown.Items.Count - 1; + } + + e.Handled = true; + } + else if (e.Key == VirtualKey.Down) + { + // navigate next + if (CommandsDropdown.SelectedIndex < CommandsDropdown.Items.Count - 1) + { + CommandsDropdown.SelectedIndex++; + } + else + { + CommandsDropdown.SelectedIndex = 0; + } + + e.Handled = true; + } + } + + private void UpdateUiForStackChange() + { + ContextFilterBox.Text = string.Empty; + ViewModel.ContextMenu?.SetSearchText(string.Empty); + CommandsDropdown.SelectedIndex = 0; + ContextFilterBox.Focus(FocusState.Programmatic); } } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs index d939381fb0..c868e3dd5e 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Controls/SearchBar.xaml.cs @@ -8,8 +8,6 @@ using CommunityToolkit.WinUI; using Microsoft.CmdPal.UI.ViewModels; using Microsoft.CmdPal.UI.ViewModels.Messages; using Microsoft.CmdPal.UI.Views; -using Microsoft.CommandPalette.Extensions; -using Microsoft.CommandPalette.Extensions.Toolkit; using Microsoft.UI.Dispatching; using Microsoft.UI.Input; using Microsoft.UI.Xaml; @@ -23,7 +21,6 @@ namespace Microsoft.CmdPal.UI.Controls; public sealed partial class SearchBar : UserControl, IRecipient, IRecipient, - IRecipient, ICurrentPageAware { private readonly DispatcherQueue _queue = DispatcherQueue.GetForCurrentThread(); @@ -34,8 +31,6 @@ public sealed partial class SearchBar : UserControl, private readonly DispatcherQueueTimer _debounceTimer = DispatcherQueue.GetForCurrentThread().CreateTimer(); private bool _isBackspaceHeld; - private Dictionary? _keyBindings; - public PageViewModel? CurrentPageViewModel { get => (PageViewModel?)GetValue(CurrentPageViewModelProperty); @@ -74,7 +69,6 @@ public sealed partial class SearchBar : UserControl, this.InitializeComponent(); WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); - WeakReferenceMessenger.Default.Register(this); } public void ClearSearch() @@ -173,17 +167,14 @@ public sealed partial class SearchBar : UserControl, WeakReferenceMessenger.Default.Send(new()); } - if (_keyBindings != null) + if (!e.Handled) { - // Does the pressed key match any of the keybindings? - var pressedKeyChord = KeyChordHelpers.FromModifiers(ctrlPressed, altPressed, shiftPressed, winPressed, (int)e.Key, 0); - if (_keyBindings.TryGetValue(pressedKeyChord, out var item)) - { - // TODO GH #245: This is a bit of a hack, but we need to make sure that the keybindings are updated before we send the message - // so that the correct item is activated. - WeakReferenceMessenger.Default.Send(new(item)); - e.Handled = true; - } + // The CommandBar is responsible for handling all the item keybindings, + // since the bound context item may need to then show another + // context menu + TryCommandKeybindingMessage msg = new(ctrlPressed, altPressed, shiftPressed, winPressed, e.Key); + WeakReferenceMessenger.Default.Send(msg); + e.Handled = msg.Handled; } } @@ -302,10 +293,5 @@ public sealed partial class SearchBar : UserControl, public void Receive(GoHomeMessage message) => ClearSearch(); - public void Receive(FocusSearchBoxMessage message) => this.Focus(Microsoft.UI.Xaml.FocusState.Programmatic); - - public void Receive(UpdateItemKeybindingsMessage message) - { - _keyBindings = message.Keys; - } + public void Receive(FocusSearchBoxMessage message) => FilterBox.Focus(Microsoft.UI.Xaml.FocusState.Programmatic); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs index bc0999ca02..869b048dbd 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Pages/ShellPage.xaml.cs @@ -187,8 +187,6 @@ public sealed partial class ShellPage : Microsoft.UI.Xaml.Controls.Page, WeakReferenceMessenger.Default.Send(new(null)); - WeakReferenceMessenger.Default.Send(new(null)); - var isMainPage = command is MainListPage; // Construct our ViewModel of the appropriate type and pass it the UI Thread context. diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw index 51b33f8ede..6c63eeff16 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI/Strings/en-us/Resources.resw @@ -394,6 +394,9 @@ Right-click to remove the key combination, thereby deactivating the shortcut. Behavior + + Search commands... + Show system tray icon diff --git a/src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs index 373a1f7891..2fc1218bd7 100644 --- a/src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs +++ b/src/modules/cmdpal/ext/SamplePagesExtension/EvilSamplesPage.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; +using Windows.System; namespace SamplePagesExtension; @@ -76,7 +77,136 @@ public partial class EvilSamplesPage : ListPage { Body = "This is a test for GH#512. If it doesn't appear immediately, it's likely InvokeCommand is happening on the UI thread.", }, - } + }, + + // More edge cases than truly evil + new ListItem( + new ToastCommand("Primary command invoked", MessageState.Info) { Name = "Primary command", Icon = new IconInfo("\uF146") }) // dial 1 + { + Title = "anonymous command test", + Subtitle = "Try pressing Ctrl+1 with me selected", + Icon = new IconInfo("\uE712"), // "More" dots + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Secondary command invoked", MessageState.Warning) { Name = "Secondary command", Icon = new IconInfo("\uF147") }) // dial 2 + { + Title = "I'm a second command", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number1), + }, + new CommandContextItem("nested...") + { + Title = "We can go deeper...", + Icon = new IconInfo("\uF148"), + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number2), + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Nested A invoked") { Name = "Do it", Icon = new IconInfo("A") }) + { + Title = "Nested A", + RequestedShortcut = KeyChordHelpers.FromModifiers(alt: true, vkey: VirtualKey.A), + }, + + new CommandContextItem( + new ToastCommand("Nested B invoked") { Name = "Do it", Icon = new IconInfo("B") }) + { + Title = "Nested B...", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.B), + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Nested C invoked") { Name = "Do it" }) + { + Title = "You get it", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.B), + } + ], + }, + ], + } + ], + }, + new ListItem( + new ToastCommand("Primary command invoked", MessageState.Info) { Name = "Primary command", Icon = new IconInfo("\uF146") }) // dial 1 + { + Title = "noop command test", + Subtitle = "Try pressing Ctrl+1 with me selected", + Icon = new IconInfo("\uE712"), // "More" dots + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Secondary command invoked", MessageState.Warning) { Name = "Secondary command", Icon = new IconInfo("\uF147") }) // dial 2 + { + Title = "I'm a second command", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number1), + }, + new CommandContextItem(new NoOpCommand()) + { + Title = "We can go deeper...", + Icon = new IconInfo("\uF148"), + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number2), + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Nested A invoked") { Name = "Do it", Icon = new IconInfo("A") }) + { + Title = "Nested A", + RequestedShortcut = KeyChordHelpers.FromModifiers(alt: true, vkey: VirtualKey.A), + }, + + new CommandContextItem( + new ToastCommand("Nested B invoked") { Name = "Do it", Icon = new IconInfo("B") }) + { + Title = "Nested B...", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.B), + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Nested C invoked") { Name = "Do it" }) + { + Title = "You get it", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.B), + } + ], + }, + ], + } + ], + }, + new ListItem( + new ToastCommand("Primary command invoked", MessageState.Info) { Name = "Primary command", Icon = new IconInfo("\uF146") }) // dial 1 + { + Title = "noop secondary command test", + Subtitle = "Try pressing Ctrl+1 with me selected", + Icon = new IconInfo("\uE712"), // "More" dots + MoreCommands = [ + new CommandContextItem(new NoOpCommand()) + { + Title = "We can go deeper...", + Icon = new IconInfo("\uF148"), + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number2), + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Nested A invoked") { Name = "Do it", Icon = new IconInfo("A") }) + { + Title = "Nested A", + RequestedShortcut = KeyChordHelpers.FromModifiers(alt: true, vkey: VirtualKey.A), + }, + + new CommandContextItem( + new ToastCommand("Nested B invoked") { Name = "Do it", Icon = new IconInfo("B") }) + { + Title = "Nested B...", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.B), + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Nested C invoked") { Name = "Do it" }) + { + Title = "You get it", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.B), + } + ], + }, + ], + } + ], + }, + ]; public EvilSamplesPage() diff --git a/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleListPage.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleListPage.cs index 954a79ce04..3cf987e417 100644 --- a/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleListPage.cs +++ b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/SampleListPage.cs @@ -69,62 +69,47 @@ internal sealed partial class SampleListPage : ListPage }, new ListItem( - new AnonymousCommand(() => - { - var t = new ToastStatusMessage(new StatusMessage() - { - Message = "Primary command invoked", - State = MessageState.Info, - }); - t.Show(); - }) - { - Result = CommandResult.KeepOpen(), - Icon = new IconInfo("\uE712"), - }) + new ToastCommand("Primary command invoked", MessageState.Info) { Name = "Primary command", Icon = new IconInfo("\uF146") }) // dial 1 { Title = "You can add context menu items too. Press Ctrl+k", Subtitle = "Try pressing Ctrl+1 with me selected", - Icon = new IconInfo("\uE712"), + Icon = new IconInfo("\uE712"), // "More" dots MoreCommands = [ new CommandContextItem( - new AnonymousCommand(() => - { - var t = new ToastStatusMessage(new StatusMessage() - { - Message = "Secondary command invoked", - State = MessageState.Warning, - }); - t.Show(); - }) - { - Name = "Secondary command", - Icon = new IconInfo("\uF147"), // Dial 2 - Result = CommandResult.KeepOpen(), - }) + new ToastCommand("Secondary command invoked", MessageState.Warning) { Name = "Secondary command", Icon = new IconInfo("\uF147") }) // dial 2 { Title = "I'm a second command", RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number1), }, new CommandContextItem( - new AnonymousCommand(() => - { - var t = new ToastStatusMessage(new StatusMessage() - { - Message = "Third command invoked", - State = MessageState.Error, - }); - t.Show(); - }) - { - Name = "Do it", - Icon = new IconInfo("\uF148"), // dial 3 - Result = CommandResult.KeepOpen(), - }) + new ToastCommand("Third command invoked", MessageState.Error) { Name = "Do 3", Icon = new IconInfo("\uF148") }) // dial 3 { - Title = "A third command too", + Title = "We can go deeper...", Icon = new IconInfo("\uF148"), RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.Number2), + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Nested A invoked") { Name = "Do it", Icon = new IconInfo("A") }) + { + Title = "Nested A", + RequestedShortcut = KeyChordHelpers.FromModifiers(alt: true, vkey: VirtualKey.A), + }, + + new CommandContextItem( + new ToastCommand("Nested B invoked") { Name = "Do it", Icon = new IconInfo("B") }) + { + Title = "Nested B...", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.B), + MoreCommands = [ + new CommandContextItem( + new ToastCommand("Nested C invoked") { Name = "Do it" }) + { + Title = "You get it", + RequestedShortcut = KeyChordHelpers.FromModifiers(ctrl: true, vkey: VirtualKey.B), + } + ], + }, + ], } ], }, @@ -183,7 +168,6 @@ internal sealed partial class SampleListPage : ListPage { Title = "Get the name of the Foreground window", }, - ]; } } diff --git a/src/modules/cmdpal/ext/SamplePagesExtension/Pages/ToastCommand.cs b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/ToastCommand.cs new file mode 100644 index 0000000000..dfbeb5225a --- /dev/null +++ b/src/modules/cmdpal/ext/SamplePagesExtension/Pages/ToastCommand.cs @@ -0,0 +1,23 @@ +// 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 Microsoft.CommandPalette.Extensions; +using Microsoft.CommandPalette.Extensions.Toolkit; + +namespace SamplePagesExtension; + +internal sealed partial class ToastCommand(string message, MessageState state = MessageState.Info) : InvokableCommand +{ + public override ICommandResult Invoke() + { + var t = new ToastStatusMessage(new StatusMessage() + { + Message = message, + State = state, + }); + t.Show(); + + return CommandResult.KeepOpen(); + } +} diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ListItem.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ListItem.cs index 91d715b509..ffd20643aa 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ListItem.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/ListItem.cs @@ -61,4 +61,9 @@ public partial class ListItem : CommandItem, IListItem : base(command) { } + + public ListItem() + : base() + { + } } From fc804a81563a72d7782a20105765d6b7554cbd77 Mon Sep 17 00:00:00 2001 From: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Fri, 25 Apr 2025 09:57:42 +0800 Subject: [PATCH 60/70] [Tool] Script to build an installer locally (#39017) * add script to build a installer * minor fix * fix search path for msix file * fix sign * fix sign * fix spelling * Fix powershell5 can't recognize emoji * ensure-wix * bring cmdpal available during local build * remove early quit * fix marco * add logger * doc * add a note * self review * fix macro def * add functionality to export cert so that other machine can install it. * spelling --- .github/actions/spell-check/expect.txt | 4 + installer/PowerToysSetup/Product.wxs | 5 +- src/common/utils/package.h | 1 + .../CmdPalModuleInterface.vcxproj | 11 +- .../cmdpal/CmdPalModuleInterface/dllmain.cpp | 19 ++- tools/build/build-installer.ps1 | 122 ++++++++++++++ tools/build/cert-management.ps1 | 159 ++++++++++++++++++ tools/build/cert-sign-package.ps1 | 29 ++++ tools/build/ensure-wix.ps1 | 71 ++++++++ 9 files changed, 411 insertions(+), 10 deletions(-) create mode 100644 tools/build/build-installer.ps1 create mode 100644 tools/build/cert-management.ps1 create mode 100644 tools/build/cert-sign-package.ps1 create mode 100644 tools/build/ensure-wix.ps1 diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index daa6449a66..52f203a9de 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -198,6 +198,7 @@ CLIPBOARDUPDATE CLIPCHILDREN CLIPSIBLINGS closesocket +clp CLSCTX clsids Clusion @@ -1045,6 +1046,7 @@ NOINHERITLAYOUT NOINTERFACE NOINVERT NOLINKINFO +nologo NOMCX NOMINMAX NOMIRRORBITMAP @@ -1277,6 +1279,7 @@ pstm PStr pstream pstrm +pswd PSYSTEM psz ptb @@ -1423,6 +1426,7 @@ searchterm SEARCHUI SECONDARYDISPLAY secpol +securestring SEEMASKINVOKEIDLIST SELCHANGE SENDCHANGE diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 37256bdd68..f15b8a4714 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -79,10 +79,7 @@ - - - - + diff --git a/src/common/utils/package.h b/src/common/utils/package.h index 60bde7ea53..138f3b8e5b 100644 --- a/src/common/utils/package.h +++ b/src/common/utils/package.h @@ -301,6 +301,7 @@ namespace package if (!std::filesystem::exists(directoryPath)) { Logger::error(L"The directory '" + directoryPath + L"' does not exist."); + return {}; } const std::regex pattern(R"(^.+\.(appx|msix|msixbundle)$)", std::regex_constants::icase); diff --git a/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj b/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj index 4395e340fa..5bd12f316e 100644 --- a/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj +++ b/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj @@ -2,6 +2,7 @@ + 17.0 Win32Proj @@ -49,13 +50,21 @@ - EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + + EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL; + %(PreprocessorDefinitions); + $(CommandPaletteBranding) + + + IS_DEV_BRANDING;%(PreprocessorDefinitions) + ..\..\..\common\inc;..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories) $(OutDir)$(TargetName)$(TargetExt) + diff --git a/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp b/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp index 134249f049..be3eb6a3b7 100644 --- a/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp +++ b/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp @@ -208,7 +208,7 @@ public: try { std::wstring packageName = L"Microsoft.CommandPalette"; -#ifdef _DEBUG +#ifdef IS_DEV_BRANDING packageName = L"Microsoft.CommandPalette.Dev"; #endif if (!package::GetRegisteredPackage(packageName, false).has_value()) @@ -245,12 +245,21 @@ public: errorMessage += e.what(); Logger::error(errorMessage); } - -#if _DEBUG - LaunchApp(std::wstring{ L"shell:AppsFolder\\" } + L"Microsoft.CommandPalette.Dev_8wekyb3d8bbwe!App", L"RunFromPT", false); + try + { +#ifdef IS_DEV_BRANDING + LaunchApp(std::wstring{ L"shell:AppsFolder\\" } + L"Microsoft.CommandPalette.Dev_8wekyb3d8bbwe!App", L"RunFromPT", false); #else - LaunchApp(std::wstring{ L"shell:AppsFolder\\" } + L"Microsoft.CommandPalette_8wekyb3d8bbwe!App", L"RunFromPT", false); + LaunchApp(std::wstring{ L"shell:AppsFolder\\" } + L"Microsoft.CommandPalette_8wekyb3d8bbwe!App", L"RunFromPT", false); #endif + } + catch (std::exception& e) + { + std::string errorMessage{ "Exception thrown while trying to launch CmdPal: " }; + errorMessage += e.what(); + Logger::error(errorMessage); + throw; + } } virtual void disable() diff --git a/tools/build/build-installer.ps1 b/tools/build/build-installer.ps1 new file mode 100644 index 0000000000..28e6939760 --- /dev/null +++ b/tools/build/build-installer.ps1 @@ -0,0 +1,122 @@ +<# +.SYNOPSIS +Build and package PowerToys (CmdPal and installer) for a specific platform and configuration LOCALLY. + +.DESCRIPTION +This script automates the end-to-end build and packaging process for PowerToys, including: +- Restoring and building all necessary solutions (CmdPal, BugReportTool, StylesReportTool, etc.) +- Cleaning up old output +- Signing generated .msix packages +- Building the WiX-based MSI and bootstrapper installers + +It is designed to work in local development. + +.PARAMETER Platform +Specifies the target platform for the build (e.g., 'arm64', 'x64'). Default is 'arm64'. + +.PARAMETER Configuration +Specifies the build configuration (e.g., 'Debug', 'Release'). Default is 'Release'. + +.EXAMPLE +.\build-installer.ps1 +Runs the installer build pipeline for ARM64 Release (default). + +.EXAMPLE +.\build-installer.ps1 -Platform x64 -Configuration Release +Runs the pipeline for x64 Debug. + +.NOTES +- Requires MSBuild, WiX Toolset, and Git to be installed and accessible from your environment. +- Make sure to run this script from a Developer PowerShell (e.g., VS2022 Developer PowerShell). +- Generated MSIX files will be signed using cert-sign-package.ps1. +- This script will clean previous outputs under the build directories and installer directory (except *.exe files). +- First time run need admin permission to trust the certificate. +- The built installer will be placed under: installer/PowerToysSetup/[Platform]/[Configuration]/UserSetup + relative to the solution root directory. +- The installer can't be run right after the build, I need to copy it to another file before it can be run. +#> + + +param ( + [string]$Platform = 'arm64', + [string]$Configuration = 'Release' +) + +$repoRoot = Resolve-Path "$PSScriptRoot\..\.." +Set-Location $repoRoot + +function RunMSBuild { + param ( + [string]$Solution, + [string]$ExtraArgs + ) + + $base = @( + $Solution + "/p:Platform=`"$Platform`"" + "/p:Configuration=$Configuration" + '/verbosity:normal' + '/clp:Summary;PerformanceSummary;ErrorsOnly;WarningsOnly' + '/nologo' + ) + + $cmd = $base + ($ExtraArgs -split ' ') + Write-Host ("[MSBUILD] {0} {1}" -f $Solution, ($cmd -join ' ')) + & msbuild.exe @cmd + + if ($LASTEXITCODE -ne 0) { + Write-Error ("Build failed: {0} {1}" -f $Solution, $ExtraArgs) + exit $LASTEXITCODE + } + +} + +function RestoreThenBuild { + param ([string]$Solution) + + # 1) restore + RunMSBuild $Solution '/t:restore /p:RestorePackagesConfig=true' + # 2) build ------------------------------------------------- + RunMSBuild $Solution '/m' +} + +Write-Host ("Make sure wix is installed and available") +& "$PSScriptRoot\ensure-wix.ps1" + +Write-Host ("[PIPELINE] Start | Platform={0} Configuration={1}" -f $Platform, $Configuration) +Write-Host '' + +$cmdpalOutputPath = Join-Path $repoRoot "$Platform\$Configuration\WinUI3Apps\CmdPal" + +if (Test-Path $cmdpalOutputPath) { + Write-Host "[CLEAN] Removing previous output: $cmdpalOutputPath" + Remove-Item $cmdpalOutputPath -Recurse -Force -ErrorAction Ignore +} + +RestoreThenBuild '.\PowerToys.sln' + +$msixSearchRoot = Join-Path $repoRoot "$Platform\$Configuration" +$msixFiles = Get-ChildItem -Path $msixSearchRoot -Recurse -Filter *.msix | +Select-Object -ExpandProperty FullName + +if ($msixFiles.Count) { + Write-Host ("[SIGN] .msix file(s): {0}" -f ($msixFiles -join '; ')) + & "$PSScriptRoot\cert-sign-package.ps1" -TargetPaths $msixFiles +} +else { + Write-Warning "[SIGN] No .msix files found in $msixSearchRoot" +} + +RestoreThenBuild '.\tools\BugReportTool\BugReportTool.sln' +RestoreThenBuild '.\tools\StylesReportTool\StylesReportTool.sln' + +Write-Host '[CLEAN] installer (keep *.exe)' +git clean -xfd -e '*.exe' -- .\installer\ | Out-Null + +RunMSBuild '.\installer\PowerToysSetup.sln' '/t:restore /p:RestorePackagesConfig=true' + +RunMSBuild '.\installer\PowerToysSetup.sln' '/m /t:PowerToysInstaller /p:PerUser=true' + +RunMSBuild '.\installer\PowerToysSetup.sln' '/m /t:PowerToysBootstrapper /p:PerUser=true' + +Write-Host '[PIPELINE] Completed' \ No newline at end of file diff --git a/tools/build/cert-management.ps1 b/tools/build/cert-management.ps1 new file mode 100644 index 0000000000..a085a5ca54 --- /dev/null +++ b/tools/build/cert-management.ps1 @@ -0,0 +1,159 @@ +<# +.SYNOPSIS +Ensures a code signing certificate exists and is trusted in all necessary certificate stores. + +.DESCRIPTION +This script provides two functions: + +1. EnsureCertificate: + - Searches for an existing code signing certificate by subject name. + - If not found, creates a new self-signed certificate. + - Exports the certificate and attempts to import it into: + - CurrentUser\TrustedPeople + - CurrentUser\Root + - LocalMachine\Root (admin privileges may be required) + +2. ImportAndVerifyCertificate: + - Imports a `.cer` file into the specified certificate store if not already present. + - Verifies the certificate is successfully imported by checking thumbprint. + +This is useful in build or signing pipelines to ensure a valid and trusted certificate is available before signing MSIX or executable files. + +.PARAMETER certSubject +The subject name of the certificate to search for or create. Default is: +"CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" + +.PARAMETER cerPath +(ImportAndVerifyCertificate only) The file path to a `.cer` certificate file to import. + +.PARAMETER storePath +(ImportAndVerifyCertificate only) The destination certificate store path (e.g. Cert:\CurrentUser\Root). + +.EXAMPLE +$cert = EnsureCertificate + +Ensures the default certificate exists and is trusted, and returns the certificate object. + +.EXAMPLE +ImportAndVerifyCertificate -cerPath "$env:TEMP\temp_cert.cer" -storePath "Cert:\CurrentUser\Root" + +Imports a certificate into the CurrentUser Root store and verifies its presence. + +.NOTES +- For full trust, administrative privileges may be needed to import into LocalMachine\Root. +- Certificates are created using RSA and SHA256 and marked as CodeSigningCert. +#> + +function ImportAndVerifyCertificate { + param ( + [string]$cerPath, + [string]$storePath + ) + + $thumbprint = (Get-PfxCertificate -FilePath $cerPath).Thumbprint + + $existingCert = Get-ChildItem -Path $storePath | Where-Object { $_.Thumbprint -eq $thumbprint } + if ($existingCert) { + Write-Host "Certificate already exists in $storePath" + return $true + } + + try { + $null = Import-Certificate -FilePath $cerPath -CertStoreLocation $storePath -ErrorAction Stop + } catch { + Write-Warning "Failed to import certificate to $storePath : $_" + return $false + } + + $imported = Get-ChildItem -Path $storePath | Where-Object { $_.Thumbprint -eq $thumbprint } + if ($imported) { + Write-Host "Certificate successfully imported to $storePath" + return $true + } else { + Write-Warning "Certificate not found in $storePath after import" + return $false + } +} + +function EnsureCertificate { + param ( + [string]$certSubject = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" + ) + + $cert = Get-ChildItem -Path Cert:\CurrentUser\My | + Where-Object { $_.Subject -eq $certSubject } | + Sort-Object NotAfter -Descending | + Select-Object -First 1 + + if (-not $cert) { + Write-Host "Certificate not found. Creating a new one..." + + $cert = New-SelfSignedCertificate -Subject $certSubject ` + -CertStoreLocation "Cert:\CurrentUser\My" ` + -KeyAlgorithm RSA ` + -Type CodeSigningCert ` + -HashAlgorithm SHA256 + + if (-not $cert) { + Write-Error "Failed to create a new certificate." + return $null + } + + Write-Host "New certificate created with thumbprint: $($cert.Thumbprint)" + } + else { + Write-Host "Using existing certificate with thumbprint: $($cert.Thumbprint)" + } + + $cerPath = "$env:TEMP\temp_cert.cer" + [void](Export-Certificate -Cert $cert -FilePath $cerPath -Force) + + if (-not (ImportAndVerifyCertificate -cerPath $cerPath -storePath "Cert:\CurrentUser\TrustedPeople")) { return $null } + if (-not (ImportAndVerifyCertificate -cerPath $cerPath -storePath "Cert:\CurrentUser\Root")) { return $null } + if (-not (ImportAndVerifyCertificate -cerPath $cerPath -storePath "Cert:\LocalMachine\Root")) { + Write-Warning "Failed to import to LocalMachine\Root (admin may be required)" + return $null + } + + return $cert +} + +function Export-CertificateFiles { + param ( + [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate, + [string]$CerPath, + [string]$PfxPath, + [securestring]$PfxPassword + ) + + if (-not $Certificate) { + Write-Error "No certificate provided to export." + return + } + + if ($CerPath) { + try { + Export-Certificate -Cert $Certificate -FilePath $CerPath -Force | Out-Null + Write-Host "Exported CER to: $CerPath" + } catch { + Write-Warning "Failed to export CER file: $_" + } + } + + if ($PfxPath -and $PfxPassword) { + try { + Export-PfxCertificate -Cert $Certificate -FilePath $PfxPath -Password $PfxPassword -Force | Out-Null + Write-Host "Exported PFX to: $PfxPath" + } catch { + Write-Warning "Failed to export PFX file: $_" + } + } + + if (-not $CerPath -and -not $PfxPath) { + Write-Warning "No output path specified. Nothing was exported." + } +} + +$cert = EnsureCertificate +$pswd = ConvertTo-SecureString -String "MySecurePassword123!" -AsPlainText -Force +Export-CertificateFiles -Certificate $cert -CerPath "$env:TEMP\cert.cer" -PfxPath "$env:TEMP\cert.pfx" -PfxPassword $pswd diff --git a/tools/build/cert-sign-package.ps1 b/tools/build/cert-sign-package.ps1 new file mode 100644 index 0000000000..8bb57762a5 --- /dev/null +++ b/tools/build/cert-sign-package.ps1 @@ -0,0 +1,29 @@ +param ( + [string]$certSubject = "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", + [string[]]$TargetPaths = "C:\PowerToys\ARM64\Release\WinUI3Apps\CmdPal\AppPackages\Microsoft.CmdPal.UI_0.0.1.0_Test\Microsoft.CmdPal.UI_0.0.1.0_arm64.msix" +) + +. "$PSScriptRoot\cert-management.ps1" +$cert = EnsureCertificate -certSubject $certSubject + +if (-not $cert) { + Write-Error "Failed to prepare certificate." + exit 1 +} + +Write-Host "Certificate ready: $($cert.Thumbprint)" + +if (-not $TargetPaths -or $TargetPaths.Count -eq 0) { + Write-Error "No target files provided to sign." + exit 1 +} + +foreach ($filePath in $TargetPaths) { + if (-not (Test-Path $filePath)) { + Write-Warning "Skipping: File does not exist - $filePath" + continue + } + + Write-Host "Signing: $filePath" + & signtool sign /sha1 $($cert.Thumbprint) /fd SHA256 /t http://timestamp.digicert.com "$filePath" +} \ No newline at end of file diff --git a/tools/build/ensure-wix.ps1 b/tools/build/ensure-wix.ps1 new file mode 100644 index 0000000000..988d382f07 --- /dev/null +++ b/tools/build/ensure-wix.ps1 @@ -0,0 +1,71 @@ +<# +.SYNOPSIS + Ensure WiX Toolset 3.14 (build 3141) is installed and ready to use. + +.DESCRIPTION + - Skips installation if the toolset is already installed (unless -Force is used). + - Otherwise downloads the official installer and binaries, verifies SHA-256, installs silently, + and copies wix.targets into the installation directory. +.PARAMETER Force + Forces reinstallation even if the toolset is already detected. +.PARAMETER InstallDir + The target installation path. Default is 'C:\Program Files (x86)\WiX Toolset v3.14'. +.EXAMPLE + .\EnsureWix.ps1 # Ensure WiX is installed + .\EnsureWix.ps1 -Force # Force reinstall +#> +[CmdletBinding()] +param( + [switch]$Force, + [string]$InstallDir = 'C:\Program Files (x86)\WiX Toolset v3.14' +) + +$ErrorActionPreference = 'Stop' +$ProgressPreference = 'SilentlyContinue' + +# Download URLs and expected SHA-256 hashes +$WixDownloadUrl = 'https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314.exe' +$WixBinariesDownloadUrl = 'https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip' +$InstallerHashExpected = '6BF6D03D6923D9EF827AE1D943B90B42B8EBB1B0F68EF6D55F868FA34C738A29' +$BinariesHashExpected = '6AC824E1642D6F7277D0ED7EA09411A508F6116BA6FAE0AA5F2C7DAA2FF43D31' + +# Check if WiX is already installed +$candlePath = Join-Path $InstallDir 'bin\candle.exe' +if (-not $Force -and (Test-Path $candlePath)) { + Write-Host "WiX Toolset is already installed at `"$InstallDir`". Skipping installation." + return +} + +# Temp file paths +$tmpDir = [IO.Path]::GetTempPath() +$installer = Join-Path $tmpDir 'wix314.exe' +$binariesZip = Join-Path $tmpDir 'wix314-binaries.zip' + +# Download installer and binaries +Write-Host 'Downloading WiX installer...' +Invoke-WebRequest -Uri $WixDownloadUrl -OutFile $installer -UseBasicParsing +Write-Host 'Downloading WiX binaries...' +Invoke-WebRequest -Uri $WixBinariesDownloadUrl -OutFile $binariesZip -UseBasicParsing + +# Verify SHA-256 hashes +Write-Host 'Verifying installer hash...' +if ((Get-FileHash -Algorithm SHA256 $installer).Hash -ne $InstallerHashExpected) { + throw 'wix314.exe SHA256 hash mismatch' +} +Write-Host 'Verifying binaries hash...' +if ((Get-FileHash -Algorithm SHA256 $binariesZip).Hash -ne $BinariesHashExpected) { + throw 'wix314-binaries.zip SHA256 hash mismatch' +} + +# Perform silent installation +Write-Host 'Installing WiX Toolset silently...' +Start-Process -FilePath $installer -ArgumentList '/install','/quiet' -Wait + +# Extract binaries and copy wix.targets +$expandDir = Join-Path $tmpDir 'wix-binaries' +if (Test-Path $expandDir) { Remove-Item $expandDir -Recurse -Force } +Expand-Archive -Path $binariesZip -DestinationPath $expandDir -Force +Copy-Item -Path (Join-Path $expandDir 'wix.targets') ` + -Destination (Join-Path $InstallDir 'wix.targets') -Force + +Write-Host "WiX Toolset has been successfully installed at: $InstallDir" From 06b56a10bd51fd3c7ca8acb178e7778ac1eb51a6 Mon Sep 17 00:00:00 2001 From: cryolithic Date: Thu, 24 Apr 2025 19:45:11 -0700 Subject: [PATCH 61/70] 37405 Advanced Paste: Image To Text doesn't work with English (Canada) (#37806) * [AdvancedPaste] [Fix Bug] Create ocrEngine from user profile language GetOCRLanguage may fail based on language tag not matching (en-CA does not match en-GB or en-US), however user profile language may be valid. * Update exception message. Signed-off-by: Shawn Yuan * update Signed-off-by: Shawn Yuan --------- Signed-off-by: Shawn Yuan Co-authored-by: Shawn Yuan --- .../AdvancedPaste/Helpers/OcrHelpers.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/OcrHelpers.cs b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/OcrHelpers.cs index b56868ece8..218349b32b 100644 --- a/src/modules/AdvancedPaste/AdvancedPaste/Helpers/OcrHelpers.cs +++ b/src/modules/AdvancedPaste/AdvancedPaste/Helpers/OcrHelpers.cs @@ -18,10 +18,19 @@ public static class OcrHelpers { public static async Task ExtractTextAsync(SoftwareBitmap bitmap, CancellationToken cancellationToken) { - var ocrLanguage = GetOCRLanguage() ?? throw new InvalidOperationException("Unable to determine OCR language"); + var ocrLanguage = GetOCRLanguage(); cancellationToken.ThrowIfCancellationRequested(); - var ocrEngine = OcrEngine.TryCreateFromLanguage(ocrLanguage) ?? throw new InvalidOperationException("Unable to create OCR engine"); + OcrEngine ocrEngine; + if (ocrLanguage is not null) + { + ocrEngine = OcrEngine.TryCreateFromLanguage(ocrLanguage) ?? throw new InvalidOperationException("Unable to create OCR engine from specified language"); + } + else + { + ocrEngine = OcrEngine.TryCreateFromUserProfileLanguages() ?? throw new InvalidOperationException("Unable to create OCR engine from user profile language"); + } + cancellationToken.ThrowIfCancellationRequested(); var ocrResult = await ocrEngine.RecognizeAsync(bitmap); From 26fe36ab8d9e99bd201f80105d4499b24c35a09f Mon Sep 17 00:00:00 2001 From: Lemonyte <49930425+lemonyte@users.noreply.github.com> Date: Thu, 24 Apr 2025 19:48:19 -0700 Subject: [PATCH 62/70] Color Picker: add Oklab and Oklch color formats (#38052) * Resolve Resources.resw conflict * Update CIE LCh chroma practical upper bound according to CSS spec * Add review suggestions * Add WIP tests (lch and oklch do not pass yet) * Deduplicate Lab to LCh converter method * Update expect.txt * Fix liberty test color * Reimplement oklab with better precision * Remove CIE LCh * Add tooltip for color param descriptions * Update spell-check expect.txt with new words * Remove 'cielch' and 'lch' from expect.txt --------- Co-authored-by: Gordon Lam (SH) Co-authored-by: Clint Rutkas Co-authored-by: Shawn Yuan <128874481+shuaiyuanxx@users.noreply.github.com> --- .github/actions/spell-check/expect.txt | 10 +- src/common/ManagedCommon/ColorFormatHelper.cs | 131 ++++++++++++++++-- .../Helpers/ColorRepresentationHelper.cs | 34 +++++ .../ViewModels/ColorEditorViewModel.cs | 16 ++- .../Helpers/ColorConverterTest.cs | 120 ++++++++++++++-- .../Helpers/ColorRepresentationHelperTest.cs | 4 +- .../ColorPickerProperties.cs | 4 +- .../Enumerations/ColorRepresentationType.cs | 15 ++ .../Controls/ColorFormatEditor.xaml | 3 +- .../Controls/ColorFormatEditor.xaml.cs | 11 +- .../Settings.UI/Strings/en-us/Resources.resw | 31 ++++- 11 files changed, 348 insertions(+), 31 deletions(-) diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index 52f203a9de..43447793a0 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1982,4 +1982,12 @@ zoomit ZOOMITX ZXk ZXNs -zzz \ No newline at end of file +zzz +ACIE +AOklab +BCIE +BOklab +culori +Evercoder +LCh +CIELCh diff --git a/src/common/ManagedCommon/ColorFormatHelper.cs b/src/common/ManagedCommon/ColorFormatHelper.cs index 08e62b921d..471104f215 100644 --- a/src/common/ManagedCommon/ColorFormatHelper.cs +++ b/src/common/ManagedCommon/ColorFormatHelper.cs @@ -141,6 +141,40 @@ namespace ManagedCommon return lab; } + /// + /// Convert a given to a Oklab color + /// + /// The to convert + /// The perceptual lightness [0..1] and two chromaticities [-0.5..0.5] + public static (double Lightness, double ChromaticityA, double ChromaticityB) ConvertToOklabColor(Color color) + { + var linear = ConvertSRGBToLinearRGB(color.R / 255d, color.G / 255d, color.B / 255d); + var oklab = GetOklabColorFromLinearRGB(linear.R, linear.G, linear.B); + return oklab; + } + + /// + /// Convert a given to a Oklch color + /// + /// The to convert + /// The perceptual lightness [0..1], the chroma [0..0.5], and the hue angle [0°..360°] + public static (double Lightness, double Chroma, double Hue) ConvertToOklchColor(Color color) + { + var oklab = ConvertToOklabColor(color); + var oklch = GetOklchColorFromOklab(oklab.Lightness, oklab.ChromaticityA, oklab.ChromaticityB); + + return oklch; + } + + public static (double R, double G, double B) ConvertSRGBToLinearRGB(double r, double g, double b) + { + // inverse companding, gamma correction must be undone + double rLinear = (r > 0.04045) ? Math.Pow((r + 0.055) / 1.055, 2.4) : (r / 12.92); + double gLinear = (g > 0.04045) ? Math.Pow((g + 0.055) / 1.055, 2.4) : (g / 12.92); + double bLinear = (b > 0.04045) ? Math.Pow((b + 0.055) / 1.055, 2.4) : (b / 12.92); + return (rLinear, gLinear, bLinear); + } + /// /// Convert a given to a CIE XYZ color (XYZ) /// The constants of the formula matches this Wikipedia page, but at a higher precision: @@ -156,10 +190,7 @@ namespace ManagedCommon double g = color.G / 255d; double b = color.B / 255d; - // inverse companding, gamma correction must be undone - double rLinear = (r > 0.04045) ? Math.Pow((r + 0.055) / 1.055, 2.4) : (r / 12.92); - double gLinear = (g > 0.04045) ? Math.Pow((g + 0.055) / 1.055, 2.4) : (g / 12.92); - double bLinear = (b > 0.04045) ? Math.Pow((b + 0.055) / 1.055, 2.4) : (b / 12.92); + (double rLinear, double gLinear, double bLinear) = ConvertSRGBToLinearRGB(r, g, b); return ( (rLinear * 0.41239079926595948) + (gLinear * 0.35758433938387796) + (bLinear * 0.18048078840183429), @@ -210,6 +241,63 @@ namespace ManagedCommon return (l, a, b); } + /// + /// Convert a linear RGB color to an Oklab color. + /// The constants of this formula come from https://github.com/Evercoder/culori/blob/2bedb8f0507116e75f844a705d0b45cf279b15d0/src/oklab/convertLrgbToOklab.js + /// and the implementation is based on https://bottosson.github.io/posts/oklab/ + /// + /// Linear R value + /// Linear G value + /// Linear B value + /// The perceptual lightness [0..1] and two chromaticities [-0.5..0.5] + private static (double Lightness, double ChromaticityA, double ChromaticityB) + GetOklabColorFromLinearRGB(double r, double g, double b) + { + double l = (0.41222147079999993 * r) + (0.5363325363 * g) + (0.0514459929 * b); + double m = (0.2119034981999999 * r) + (0.6806995450999999 * g) + (0.1073969566 * b); + double s = (0.08830246189999998 * r) + (0.2817188376 * g) + (0.6299787005000002 * b); + + double l_ = Math.Cbrt(l); + double m_ = Math.Cbrt(m); + double s_ = Math.Cbrt(s); + + return ( + (0.2104542553 * l_) + (0.793617785 * m_) - (0.0040720468 * s_), + (1.9779984951 * l_) - (2.428592205 * m_) + (0.4505937099 * s_), + (0.0259040371 * l_) + (0.7827717662 * m_) - (0.808675766 * s_) + ); + } + + /// + /// Convert an Oklab color from Cartesian form to its polar form Oklch + /// https://bottosson.github.io/posts/oklab/#the-oklab-color-space + /// + /// The + /// The + /// The + /// The perceptual lightness [0..1], the chroma [0..0.5], and the hue angle [0°..360°] + private static (double Lightness, double Chroma, double Hue) + GetOklchColorFromOklab(double lightness, double chromaticity_a, double chromaticity_b) + { + return GetLCHColorFromLAB(lightness, chromaticity_a, chromaticity_b); + } + + /// + /// Convert a color in Cartesian form (Lab) to its polar form (LCh) + /// + /// The + /// The + /// The + /// The lightness, chroma, and hue angle + private static (double Lightness, double Chroma, double Hue) + GetLCHColorFromLAB(double lightness, double chromaticity_a, double chromaticity_b) + { + // Lab to LCh transformation + double chroma = Math.Sqrt(Math.Pow(chromaticity_a, 2) + Math.Pow(chromaticity_b, 2)); + double hue = Math.Round(chroma, 3) == 0 ? 0.0 : ((Math.Atan2(chromaticity_b, chromaticity_a) * 180d / Math.PI) + 360d) % 360d; + return (lightness, chroma, hue); + } + /// /// Convert a given to a natural color (hue, whiteness, blackness) /// @@ -276,12 +364,17 @@ namespace ManagedCommon { "Br", 'p' }, // brightness percent { "In", 'p' }, // intensity percent { "Ll", 'p' }, // lightness (HSL) percent - { "Lc", 'p' }, // lightness(CIELAB)percent { "Va", 'p' }, // value percent { "Wh", 'p' }, // whiteness percent { "Bn", 'p' }, // blackness percent - { "Ca", 'p' }, // chromaticityA percent - { "Cb", 'p' }, // chromaticityB percent + { "Lc", 'p' }, // lightness (CIE) percent + { "Ca", 'p' }, // chromaticityA (CIELAB) percent + { "Cb", 'p' }, // chromaticityB (CIELAB) percent + { "Lo", 'p' }, // lightness (Oklab/Oklch) percent + { "Oa", 'p' }, // chromaticityA (Oklab) percent + { "Ob", 'p' }, // chromaticityB (Oklab) percent + { "Oc", 'p' }, // chroma (Oklch) percent + { "Oh", 'p' }, // hue angle (Oklch) percent { "Xv", 'i' }, // X value int { "Yv", 'i' }, // Y value int { "Zv", 'i' }, // Z value int @@ -424,6 +517,10 @@ namespace ManagedCommon var (lightnessC, _, _) = ConvertToCIELABColor(color); lightnessC = Math.Round(lightnessC, 2); return lightnessC.ToString(CultureInfo.InvariantCulture); + case "Lo": + var (lightnessO, _, _) = ConvertToOklabColor(color); + lightnessO = Math.Round(lightnessO, 2); + return lightnessO.ToString(CultureInfo.InvariantCulture); case "Wh": var (_, whiteness, _) = ConvertToHWBColor(color); whiteness = Math.Round(whiteness * 100); @@ -440,6 +537,22 @@ namespace ManagedCommon var (_, _, chromaticityB) = ConvertToCIELABColor(color); chromaticityB = Math.Round(chromaticityB, 2); return chromaticityB.ToString(CultureInfo.InvariantCulture); + case "Oa": + var (_, chromaticityAOklab, _) = ConvertToOklabColor(color); + chromaticityAOklab = Math.Round(chromaticityAOklab, 2); + return chromaticityAOklab.ToString(CultureInfo.InvariantCulture); + case "Ob": + var (_, _, chromaticityBOklab) = ConvertToOklabColor(color); + chromaticityBOklab = Math.Round(chromaticityBOklab, 2); + return chromaticityBOklab.ToString(CultureInfo.InvariantCulture); + case "Oc": + var (_, chromaOklch, _) = ConvertToOklchColor(color); + chromaOklch = Math.Round(chromaOklch, 2); + return chromaOklch.ToString(CultureInfo.InvariantCulture); + case "Oh": + var (_, _, hueOklch) = ConvertToOklchColor(color); + hueOklch = Math.Round(hueOklch, 2); + return hueOklch.ToString(CultureInfo.InvariantCulture); case "Xv": var (x, _, _) = ConvertToCIEXYZColor(color); x = Math.Round(x * 100, 4); @@ -495,8 +608,10 @@ namespace ManagedCommon case "HSI": return "hsi(%Hu, %Si%, %In%)"; case "HWB": return "hwb(%Hu, %Wh%, %Bn%)"; case "NCol": return "%Hn, %Wh%, %Bn%"; - case "CIELAB": return "CIELab(%Lc, %Ca, %Cb)"; case "CIEXYZ": return "XYZ(%Xv, %Yv, %Zv)"; + case "CIELAB": return "CIELab(%Lc, %Ca, %Cb)"; + case "Oklab": return "oklab(%Lo, %Oa, %Ob)"; + case "Oklch": return "oklch(%Lo, %Oc, %Oh)"; case "VEC4": return "(%Reff, %Grff, %Blff, 1f)"; case "Decimal": return "%Dv"; case "HEX Int": return "0xFF%ReX%GrX%BlX"; diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs index 82b238993d..3f0feaaae3 100644 --- a/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs +++ b/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs @@ -243,6 +243,40 @@ namespace ColorPicker.Helpers $", {chromaticityB.ToString(CultureInfo.InvariantCulture)})"; } + /// + /// Returns a representation of a Oklab color + /// + /// The for the Oklab color presentation + /// A representation of a Oklab color + private static string ColorToOklab(Color color) + { + var (lightness, chromaticityA, chromaticityB) = ColorFormatHelper.ConvertToOklabColor(color); + lightness = Math.Round(lightness, 2); + chromaticityA = Math.Round(chromaticityA, 2); + chromaticityB = Math.Round(chromaticityB, 2); + + return $"oklab({lightness.ToString(CultureInfo.InvariantCulture)}" + + $", {chromaticityA.ToString(CultureInfo.InvariantCulture)}" + + $", {chromaticityB.ToString(CultureInfo.InvariantCulture)})"; + } + + /// + /// Returns a representation of a CIE LCh color + /// + /// The for the CIE LCh color presentation + /// A representation of a CIE LCh color + private static string ColorToOklch(Color color) + { + var (lightness, chroma, hue) = ColorFormatHelper.ConvertToOklchColor(color); + lightness = Math.Round(lightness, 2); + chroma = Math.Round(chroma, 2); + hue = Math.Round(hue, 2); + + return $"oklch({lightness.ToString(CultureInfo.InvariantCulture)}" + + $", {chroma.ToString(CultureInfo.InvariantCulture)}" + + $", {hue.ToString(CultureInfo.InvariantCulture)})"; + } + /// /// Returns a representation of a CIE XYZ color /// diff --git a/src/modules/colorPicker/ColorPickerUI/ViewModels/ColorEditorViewModel.cs b/src/modules/colorPicker/ColorPickerUI/ViewModels/ColorEditorViewModel.cs index 129f365e0d..2f8d5a2348 100644 --- a/src/modules/colorPicker/ColorPickerUI/ViewModels/ColorEditorViewModel.cs +++ b/src/modules/colorPicker/ColorPickerUI/ViewModels/ColorEditorViewModel.cs @@ -301,6 +301,12 @@ namespace ColorPicker.ViewModels FormatName = ColorRepresentationType.NCol.ToString(), Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.NCol.ToString()), }); + _allColorRepresentations.Add( + new ColorFormatModel() + { + FormatName = ColorRepresentationType.CIEXYZ.ToString(), + Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CIEXYZ.ToString()), + }); _allColorRepresentations.Add( new ColorFormatModel() { @@ -310,8 +316,14 @@ namespace ColorPicker.ViewModels _allColorRepresentations.Add( new ColorFormatModel() { - FormatName = ColorRepresentationType.CIEXYZ.ToString(), - Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CIEXYZ.ToString()), + FormatName = ColorRepresentationType.Oklab.ToString(), + Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.Oklab.ToString()), + }); + _allColorRepresentations.Add( + new ColorFormatModel() + { + FormatName = ColorRepresentationType.Oklch.ToString(), + Convert = (Color color) => ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.Oklch.ToString()), }); _allColorRepresentations.Add( new ColorFormatModel() diff --git a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorConverterTest.cs b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorConverterTest.cs index eaa5369dd6..288ed0f599 100644 --- a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorConverterTest.cs +++ b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorConverterTest.cs @@ -364,9 +364,6 @@ namespace Microsoft.ColorPicker.UnitTests [DataRow("8080FF", 59.20, 33.10, -63.46)] // blue [DataRow("BF40BF", 50.10, 65.50, -41.48)] // magenta [DataRow("BFBF00", 75.04, -17.35, 76.03)] // yellow - [DataRow("008000", 46.23, -51.70, 49.90)] // green - [DataRow("8080FF", 59.20, 33.10, -63.46)] // blue - [DataRow("BF40BF", 50.10, 65.50, -41.48)] // magenta [DataRow("0048BA", 34.35, 27.94, -64.80)] // absolute zero [DataRow("B0BF1A", 73.91, -23.39, 71.15)] // acid green [DataRow("D0FF14", 93.87, -40.20, 88.97)] // arctic lime @@ -401,13 +398,121 @@ namespace Microsoft.ColorPicker.UnitTests var result = ColorFormatHelper.ConvertToCIELABColor(color); // lightness[0..100] - Assert.AreEqual(Math.Round(result.Lightness, 2), lightness); + Assert.AreEqual(lightness, Math.Round(result.Lightness, 2)); // chromaticityA[-128..127] - Assert.AreEqual(Math.Round(result.ChromaticityA, 2), chromaticityA); + Assert.AreEqual(chromaticityA, Math.Round(result.ChromaticityA, 2)); // chromaticityB[-128..127] - Assert.AreEqual(Math.Round(result.ChromaticityB, 2), chromaticityB); + Assert.AreEqual(chromaticityB, Math.Round(result.ChromaticityB, 2)); + } + + // Test data calculated using https://oklch.com (which uses https://github.com/Evercoder/culori) + [TestMethod] + [DataRow("FFFFFF", 1.00, 0.00, 0.00)] // white + [DataRow("808080", 0.6, 0.00, 0.00)] // gray + [DataRow("000000", 0.00, 0.00, 0.00)] // black + [DataRow("FF0000", 0.628, 0.22, 0.13)] // red + [DataRow("008000", 0.52, -0.14, 0.11)] // green + [DataRow("80FFFF", 0.928, -0.11, -0.03)] // cyan + [DataRow("8080FF", 0.661, 0.03, -0.18)] // blue + [DataRow("BF40BF", 0.598, 0.18, -0.11)] // magenta + [DataRow("BFBF00", 0.779, -0.06, 0.16)] // yellow + [DataRow("0048BA", 0.444, -0.03, -0.19)] // absolute zero + [DataRow("B0BF1A", 0.767, -0.07, 0.15)] // acid green + [DataRow("D0FF14", 0.934, -0.12, 0.19)] // arctic lime + [DataRow("1B4D3E", 0.382, -0.06, 0.01)] // brunswick green + [DataRow("FFEF00", 0.935, -0.05, 0.19)] // canary yellow + [DataRow("FFA600", 0.794, 0.06, 0.16)] // cheese + [DataRow("1A2421", 0.25, -0.02, 0)] // dark jungle green + [DataRow("003399", 0.371, -0.02, -0.17)] // dark powder blue + [DataRow("D70A53", 0.563, 0.22, 0.04)] // debian red + [DataRow("80FFD5", 0.916, -0.13, 0.02)] // fathom secret green + [DataRow("EFDFBB", 0.907, 0, 0.05)] // dutch white + [DataRow("5218FA", 0.489, 0.05, -0.28)] // han purple + [DataRow("FF496C", 0.675, 0.21, 0.05)] // infra red + [DataRow("545AA7", 0.5, 0.02, -0.12)] // liberty + [DataRow("E6A8D7", 0.804, 0.09, -0.04)] // light orchid + [DataRow("ADDFAD", 0.856, -0.07, 0.05)] // light moss green + [DataRow("E3F988", 0.942, -0.07, 0.12)] // mindaro + public void ColorRGBtoOklabTest(string hexValue, double lightness, double chromaticityA, double chromaticityB) + { + if (string.IsNullOrWhiteSpace(hexValue)) + { + Assert.IsNotNull(hexValue); + } + + Assert.IsTrue(hexValue.Length >= 6); + + var red = int.Parse(hexValue.AsSpan(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); + var green = int.Parse(hexValue.AsSpan(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); + var blue = int.Parse(hexValue.AsSpan(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); + + var color = Color.FromArgb(255, red, green, blue); + var result = ColorFormatHelper.ConvertToOklabColor(color); + + // lightness[0..1] + Assert.AreEqual(lightness, Math.Round(result.Lightness, 3)); + + // chromaticityA[-0.5..0.5] + Assert.AreEqual(chromaticityA, Math.Round(result.ChromaticityA, 2)); + + // chromaticityB[-0.5..0.5] + Assert.AreEqual(chromaticityB, Math.Round(result.ChromaticityB, 2)); + } + + // Test data calculated using https://oklch.com (which uses https://github.com/Evercoder/culori) + [TestMethod] + [DataRow("FFFFFF", 1.00, 0.00, 0.00)] // white + [DataRow("808080", 0.6, 0.00, 0.00)] // gray + [DataRow("000000", 0.00, 0.00, 0.00)] // black + [DataRow("FF0000", 0.628, 0.258, 29.23)] // red + [DataRow("008000", 0.52, 0.177, 142.5)] // green + [DataRow("80FFFF", 0.928, 0.113, 195.38)] // cyan + [DataRow("8080FF", 0.661, 0.184, 280.13)] // blue + [DataRow("BF40BF", 0.598, 0.216, 327.86)] // magenta + [DataRow("BFBF00", 0.779, 0.17, 109.77)] // yellow + [DataRow("0048BA", 0.444, 0.19, 260.86)] // absolute zero + [DataRow("B0BF1A", 0.767, 0.169, 115.4)] // acid green + [DataRow("D0FF14", 0.934, 0.224, 122.28)] // arctic lime + [DataRow("1B4D3E", 0.382, 0.06, 170.28)] // brunswick green + [DataRow("FFEF00", 0.935, 0.198, 104.67)] // canary yellow + [DataRow("FFA600", 0.794, 0.171, 71.19)] // cheese + [DataRow("1A2421", 0.25, 0.015, 174.74)] // dark jungle green + [DataRow("003399", 0.371, 0.173, 262.12)] // dark powder blue + [DataRow("D70A53", 0.563, 0.222, 11.5)] // debian red + [DataRow("80FFD5", 0.916, 0.129, 169.38)] // fathom secret green + [DataRow("EFDFBB", 0.907, 0.05, 86.89)] // dutch white + [DataRow("5218FA", 0.489, 0.286, 279.13)] // han purple + [DataRow("FF496C", 0.675, 0.217, 14.37)] // infra red + [DataRow("545AA7", 0.5, 0.121, 277.7)] // liberty + [DataRow("E6A8D7", 0.804, 0.095, 335.4)] // light orchid + [DataRow("ADDFAD", 0.856, 0.086, 144.78)] // light moss green + [DataRow("E3F988", 0.942, 0.141, 118.24)] // mindaro + public void ColorRGBtoOklchTest(string hexValue, double lightness, double chroma, double hue) + { + if (string.IsNullOrWhiteSpace(hexValue)) + { + Assert.IsNotNull(hexValue); + } + + Assert.IsTrue(hexValue.Length >= 6); + + var red = int.Parse(hexValue.AsSpan(0, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); + var green = int.Parse(hexValue.AsSpan(2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); + var blue = int.Parse(hexValue.AsSpan(4, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); + + var color = Color.FromArgb(255, red, green, blue); + var result = ColorFormatHelper.ConvertToOklchColor(color); + + // lightness[0..1] + Assert.AreEqual(lightness, Math.Round(result.Lightness, 3)); + + // chroma[0..0.5] + Assert.AreEqual(chroma, Math.Round(result.Chroma, 3)); + + // hue[0°..360°] + Assert.AreEqual(hue, Math.Round(result.Hue, 2)); } // The following results are computed using LittleCMS2, an open-source color management engine, @@ -428,9 +533,6 @@ namespace Microsoft.ColorPicker.UnitTests [DataRow("8080FF", 34.6688, 27.2469, 98.0434)] // blue [DataRow("BF40BF", 32.7217, 18.5062, 51.1405)] // magenta [DataRow("BFBF00", 40.1154, 48.3384, 7.2171)] // yellow - [DataRow("008000", 7.7188, 15.4377, 2.5729)] // green - [DataRow("8080FF", 34.6688, 27.2469, 98.0434)] // blue - [DataRow("BF40BF", 32.7217, 18.5062, 51.1405)] // magenta [DataRow("0048BA", 11.1792, 8.1793, 47.4455)] // absolute zero [DataRow("B0BF1A", 36.7205, 46.5663, 8.0311)] // acid green [DataRow("D0FF14", 61.8965, 84.9797, 13.8037)] // arctic lime diff --git a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs index a96310dc82..f1f0c99e3d 100644 --- a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs +++ b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs @@ -23,8 +23,10 @@ namespace Microsoft.ColorPicker.UnitTests [DataRow("HSV", "hsv(0, 0%, 0%)")] [DataRow("HWB", "hwb(0, 0%, 100%)")] [DataRow("RGB", "rgb(0, 0, 0)")] - [DataRow("CIELAB", "CIELab(0, 0, 0)")] [DataRow("CIEXYZ", "XYZ(0, 0, 0)")] + [DataRow("CIELAB", "CIELab(0, 0, 0)")] + [DataRow("Oklab", "oklab(0, 0, 0)")] + [DataRow("Oklch", "oklch(0, 0, 0)")] [DataRow("VEC4", "(0f, 0f, 0f, 1f)")] [DataRow("Decimal", "0")] [DataRow("HEX Int", "0xFF000000")] diff --git a/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs b/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs index 0d3fc918d6..b82ef56888 100644 --- a/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs +++ b/src/settings-ui/Settings.UI.Library/ColorPickerProperties.cs @@ -32,8 +32,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library VisibleColorFormats.Add("HSI", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("HSI"))); VisibleColorFormats.Add("HWB", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("HWB"))); VisibleColorFormats.Add("NCol", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("NCol"))); - VisibleColorFormats.Add("CIELAB", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("CIELAB"))); VisibleColorFormats.Add("CIEXYZ", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("CIEXYZ"))); + VisibleColorFormats.Add("CIELAB", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("CIELAB"))); + VisibleColorFormats.Add("Oklab", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("Oklab"))); + VisibleColorFormats.Add("Oklch", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("Oklch"))); VisibleColorFormats.Add("VEC4", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("VEC4"))); VisibleColorFormats.Add("Decimal", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("Decimal"))); VisibleColorFormats.Add("HEX Int", new KeyValuePair(false, ColorFormatHelper.GetDefaultFormat("HEX Int"))); diff --git a/src/settings-ui/Settings.UI.Library/Enumerations/ColorRepresentationType.cs b/src/settings-ui/Settings.UI.Library/Enumerations/ColorRepresentationType.cs index 09ef003e88..7e57f5a730 100644 --- a/src/settings-ui/Settings.UI.Library/Enumerations/ColorRepresentationType.cs +++ b/src/settings-ui/Settings.UI.Library/Enumerations/ColorRepresentationType.cs @@ -80,5 +80,20 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations /// Color presentation as an 8-digit hexadecimal integer (0xFFFFFFFF) /// HexInteger = 13, + + /// + /// Color representation as CIELCh color space (L[0..100], C[0..230], h[0°..360°]) + /// + CIELCh = 14, + + /// + /// Color representation as Oklab color space (L[0..1], a[-0.5..0.5], b[-0.5..0.5]) + /// + Oklab = 15, + + /// + /// Color representation as Oklch color space (L[0..1], C[0..0.5], h[0°..360°]) + /// + Oklch = 16, } } diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml index 32f0ee488e..ea6d1c9f22 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml @@ -32,7 +32,8 @@ Style="{StaticResource CaptionTextBlockStyle}" Text="{x:Bind Description}" TextTrimming="CharacterEllipsis" - TextWrapping="NoWrap" /> + TextWrapping="NoWrap" + ToolTipService.ToolTip="{x:Bind Description}" /> diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml.cs index 76681d8b46..475d399674 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml.cs +++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ColorFormatEditor.xaml.cs @@ -47,12 +47,17 @@ namespace Microsoft.PowerToys.Settings.UI.Controls new ColorFormatParameter() { Parameter = "%In", Description = resourceLoader.GetString("Help_intensity") }, new ColorFormatParameter() { Parameter = "%Hn", Description = resourceLoader.GetString("Help_hueNat") }, new ColorFormatParameter() { Parameter = "%Ll", Description = resourceLoader.GetString("Help_lightnessNat") }, - new ColorFormatParameter() { Parameter = "%Lc", Description = resourceLoader.GetString("Help_lightnessCIE") }, new ColorFormatParameter() { Parameter = "%Va", Description = resourceLoader.GetString("Help_value") }, new ColorFormatParameter() { Parameter = "%Wh", Description = resourceLoader.GetString("Help_whiteness") }, new ColorFormatParameter() { Parameter = "%Bn", Description = resourceLoader.GetString("Help_blackness") }, - new ColorFormatParameter() { Parameter = "%Ca", Description = resourceLoader.GetString("Help_chromaticityA") }, - new ColorFormatParameter() { Parameter = "%Cb", Description = resourceLoader.GetString("Help_chromaticityB") }, + new ColorFormatParameter() { Parameter = "%Lc", Description = resourceLoader.GetString("Help_lightnessCIE") }, + new ColorFormatParameter() { Parameter = "%Ca", Description = resourceLoader.GetString("Help_chromaticityACIE") }, + new ColorFormatParameter() { Parameter = "%Cb", Description = resourceLoader.GetString("Help_chromaticityBCIE") }, + new ColorFormatParameter() { Parameter = "%Lo", Description = resourceLoader.GetString("Help_lightnessOklab") }, + new ColorFormatParameter() { Parameter = "%Oa", Description = resourceLoader.GetString("Help_chromaticityAOklab") }, + new ColorFormatParameter() { Parameter = "%Ob", Description = resourceLoader.GetString("Help_chromaticityBOklab") }, + new ColorFormatParameter() { Parameter = "%Oc", Description = resourceLoader.GetString("Help_chromaOklch") }, + new ColorFormatParameter() { Parameter = "%Oh", Description = resourceLoader.GetString("Help_hueOklch") }, new ColorFormatParameter() { Parameter = "%Xv", Description = resourceLoader.GetString("Help_X_value") }, new ColorFormatParameter() { Parameter = "%Yv", Description = resourceLoader.GetString("Help_Y_value") }, new ColorFormatParameter() { Parameter = "%Zv", Description = resourceLoader.GetString("Help_Z_value") }, diff --git a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw index a95cdb86cd..694603707c 100644 --- a/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw +++ b/src/settings-ui/Settings.UI/Strings/en-us/Resources.resw @@ -1660,11 +1660,11 @@ Made with 💗 by Microsoft and the PowerToys community. blackness - - chromaticityA + + chromaticity A (CIE Lab) - - chromaticityB + + chromaticity B (CIE Lab) X value @@ -4460,7 +4460,7 @@ Activate by holding the key for the character you want to add an accent to, then Commonly used variables New+ commonly used variables header in the flyout info card - + Year, represented by a full four or five digits, depending on the calendar used. New+ description of the year $YYYY variable - casing of $YYYY is important @@ -4999,4 +4999,25 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m Go to Command Palette settings to customize the activation shortcut. + + chroma (CIE LCh) + + + hue (CIE LCh) + + + lightness (Oklab/Oklch) + + + chromaticity A (Oklab) + + + chromaticity B (Oklab) + + + chroma (Oklch) + + + hue (Oklch) + \ No newline at end of file From 7dc2a05c45e6be92c02f284870c4b2a8159427ae Mon Sep 17 00:00:00 2001 From: Corey Hayward <72159232+CoreyHayward@users.noreply.github.com> Date: Fri, 25 Apr 2025 05:27:54 +0100 Subject: [PATCH 63/70] [PTRun] Allow preventing usage based ordering results (#37491) * Allow preventing selected result data retrieval * Updated implementation to calculate sort order on result and update property name to better reflect purpose * Update Result.cs sort order method name Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> * Align with the name GetSortOrderScore --------- Co-authored-by: Heiko <61519853+htcfreek@users.noreply.github.com> Co-authored-by: Gordon Lam (SH) --- .../PowerLauncher/ViewModel/ResultsViewModel.cs | 4 ++-- src/modules/launcher/Wox.Plugin/Result.cs | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/modules/launcher/PowerLauncher/ViewModel/ResultsViewModel.cs b/src/modules/launcher/PowerLauncher/ViewModel/ResultsViewModel.cs index 02e6138b30..64a52e8385 100644 --- a/src/modules/launcher/PowerLauncher/ViewModel/ResultsViewModel.cs +++ b/src/modules/launcher/PowerLauncher/ViewModel/ResultsViewModel.cs @@ -282,11 +282,11 @@ namespace PowerLauncher.ViewModel if (options.SearchQueryTuningEnabled) { - sorted = Results.OrderByDescending(x => (x.Result.Metadata.WeightBoost + x.Result.Score + (x.Result.SelectedCount * options.SearchClickedItemWeight))).ToList(); + sorted = Results.OrderByDescending(x => x.Result.GetSortOrderScore(options.SearchClickedItemWeight)).ToList(); } else { - sorted = Results.OrderByDescending(x => (x.Result.Metadata.WeightBoost + x.Result.Score + (x.Result.SelectedCount * 5))).ToList(); + sorted = Results.OrderByDescending(x => x.Result.GetSortOrderScore(5)).ToList(); } // remove history items in they are in the list as non-history items diff --git a/src/modules/launcher/Wox.Plugin/Result.cs b/src/modules/launcher/Wox.Plugin/Result.cs index 91f026bbb2..3bbb6dbf5e 100644 --- a/src/modules/launcher/Wox.Plugin/Result.cs +++ b/src/modules/launcher/Wox.Plugin/Result.cs @@ -187,5 +187,20 @@ namespace Wox.Plugin /// Gets plugin ID that generated this result /// public string PluginID { get; internal set; } + + /// + /// Gets or sets a value indicating whether usage based sorting should be applied to this result. + /// + public bool DisableUsageBasedScoring { get; set; } + + public int GetSortOrderScore(int selectedItemMultiplier) + { + if (DisableUsageBasedScoring) + { + return Metadata.WeightBoost + Score; + } + + return Metadata.WeightBoost + Score + (SelectedCount * selectedItemMultiplier); + } } } From 9a6c64f9c0c24dbffb560dfd848c00f18812987d Mon Sep 17 00:00:00 2001 From: Yu Leng <42196638+moooyo@users.noreply.github.com> Date: Fri, 25 Apr 2025 16:22:50 +0800 Subject: [PATCH 64/70] [cmdpal] [AOT] make Clipboard/System/WebSearch/WindowsSettings ext become AOT compatible. (#39080) Co-authored-by: Yu Leng (from Dev Box) --- .../Helpers/NativeMethods.cs | 2 +- ...crosoft.CmdPal.Ext.ClipboardHistory.csproj | 1 + .../Helpers/NetworkConnectionProperties.cs | 10 ++++----- .../Microsoft.CmdPal.Ext.System.csproj | 1 + .../Helpers/HistoryItem.cs | 2 +- .../Helpers/SettingsManager.cs | 10 ++++----- .../WebSearchJsonSerializationContext.cs | 20 +++++++++++++++++ .../Microsoft.CmdPal.Ext.WebSearch.csproj | 1 + .../Helpers/JsonSettingsListHelper.cs | 12 +++++----- .../JsonSerializationContext.cs | 22 +++++++++++++++++++ ...icrosoft.CmdPal.Ext.WindowsSettings.csproj | 1 + 11 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/WebSearchJsonSerializationContext.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/JsonSerializationContext.cs diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/NativeMethods.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/NativeMethods.cs index 50ff346103..f4b6089229 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/NativeMethods.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/NativeMethods.cs @@ -17,7 +17,7 @@ internal static class NativeMethods internal INPUTTYPE type; internal InputUnion data; - internal static int Size => Marshal.SizeOf(typeof(INPUT)); + internal static int Size => Marshal.SizeOf(); } [StructLayout(LayoutKind.Explicit)] diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj index 1d583e279b..774753f31d 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Microsoft.CmdPal.Ext.ClipboardHistory.csproj @@ -1,5 +1,6 @@  + Microsoft.CmdPal.Ext.ClipboardHistory $(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs index 9afb39b6f1..486eeaa8b5 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/NetworkConnectionProperties.cs @@ -311,14 +311,14 @@ internal sealed class NetworkConnectionProperties { switch (property) { - case string: - return string.IsNullOrWhiteSpace(property) ? string.Empty : $"\n\n{title}{property}"; + case string str: + return string.IsNullOrWhiteSpace(str) ? string.Empty : $"\n\n{title}{str}"; case List listString: - return listString.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", property)}"; + return listString.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", listString)}"; case List listIP: - return listIP.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", property)}"; + return listIP.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", listIP)}"; case IPAddressCollection collectionIP: - return collectionIP.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", property)}"; + return collectionIP.Count == 0 ? string.Empty : $"\n\n{title}{string.Join("\n\n* ", collectionIP)}"; case null: return string.Empty; default: diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj index 4c619bc5e5..48e9d6ba82 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Microsoft.CmdPal.Ext.System.csproj @@ -1,5 +1,6 @@  + enable Microsoft.CmdPal.Ext.System diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/HistoryItem.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/HistoryItem.cs index 84a1c249ba..d381c1e4cc 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/HistoryItem.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/HistoryItem.cs @@ -13,5 +13,5 @@ public class HistoryItem(string searchString, DateTime timestamp) public DateTime Timestamp { get; private set; } = timestamp; - public string ToJson() => JsonSerializer.Serialize(this); + public string ToJson() => JsonSerializer.Serialize(this, WebSearchJsonSerializationContext.Default.HistoryItem); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs index b83ba47a73..8a39bca35b 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/SettingsManager.cs @@ -80,7 +80,7 @@ public class SettingsManager : JsonSettingsManager if (File.Exists(_historyPath)) { var existingContent = File.ReadAllText(_historyPath); - historyItems = JsonSerializer.Deserialize>(existingContent) ?? []; + historyItems = JsonSerializer.Deserialize>(existingContent, WebSearchJsonSerializationContext.Default.ListHistoryItem) ?? []; } else { @@ -101,7 +101,7 @@ public class SettingsManager : JsonSettingsManager } // Serialize the updated list back to JSON and save it - var historyJson = JsonSerializer.Serialize(historyItems); + var historyJson = JsonSerializer.Serialize(historyItems, WebSearchJsonSerializationContext.Default.ListHistoryItem); File.WriteAllText(_historyPath, historyJson); } catch (Exception ex) @@ -121,7 +121,7 @@ public class SettingsManager : JsonSettingsManager // Read and deserialize JSON into a list of HistoryItem objects var fileContent = File.ReadAllText(_historyPath); - var historyItems = JsonSerializer.Deserialize>(fileContent) ?? []; + var historyItems = JsonSerializer.Deserialize>(fileContent, WebSearchJsonSerializationContext.Default.ListHistoryItem) ?? []; // Convert each HistoryItem to a ListItem var listItems = new List(); @@ -198,7 +198,7 @@ public class SettingsManager : JsonSettingsManager if (File.Exists(_historyPath)) { var existingContent = File.ReadAllText(_historyPath); - var historyItems = JsonSerializer.Deserialize>(existingContent) ?? []; + var historyItems = JsonSerializer.Deserialize>(existingContent, WebSearchJsonSerializationContext.Default.ListHistoryItem) ?? []; // Check if trimming is needed if (historyItems.Count > maxHistoryItems) @@ -207,7 +207,7 @@ public class SettingsManager : JsonSettingsManager historyItems = historyItems.Skip(historyItems.Count - maxHistoryItems).ToList(); // Save the trimmed history back to the file - var trimmedHistoryJson = JsonSerializer.Serialize(historyItems); + var trimmedHistoryJson = JsonSerializer.Serialize(historyItems, WebSearchJsonSerializationContext.Default.ListHistoryItem); File.WriteAllText(_historyPath, trimmedHistoryJson); } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/WebSearchJsonSerializationContext.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/WebSearchJsonSerializationContext.cs new file mode 100644 index 0000000000..443c9cdf40 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Helpers/WebSearchJsonSerializationContext.cs @@ -0,0 +1,20 @@ +// 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.Collections.Generic; +using System.Text.Json.Serialization; +using Microsoft.CmdPal.Ext.WebSearch.Helpers; + +namespace Microsoft.CmdPal.Ext.WebSearch; + +[JsonSerializable(typeof(float))] +[JsonSerializable(typeof(int))] +[JsonSerializable(typeof(string))] +[JsonSerializable(typeof(bool))] +[JsonSerializable(typeof(HistoryItem))] +[JsonSerializable(typeof(List))] +[JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true, IncludeFields = true, PropertyNameCaseInsensitive = true, AllowTrailingCommas = true)] +internal sealed partial class WebSearchJsonSerializationContext : JsonSerializerContext +{ +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj index 3ddedfcd71..3fbaeb30a7 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WebSearch/Microsoft.CmdPal.Ext.WebSearch.csproj @@ -1,5 +1,6 @@  + Microsoft.CmdPal.Ext.WebSearch enable diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/JsonSettingsListHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/JsonSettingsListHelper.cs index f99f0ce3b3..18b2548ce2 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/JsonSettingsListHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Helpers/JsonSettingsListHelper.cs @@ -4,10 +4,8 @@ using System; using System.IO; -using System.Linq; using System.Reflection; using System.Text.Json; -using System.Text.Json.Serialization; namespace Microsoft.CmdPal.Ext.WindowsSettings.Helpers; @@ -21,6 +19,8 @@ internal static class JsonSettingsListHelper /// private const string _settingsFile = "WindowsSettings.json"; + private const string _extTypeNamespace = "Microsoft.CmdPal.Ext.WindowsSettings"; + private static readonly JsonSerializerOptions _serializerOptions = new() { }; @@ -32,7 +32,6 @@ internal static class JsonSettingsListHelper internal static Classes.WindowsSettings ReadAllPossibleSettings() { var assembly = Assembly.GetExecutingAssembly(); - var type = assembly.GetTypes().FirstOrDefault(x => x.Name == nameof(WindowsSettingsCommandsProvider)); #pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context. Classes.WindowsSettings? settings = null; @@ -40,7 +39,7 @@ internal static class JsonSettingsListHelper try { - var resourceName = $"{type?.Namespace}.{_settingsFile}"; + var resourceName = $"{_extTypeNamespace}.{_settingsFile}"; using var stream = assembly.GetManifestResourceStream(resourceName); if (stream is null) { @@ -48,12 +47,13 @@ internal static class JsonSettingsListHelper } var options = _serializerOptions; - options.Converters.Add(new JsonStringEnumConverter()); + // Why we need it? I don't see any enum usage in WindowsSettings + // options.Converters.Add(new JsonStringEnumConverter()); using var reader = new StreamReader(stream); var text = reader.ReadToEnd(); - settings = JsonSerializer.Deserialize(text, options); + settings = JsonSerializer.Deserialize(text, WindowsSettingsJsonSerializationContext.Default.WindowsSettings); } #pragma warning disable CS0168 catch (Exception exception) diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/JsonSerializationContext.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/JsonSerializationContext.cs new file mode 100644 index 0000000000..e267e8f52e --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/JsonSerializationContext.cs @@ -0,0 +1,22 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json.Serialization; +using System.Threading.Tasks; + +namespace Microsoft.CmdPal.Ext.WindowsSettings; + +[JsonSerializable(typeof(float))] +[JsonSerializable(typeof(int))] +[JsonSerializable(typeof(string))] +[JsonSerializable(typeof(bool))] +[JsonSerializable(typeof(Classes.WindowsSettings))] +[JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true, IncludeFields = true, PropertyNameCaseInsensitive = true, AllowTrailingCommas = true)] +internal sealed partial class WindowsSettingsJsonSerializationContext : JsonSerializerContext +{ +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj index d44e907606..9f2d72bc8a 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsSettings/Microsoft.CmdPal.Ext.WindowsSettings.csproj @@ -1,5 +1,6 @@  + Microsoft.CmdPal.Ext.WindowsSettings $(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal From 30df5e0df298d5fe7f3699c517cc37a6bb7cfa93 Mon Sep 17 00:00:00 2001 From: Gordon Lam <73506701+yeelam-gordon@users.noreply.github.com> Date: Sat, 26 Apr 2025 17:59:44 -0700 Subject: [PATCH 65/70] Update the ADO path for tsa.json (#39079) The previous ADO area path for Powertoys was gone, we need to update to new one. --- .pipelines/tsa.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pipelines/tsa.json b/.pipelines/tsa.json index 351545613f..2f1e84c7f1 100644 --- a/.pipelines/tsa.json +++ b/.pipelines/tsa.json @@ -3,5 +3,5 @@ "notificationAliases": ["powertoys@microsoft.com"], "instanceUrl": "https://microsoft.visualstudio.com", "projectName": "OS", - "areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\SHINE\\PowerToys" + "areaPath": "OS\\Windows Client and Services\\WinPD\\DEEP-Developer Experience, Ecosystem and Partnerships\\DIVE\\PowerToys" } From ba230eca070322c2010f5e0a304229691882bc7b Mon Sep 17 00:00:00 2001 From: Clint Rutkas Date: Sun, 27 Apr 2025 05:44:47 +0000 Subject: [PATCH 66/70] Start progress on AoT. (#39051) * starting AoT flag push * Few more * bookmarks * Really? The VM project compiles? * Disable publish AOT before we really testing it. --------- Co-authored-by: Mike Griese Co-authored-by: Yu Leng (from Dev Box) --- .../AppStateModel.cs | 33 +++++++------- .../Commands/CreatedExtensionForm.cs | 15 ++++--- .../Commands/NewExtensionForm.cs | 7 ++- .../ContentFormViewModel.cs | 11 ++--- .../Microsoft.CmdPal.UI.ViewModels.csproj | 13 ++++++ .../Models/ExtensionService.cs | 2 +- .../Models/ExtensionWrapper.cs | 42 ++++++++++------- .../NativeMethods.json | 4 ++ .../PageViewModel.cs | 2 +- .../RecentCommandsManager.cs | 2 +- .../SettingsModel.cs | 45 ++++++++++++------- .../ShellViewModel.cs | 7 ++- .../AddBookmarkForm.cs | 4 +- .../BookmarkSerializationContext.cs | 20 +++++++++ .../Bookmarks.cs | 4 +- .../Microsoft.CmdPal.Ext.Bookmarks.csproj | 7 +-- .../JsonSerializationContext.cs | 1 - 17 files changed, 144 insertions(+), 75 deletions(-) create mode 100644 src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/NativeMethods.json create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkSerializationContext.cs diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AppStateModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AppStateModel.cs index 69d38a8655..649e49fbc7 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AppStateModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AppStateModel.cs @@ -49,7 +49,7 @@ public partial class AppStateModel : ObservableObject // Read the JSON content from the file var jsonContent = File.ReadAllText(FilePath); - var loaded = JsonSerializer.Deserialize(jsonContent, _deserializerOptions); + var loaded = JsonSerializer.Deserialize(jsonContent, JsonSerializationContext.Default.AppStateModel); Debug.WriteLine(loaded != null ? "Loaded settings file" : "Failed to parse"); @@ -73,7 +73,7 @@ public partial class AppStateModel : ObservableObject try { // Serialize the main dictionary to JSON and save it to the file - var settingsJson = JsonSerializer.Serialize(model, _serializerOptions); + var settingsJson = JsonSerializer.Serialize(model, JsonSerializationContext.Default.AppStateModel); // Is it valid JSON? if (JsonNode.Parse(settingsJson) is JsonObject newSettings) @@ -89,7 +89,7 @@ public partial class AppStateModel : ObservableObject savedSettings[item.Key] = item.Value != null ? item.Value.DeepClone() : null; } - var serialized = savedSettings.ToJsonString(_serializerOptions); + var serialized = savedSettings.ToJsonString(JsonSerializationContext.Default.AppStateModel.Options); File.WriteAllText(FilePath, serialized); // TODO: Instead of just raising the event here, we should @@ -122,18 +122,19 @@ public partial class AppStateModel : ObservableObject return Path.Combine(directory, "state.json"); } - private static readonly JsonSerializerOptions _serializerOptions = new() - { - WriteIndented = true, - Converters = { new JsonStringEnumConverter() }, - }; + // [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")] + // private static readonly JsonSerializerOptions _serializerOptions = new() + // { + // WriteIndented = true, + // Converters = { new JsonStringEnumConverter() }, + // }; - private static readonly JsonSerializerOptions _deserializerOptions = new() - { - PropertyNameCaseInsensitive = true, - IncludeFields = true, - AllowTrailingCommas = true, - PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate, - ReadCommentHandling = JsonCommentHandling.Skip, - }; + // private static readonly JsonSerializerOptions _deserializerOptions = new() + // { + // PropertyNameCaseInsensitive = true, + // IncludeFields = true, + // AllowTrailingCommas = true, + // PreferredObjectCreationHandling = JsonObjectCreationHandling.Populate, + // ReadCommentHandling = JsonCommentHandling.Skip, + // }; } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs index 1939162662..44bcb49cb3 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/CreatedExtensionForm.cs @@ -13,12 +13,13 @@ internal sealed partial class CreatedExtensionForm : NewExtensionFormBase { public CreatedExtensionForm(string name, string displayName, string path) { + var serializeString = (string? s) => JsonSerializer.Serialize(s, JsonSerializationContext.Default.String); TemplateJson = CardTemplate; DataJson = $$""" { - "name": {{JsonSerializer.Serialize(name)}}, - "directory": {{JsonSerializer.Serialize(path)}}, - "displayName": {{JsonSerializer.Serialize(displayName)}} + "name": {{serializeString(name)}}, + "directory": {{serializeString(path)}}, + "displayName": {{serializeString(displayName)}} } """; _name = name; @@ -28,13 +29,13 @@ internal sealed partial class CreatedExtensionForm : NewExtensionFormBase public override ICommandResult SubmitForm(string inputs, string data) { - JsonObject? dataInput = JsonNode.Parse(data)?.AsObject(); + var dataInput = JsonNode.Parse(data)?.AsObject(); if (dataInput == null) { return CommandResult.KeepOpen(); } - string verb = dataInput["x"]?.AsValue()?.ToString() ?? string.Empty; + var verb = dataInput["x"]?.AsValue()?.ToString() ?? string.Empty; return verb switch { "sln" => OpenSolution(), @@ -47,7 +48,7 @@ internal sealed partial class CreatedExtensionForm : NewExtensionFormBase private ICommandResult OpenSolution() { string[] parts = [_path, _name, $"{_name}.sln"]; - string pathToSolution = Path.Combine(parts); + var pathToSolution = Path.Combine(parts); ShellHelpers.OpenInShell(pathToSolution); return CommandResult.Hide(); } @@ -55,7 +56,7 @@ internal sealed partial class CreatedExtensionForm : NewExtensionFormBase private ICommandResult OpenDirectory() { string[] parts = [_path, _name]; - string pathToDir = Path.Combine(parts); + var pathToDir = Path.Combine(parts); ShellHelpers.OpenInShell(pathToDir); return CommandResult.Hide(); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs index 698faf0335..aca45f3494 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Commands/NewExtensionForm.cs @@ -194,9 +194,8 @@ internal sealed partial class NewExtensionForm : NewExtensionFormBase Directory.Delete(tempDir, true); } - private string FormatJsonString(string str) - { + private string FormatJsonString(string str) => + // Escape the string for JSON - return JsonSerializer.Serialize(str); - } + JsonSerializer.Serialize(str, JsonSerializationContext.Default.String); } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs index e1bbe0b604..5af1959cd6 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ContentFormViewModel.cs @@ -51,15 +51,16 @@ public partial class ContentFormViewModel(IFormContent _form, WeakReference JsonSerializer.Serialize(s, JsonSerializationContext.Default.String); // todo: we could probably stick Card.Errors in there too var dataJson = $$""" { - "error_message": {{JsonSerializer.Serialize(e.Message)}}, - "error_stack": {{JsonSerializer.Serialize(e.StackTrace)}}, - "inner_exception": {{JsonSerializer.Serialize(e.InnerException?.Message)}}, - "template_json": {{JsonSerializer.Serialize(TemplateJson)}}, - "data_json": {{JsonSerializer.Serialize(DataJson)}} + "error_message": {{serializeString(e.Message)}}, + "error_stack": {{serializeString(e.StackTrace)}}, + "inner_exception": {{serializeString(e.InnerException?.Message)}}, + "template_json": {{serializeString(TemplateJson)}}, + "data_json": {{serializeString(DataJson)}} } """; var cardJson = template.Expand(dataJson); diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj index 342dbe251c..8057bb09be 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Microsoft.CmdPal.UI.ViewModels.csproj @@ -1,5 +1,7 @@  + + enable enable @@ -67,4 +69,15 @@ + + + diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionService.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionService.cs index 576ea08140..6d59aa66b4 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionService.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionService.cs @@ -11,7 +11,7 @@ using Windows.Foundation.Collections; namespace Microsoft.CmdPal.UI.ViewModels.Models; -public class ExtensionService : IExtensionService, IDisposable +public partial class ExtensionService : IExtensionService, IDisposable { public event TypedEventHandler>? OnExtensionAdded; diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionWrapper.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionWrapper.cs index ed15268507..83644c8d44 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionWrapper.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Models/ExtensionWrapper.cs @@ -12,6 +12,7 @@ using Windows.Win32; using Windows.Win32.System.Com; using WinRT; +// [assembly: System.Runtime.CompilerServices.DisableRuntimeMarshalling] namespace Microsoft.CmdPal.UI.ViewModels.Models; public class ExtensionWrapper : IExtensionWrapper @@ -113,25 +114,36 @@ public class ExtensionWrapper : IExtensionWrapper // -2147467262: E_NOINTERFACE // -2147024893: E_PATH_NOT_FOUND var guid = typeof(IExtension).GUID; - var hr = PInvoke.CoCreateInstance(Guid.Parse(ExtensionClassId), null, CLSCTX.CLSCTX_LOCAL_SERVER, guid, out var extensionObj); - if (hr.Value == -2147024893) + unsafe { - Logger.LogDebug($"Failed to find {ExtensionDisplayName}: {hr}. It may have been uninstalled or deleted."); + var hr = PInvoke.CoCreateInstance(Guid.Parse(ExtensionClassId), null, CLSCTX.CLSCTX_LOCAL_SERVER, guid, out var extensionObj); - // We don't really need to throw this exception. - // We'll just return out nothing. - return; + if (hr.Value == -2147024893) + { + Logger.LogDebug($"Failed to find {ExtensionDisplayName}: {hr}. It may have been uninstalled or deleted."); + + // We don't really need to throw this exception. + // We'll just return out nothing. + return; + } + + extensionPtr = Marshal.GetIUnknownForObject((nint)extensionObj); + if (hr < 0) + { + Logger.LogDebug($"Failed to instantiate {ExtensionDisplayName}: {hr}"); + Marshal.ThrowExceptionForHR(hr); + } + + // extensionPtr = Marshal.GetIUnknownForObject(extensionObj); + extensionPtr = (nint)extensionObj; + if (hr < 0) + { + Marshal.ThrowExceptionForHR(hr); + } + + _extensionObject = MarshalInterface.FromAbi(extensionPtr); } - - extensionPtr = Marshal.GetIUnknownForObject(extensionObj); - if (hr < 0) - { - Logger.LogDebug($"Failed to instantiate {ExtensionDisplayName}: {hr}"); - Marshal.ThrowExceptionForHR(hr); - } - - _extensionObject = MarshalInterface.FromAbi(extensionPtr); } finally { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/NativeMethods.json b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/NativeMethods.json new file mode 100644 index 0000000000..59fa7259c4 --- /dev/null +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/NativeMethods.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://aka.ms/CsWin32.schema.json", + "allowMarshaling": false +} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/PageViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/PageViewModel.cs index a082f0acd2..9a1cda196b 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/PageViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/PageViewModel.cs @@ -99,7 +99,7 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext //// Run on background thread from ListPage.xaml.cs [RelayCommand] - private Task InitializeAsync() + internal Task InitializeAsync() { // TODO: We may want a SemaphoreSlim lock here. diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/RecentCommandsManager.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/RecentCommandsManager.cs index 9e971ae510..c740341c7a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/RecentCommandsManager.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/RecentCommandsManager.cs @@ -10,7 +10,7 @@ namespace Microsoft.CmdPal.UI.ViewModels; public partial class RecentCommandsManager : ObservableObject { [JsonInclude] - private List History { get; set; } = []; + internal List History { get; set; } = []; public RecentCommandsManager() { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs index 27dd119b48..ae97849f7a 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/SettingsModel.cs @@ -93,7 +93,7 @@ public partial class SettingsModel : ObservableObject // Read the JSON content from the file var jsonContent = File.ReadAllText(FilePath); - var loaded = JsonSerializer.Deserialize(jsonContent, _deserializerOptions); + var loaded = JsonSerializer.Deserialize(jsonContent, JsonSerializationContext.Default.SettingsModel); Debug.WriteLine(loaded != null ? "Loaded settings file" : "Failed to parse"); @@ -117,7 +117,7 @@ public partial class SettingsModel : ObservableObject try { // Serialize the main dictionary to JSON and save it to the file - var settingsJson = JsonSerializer.Serialize(model, _serializerOptions); + var settingsJson = JsonSerializer.Serialize(model, JsonSerializationContext.Default.SettingsModel); // Is it valid JSON? if (JsonNode.Parse(settingsJson) is JsonObject newSettings) @@ -133,7 +133,7 @@ public partial class SettingsModel : ObservableObject savedSettings[item.Key] = item.Value != null ? item.Value.DeepClone() : null; } - var serialized = savedSettings.ToJsonString(_serializerOptions); + var serialized = savedSettings.ToJsonString(JsonSerializationContext.Default.Options); File.WriteAllText(FilePath, serialized); // TODO: Instead of just raising the event here, we should @@ -166,19 +166,34 @@ public partial class SettingsModel : ObservableObject return Path.Combine(directory, "settings.json"); } - private static readonly JsonSerializerOptions _serializerOptions = new() - { - WriteIndented = true, - Converters = { new JsonStringEnumConverter() }, - }; + // [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")] + // private static readonly JsonSerializerOptions _serializerOptions = new() + // { + // WriteIndented = true, + // Converters = { new JsonStringEnumConverter() }, + // }; + // private static readonly JsonSerializerOptions _deserializerOptions = new() + // { + // PropertyNameCaseInsensitive = true, + // IncludeFields = true, + // Converters = { new JsonStringEnumConverter() }, + // AllowTrailingCommas = true, + // }; +} - private static readonly JsonSerializerOptions _deserializerOptions = new() - { - PropertyNameCaseInsensitive = true, - IncludeFields = true, - Converters = { new JsonStringEnumConverter() }, - AllowTrailingCommas = true, - }; +[JsonSerializable(typeof(float))] +[JsonSerializable(typeof(int))] +[JsonSerializable(typeof(string))] +[JsonSerializable(typeof(bool))] +[JsonSerializable(typeof(HistoryItem))] +[JsonSerializable(typeof(SettingsModel))] +[JsonSerializable(typeof(AppStateModel))] +[JsonSerializable(typeof(List), TypeInfoPropertyName = "HistoryList")] +[JsonSerializable(typeof(Dictionary), TypeInfoPropertyName = "Dictionary")] +[JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true, IncludeFields = true, PropertyNameCaseInsensitive = true, AllowTrailingCommas = true)] +[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Just used here")] +internal sealed partial class JsonSerializationContext : JsonSerializerContext +{ } public enum MonitorBehavior diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ShellViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ShellViewModel.cs index 043598196b..d86831d0a1 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ShellViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ShellViewModel.cs @@ -109,9 +109,12 @@ public partial class ShellViewModel(IServiceProvider _serviceProvider, TaskSched // TODO GH #239 switch back when using the new MD text block // _ = _queue.EnqueueAsync(() => _ = Task.Factory.StartNew( - () => + async () => { - var result = (bool)viewModel.InitializeCommand.ExecutionTask.GetResultOrDefault()!; + // bool f = await viewModel.InitializeCommand.ExecutionTask.; + // var result = viewModel.InitializeCommand.ExecutionTask.GetResultOrDefault()!; + // var result = viewModel.InitializeCommand.ExecutionTask.GetResultOrDefault()!; + var result = await viewModel.InitializeAsync(); CurrentPage = viewModel; // result ? viewModel : null; ////LoadedState = result ? ViewModelLoadedState.Loaded : ViewModelLoadedState.Error; diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs index 9b3f54a21f..5da419cd40 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/AddBookmarkForm.cs @@ -34,7 +34,7 @@ internal sealed partial class AddBookmarkForm : FormContent "style": "text", "id": "name", "label": "{{Resources.bookmarks_form_name_label}}", - "value": {{JsonSerializer.Serialize(name)}}, + "value": {{JsonSerializer.Serialize(name, BookmarkSerializationContext.Default.String)}}, "isRequired": true, "errorMessage": "{{Resources.bookmarks_form_name_required}}" }, @@ -42,7 +42,7 @@ internal sealed partial class AddBookmarkForm : FormContent "type": "Input.Text", "style": "text", "id": "bookmark", - "value": {{JsonSerializer.Serialize(url)}}, + "value": {{JsonSerializer.Serialize(url, BookmarkSerializationContext.Default.String)}}, "label": "{{Resources.bookmarks_form_bookmark_label}}", "isRequired": true, "errorMessage": "{{Resources.bookmarks_form_bookmark_required}}" diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkSerializationContext.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkSerializationContext.cs new file mode 100644 index 0000000000..9730bf214d --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/BookmarkSerializationContext.cs @@ -0,0 +1,20 @@ +// 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.Collections.Generic; +using System.Text.Json.Serialization; + +namespace Microsoft.CmdPal.Ext.Bookmarks; + +[JsonSerializable(typeof(float))] +[JsonSerializable(typeof(int))] +[JsonSerializable(typeof(string))] +[JsonSerializable(typeof(bool))] +[JsonSerializable(typeof(BookmarkData))] +[JsonSerializable(typeof(Bookmarks))] +[JsonSerializable(typeof(List), TypeInfoPropertyName = "BookmarkList")] +[JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true, IncludeFields = true, PropertyNameCaseInsensitive = true, AllowTrailingCommas = true)] +internal sealed partial class BookmarkSerializationContext : JsonSerializerContext +{ +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Bookmarks.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Bookmarks.cs index 7c3a1dd1e0..8f2e257782 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Bookmarks.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Bookmarks.cs @@ -28,7 +28,7 @@ public sealed class Bookmarks if (!string.IsNullOrEmpty(jsonStringReading)) { - data = JsonSerializer.Deserialize(jsonStringReading, _jsonOptions) ?? new Bookmarks(); + data = JsonSerializer.Deserialize(jsonStringReading, BookmarkSerializationContext.Default.Bookmarks) ?? new Bookmarks(); } } @@ -37,7 +37,7 @@ public sealed class Bookmarks public static void WriteToFile(string path, Bookmarks data) { - var jsonString = JsonSerializer.Serialize(data, _jsonOptions); + var jsonString = JsonSerializer.Serialize(data, BookmarkSerializationContext.Default.Bookmarks); File.WriteAllText(BookmarksCommandProvider.StateJsonPath(), jsonString); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj index 7bbf1efc5f..40c3cca9f2 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Bookmark/Microsoft.CmdPal.Ext.Bookmarks.csproj @@ -1,5 +1,6 @@  + Microsoft.CmdPal.Ext.Bookmarks enable @@ -16,7 +17,7 @@ - + Resources.resx @@ -24,7 +25,7 @@ True - + PreserveNewest @@ -39,5 +40,5 @@ PublicResXFileCodeGenerator - + diff --git a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/JsonSerializationContext.cs b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/JsonSerializationContext.cs index 6fbc734560..6d92cdc146 100644 --- a/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/JsonSerializationContext.cs +++ b/src/modules/cmdpal/extensionsdk/Microsoft.CommandPalette.Extensions.Toolkit/JsonSerializationContext.cs @@ -16,7 +16,6 @@ namespace Microsoft.CommandPalette.Extensions.Toolkit; [JsonSerializable(typeof(List))] [JsonSerializable(typeof(Dictionary), TypeInfoPropertyName = "Dictionary")] [JsonSourceGenerationOptions(UseStringEnumConverter = true, WriteIndented = true)] -[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "Just used here")] internal partial class JsonSerializationContext : JsonSerializerContext { } From 7efbd2f01364128efaeab334f0f7b7ba0d824963 Mon Sep 17 00:00:00 2001 From: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Sun, 27 Apr 2025 13:47:56 +0800 Subject: [PATCH 67/70] [CmdPal] Launch cmd pal with retry (#39039) * Add Retry when enable * Add correct for the checking logic * Retry in another thread (#39042) * launch thread * dev * fix a thread safety * improve * improve * make code clear * Fix comment * fix comment * improve * self review * fix & log * silent fail if not reach 10 times * fix a ci build flag error * fix a macro * some simple improve --------- Co-authored-by: Gordon Lam (SH) --- .../CmdPalModuleInterface.vcxproj | 3 +- .../cmdpal/CmdPalModuleInterface/dllmain.cpp | 124 +++++++++++++----- 2 files changed, 93 insertions(+), 34 deletions(-) diff --git a/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj b/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj index 5bd12f316e..2d70013009 100644 --- a/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj +++ b/src/modules/cmdpal/CmdPalModuleInterface/CmdPalModuleInterface.vcxproj @@ -2,7 +2,7 @@ - + 17.0 Win32Proj @@ -53,7 +53,6 @@ EXAMPLEPOWERTOY_EXPORTS;_WINDOWS;_USRDLL; %(PreprocessorDefinitions); - $(CommandPaletteBranding) IS_DEV_BRANDING;%(PreprocessorDefinitions) diff --git a/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp b/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp index be3eb6a3b7..bff7279b68 100644 --- a/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp +++ b/src/modules/cmdpal/CmdPalModuleInterface/dllmain.cpp @@ -3,6 +3,7 @@ #include +#include #include #include #include @@ -10,10 +11,11 @@ #include #include #include +#include #include #include #include -#include +#include HINSTANCE g_hInst_cmdPal = 0; @@ -37,8 +39,6 @@ BOOL APIENTRY DllMain(HMODULE hInstance, class CmdPal : public PowertoyModuleIface { private: - bool m_enabled = false; - std::wstring app_name; //contains the non localized key of the powertoy @@ -46,7 +46,10 @@ private: HANDLE m_hTerminateEvent; - void LaunchApp(const std::wstring& appPath, const std::wstring& commandLineArgs, bool elevated) + // Track if this is the first call to enable + bool firstEnableCall = true; + + static bool LaunchApp(const std::wstring& appPath, const std::wstring& commandLineArgs, bool elevated, bool silentFail) { std::wstring dir = std::filesystem::path(appPath).parent_path(); @@ -54,6 +57,10 @@ private: sei.cbSize = sizeof(SHELLEXECUTEINFO); sei.hwnd = nullptr; sei.fMask = SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE; + if (silentFail) + { + sei.fMask = sei.fMask | SEE_MASK_FLAG_NO_UI; + } sei.lpVerb = elevated ? L"runas" : L"open"; sei.lpFile = appPath.c_str(); sei.lpParameters = commandLineArgs.c_str(); @@ -64,7 +71,11 @@ private: { std::wstring error = get_last_error_or_default(GetLastError()); Logger::error(L"Failed to launch process. {}", error); + return false; } + + m_launched.store(true); + return true; } std::vector GetProcessesIdByName(const std::wstring& processName) @@ -122,6 +133,9 @@ private: } public: + static std::atomic m_enabled; + static std::atomic m_launched; + CmdPal() { app_name = L"CmdPal"; @@ -133,10 +147,7 @@ public: ~CmdPal() { - if (m_enabled) - { - } - m_enabled = false; + CmdPal::m_enabled.store(false); } // Destroy the powertoy and free memory @@ -203,15 +214,18 @@ public: { Logger::trace("CmdPal::enable()"); - m_enabled = true; + CmdPal::m_enabled.store(true); - try - { - std::wstring packageName = L"Microsoft.CommandPalette"; + std::wstring packageName = L"Microsoft.CommandPalette"; + std::wstring launchPath = L"shell:AppsFolder\\Microsoft.CommandPalette_8wekyb3d8bbwe!App"; #ifdef IS_DEV_BRANDING - packageName = L"Microsoft.CommandPalette.Dev"; + packageName = L"Microsoft.CommandPalette.Dev"; + launchPath = L"shell:AppsFolder\\Microsoft.CommandPalette.Dev_8wekyb3d8bbwe!App"; #endif - if (!package::GetRegisteredPackage(packageName, false).has_value()) + + if (!package::GetRegisteredPackage(packageName, false).has_value()) + { + try { Logger::info(L"CmdPal not installed. Installing..."); @@ -238,28 +252,34 @@ public: } } } + catch (std::exception& e) + { + std::string errorMessage{ "Exception thrown while trying to install CmdPal package: " }; + errorMessage += e.what(); + Logger::error(errorMessage); + } } - catch (std::exception& e) + + if (!package::GetRegisteredPackage(packageName, false).has_value()) { - std::string errorMessage{ "Exception thrown while trying to install CmdPal package: " }; - errorMessage += e.what(); - Logger::error(errorMessage); + Logger::error("Cmdpal is not registered, quit.."); + return; } - try + + if (!firstEnableCall) { -#ifdef IS_DEV_BRANDING - LaunchApp(std::wstring{ L"shell:AppsFolder\\" } + L"Microsoft.CommandPalette.Dev_8wekyb3d8bbwe!App", L"RunFromPT", false); -#else - LaunchApp(std::wstring{ L"shell:AppsFolder\\" } + L"Microsoft.CommandPalette_8wekyb3d8bbwe!App", L"RunFromPT", false); -#endif + Logger::trace("Not first attempt, try to launch"); + LaunchApp(launchPath, L"RunFromPT", false /*no elevated*/, false /*error pop up*/); } - catch (std::exception& e) + else { - std::string errorMessage{ "Exception thrown while trying to launch CmdPal: " }; - errorMessage += e.what(); - Logger::error(errorMessage); - throw; + // If first time enable, do retry launch. + Logger::trace("First attempt, try to launch"); + std::thread launchThread(&CmdPal::RetryLaunch, launchPath); + launchThread.detach(); } + + firstEnableCall = false; } virtual void disable() @@ -267,7 +287,44 @@ public: Logger::trace("CmdPal::disable()"); TerminateCmdPal(); - m_enabled = false; + CmdPal::m_enabled.store(false); + } + + static void RetryLaunch(std::wstring path) + { + const int base_delay_milliseconds = 1000; + int max_retry = 9; // 2**9 - 1 seconds. Control total wait time within 10 min. + int retry = 0; + do + { + auto launch_result = LaunchApp(path, L"RunFromPT", false, retry < max_retry); + if (launch_result) + { + Logger::info(L"CmdPal launched successfully after {} retries.", retry); + return; + } + else + { + Logger::error(L"Retry {} launch CmdPal launch failed.", retry); + } + + // When we got max retry, we don't need to wait for the next retry. + if (retry < max_retry) + { + int delay = base_delay_milliseconds * (1 << (retry)); + std::this_thread::sleep_for(std::chrono::milliseconds(delay)); + } + ++retry; + } while (retry <= max_retry && m_enabled.load() && !m_launched.load()); + + if (!m_enabled.load() || m_launched.load()) + { + Logger::error(L"Retry cancelled. CmdPal is disabled or already launched."); + } + else + { + Logger::error(L"CmdPal launch failed after {} attempts.", retry); + } } virtual bool on_hotkey(size_t) override @@ -282,11 +339,14 @@ public: virtual bool is_enabled() override { - return m_enabled; + return CmdPal::m_enabled.load(); } }; +std::atomic CmdPal::m_enabled{ false }; +std::atomic CmdPal::m_launched{ false }; + extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create() { return new CmdPal(); -} +} \ No newline at end of file From 49e5bbb5f070cdab49fb334bb5b18236f0e234a3 Mon Sep 17 00:00:00 2001 From: Yu Leng <42196638+moooyo@users.noreply.github.com> Date: Sun, 27 Apr 2025 17:18:01 +0800 Subject: [PATCH 68/70] [cmdpal][aot] Remove some unused file in CmdPal.Common and mark it as AOT compatible. (#39110) * Remove unused com interface * Remove unused file * Remove unused file * Remove unused file --------- Co-authored-by: Yu Leng (from Dev Box) --- .../Contracts/IFileService.cs | 14 -- .../Contracts/ILocalSettingsService.cs | 16 --- .../Extensions/ApplicationExtensions.cs | 40 ------ .../Extensions/IHostExtensions.cs | 40 ------ .../Microsoft.CmdPal.Common/Helpers/Json.cs | 36 ------ .../Helpers/NativeEventWaiter.cs | 2 +- .../Helpers/RuntimeHelper.cs | 2 +- .../Messages/HideWindowMessage.cs | 2 +- .../Microsoft.CmdPal.Common.csproj | 1 + .../Models/LocalSettingsOptions.cs | 18 --- .../Microsoft.CmdPal.Common/NativeMethods.txt | 9 -- .../Services/FileService.cs | 48 ------- .../Microsoft.CmdPal.Common/Services/IApp.cs | 18 --- .../Services/LocalSettingsService.cs | 120 ------------------ 14 files changed, 4 insertions(+), 362 deletions(-) delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Contracts/IFileService.cs delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Contracts/ILocalSettingsService.cs delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Extensions/ApplicationExtensions.cs delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Extensions/IHostExtensions.cs delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/Json.cs delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Models/LocalSettingsOptions.cs delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Services/FileService.cs delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Services/IApp.cs delete mode 100644 src/modules/cmdpal/Microsoft.CmdPal.Common/Services/LocalSettingsService.cs diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Contracts/IFileService.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Contracts/IFileService.cs deleted file mode 100644 index b9348eb520..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Contracts/IFileService.cs +++ /dev/null @@ -1,14 +0,0 @@ -// 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.CmdPal.Common.Contracts; - -public interface IFileService -{ - T Read(string folderPath, string fileName); - - void Save(string folderPath, string fileName, T content); - - void Delete(string folderPath, string fileName); -} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Contracts/ILocalSettingsService.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Contracts/ILocalSettingsService.cs deleted file mode 100644 index 2350050e3e..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Contracts/ILocalSettingsService.cs +++ /dev/null @@ -1,16 +0,0 @@ -// 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.Threading.Tasks; - -namespace Microsoft.CmdPal.Common.Contracts; - -public interface ILocalSettingsService -{ - Task HasSettingAsync(string key); - - Task ReadSettingAsync(string key); - - Task SaveSettingAsync(string key, T value); -} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Extensions/ApplicationExtensions.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Extensions/ApplicationExtensions.cs deleted file mode 100644 index a975083c7c..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Extensions/ApplicationExtensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -// 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 Microsoft.CmdPal.Common.Services; -using Microsoft.UI.Xaml; - -namespace Microsoft.CmdPal.Common.Extensions; - -/// -/// Extension class implementing extension methods for . -/// -public static class ApplicationExtensions -{ - /// - /// Get registered services at the application level from anywhere in the - /// application. - /// - /// Note: - /// https://learn.microsoft.com/uwp/api/windows.ui.xaml.application.current?view=winrt-22621#windows-ui-xaml-application-current - /// "Application is a singleton that implements the static Current property - /// to provide shared access to the Application instance for the current - /// application. The singleton pattern ensures that state managed by - /// Application, including shared resources and properties, is available - /// from a single, shared location." - /// - /// Example of usage: - /// - /// Application.Current.GetService() - /// - /// - /// Service type. - /// Current application. - /// Service reference. - public static T GetService(this Application application) - where T : class - { - return (application as IApp)!.GetService(); - } -} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Extensions/IHostExtensions.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Extensions/IHostExtensions.cs deleted file mode 100644 index 660dcd2931..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Extensions/IHostExtensions.cs +++ /dev/null @@ -1,40 +0,0 @@ -// 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 Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; - -namespace Microsoft.CmdPal.Common.Extensions; - -public static class IHostExtensions -{ - /// - /// - /// - public static T CreateInstance(this IHost host, params object[] parameters) - { - return ActivatorUtilities.CreateInstance(host.Services, parameters); - } - - /// - /// Gets the service object for the specified type, or throws an exception - /// if type was not registered. - /// - /// Service type - /// Host object - /// Service object - /// Throw an exception if the specified - /// type is not registered - public static T GetService(this IHost host) - where T : class - { - if (host.Services.GetService(typeof(T)) is not T service) - { - throw new ArgumentException($"{typeof(T)} needs to be registered in ConfigureServices."); - } - - return service; - } -} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/Json.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/Json.cs deleted file mode 100644 index d865e10bdb..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/Json.cs +++ /dev/null @@ -1,36 +0,0 @@ -// 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.IO; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; - -namespace Microsoft.CmdPal.Common.Helpers; - -public static class Json -{ - public static async Task ToObjectAsync(string value) - { - if (typeof(T) == typeof(bool)) - { - return (T)(object)bool.Parse(value); - } - - await using var stream = new MemoryStream(Encoding.UTF8.GetBytes(value)); - return (await JsonSerializer.DeserializeAsync(stream))!; - } - - public static async Task StringifyAsync(T value) - { - if (typeof(T) == typeof(bool)) - { - return value!.ToString()!.ToLowerInvariant(); - } - - await using var stream = new MemoryStream(); - await JsonSerializer.SerializeAsync(stream, value); - return Encoding.UTF8.GetString(stream.ToArray()); - } -} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/NativeEventWaiter.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/NativeEventWaiter.cs index 6ec1885a4c..2344fbb917 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/NativeEventWaiter.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/NativeEventWaiter.cs @@ -9,7 +9,7 @@ using Microsoft.UI.Dispatching; namespace Microsoft.CmdPal.Common.Helpers; -public static class NativeEventWaiter +public static partial class NativeEventWaiter { public static void WaitForEventLoop(string eventName, Action callback) { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/RuntimeHelper.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/RuntimeHelper.cs index 46dce07e5e..342667cf83 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/RuntimeHelper.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Common/Helpers/RuntimeHelper.cs @@ -9,7 +9,7 @@ using Windows.Win32.Foundation; namespace Microsoft.CmdPal.Common.Helpers; -public static class RuntimeHelper +public static partial class RuntimeHelper { public static bool IsMSIX { diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Messages/HideWindowMessage.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Messages/HideWindowMessage.cs index ed698d1024..097aefdee9 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Messages/HideWindowMessage.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.Common/Messages/HideWindowMessage.cs @@ -4,6 +4,6 @@ namespace Microsoft.CmdPal.Common.Messages; -public record HideWindowMessage() +public partial record HideWindowMessage() { } diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Microsoft.CmdPal.Common.csproj b/src/modules/cmdpal/Microsoft.CmdPal.Common/Microsoft.CmdPal.Common.csproj index 970df0df58..5f83ca54e1 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Microsoft.CmdPal.Common.csproj +++ b/src/modules/cmdpal/Microsoft.CmdPal.Common/Microsoft.CmdPal.Common.csproj @@ -1,5 +1,6 @@ + Microsoft.CmdPal.Common enable diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Models/LocalSettingsOptions.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Models/LocalSettingsOptions.cs deleted file mode 100644 index bae7422878..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Models/LocalSettingsOptions.cs +++ /dev/null @@ -1,18 +0,0 @@ -// 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.CmdPal.Common.Models; - -public class LocalSettingsOptions -{ - public string? ApplicationDataFolder - { - get; set; - } - - public string? LocalSettingsFile - { - get; set; - } -} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/NativeMethods.txt b/src/modules/cmdpal/Microsoft.CmdPal.Common/NativeMethods.txt index 0d456bde31..996bbd7153 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/NativeMethods.txt +++ b/src/modules/cmdpal/Microsoft.CmdPal.Common/NativeMethods.txt @@ -1,16 +1,7 @@ -EnableWindow -CoCreateInstance -FileOpenDialog -FileSaveDialog -IFileOpenDialog -IFileSaveDialog -SHCreateItemFromParsingName GetCurrentPackageFullName SetWindowLong GetWindowLong WINDOW_EX_STYLE -SHLoadIndirectString -StrFormatByteSizeEx SFBS_FLAGS MAX_PATH GetDpiForWindow diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Services/FileService.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Services/FileService.cs deleted file mode 100644 index cc6ef96098..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Services/FileService.cs +++ /dev/null @@ -1,48 +0,0 @@ -// 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.IO; -using System.Text; -using System.Text.Json; -using Microsoft.CmdPal.Common.Contracts; - -namespace Microsoft.CmdPal.Common.Services; - -public class FileService : IFileService -{ - private static readonly Encoding _encoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false); - -#pragma warning disable CS8603 // Possible null reference return. - public T Read(string folderPath, string fileName) - { - var path = Path.Combine(folderPath, fileName); - if (File.Exists(path)) - { - using var fileStream = File.OpenText(path); - return JsonSerializer.Deserialize(fileStream.BaseStream); - } - - return default; - } -#pragma warning restore CS8603 // Possible null reference return. - - public void Save(string folderPath, string fileName, T content) - { - if (!Directory.Exists(folderPath)) - { - Directory.CreateDirectory(folderPath); - } - - var fileContent = JsonSerializer.Serialize(content); - File.WriteAllText(Path.Combine(folderPath, fileName), fileContent, _encoding); - } - - public void Delete(string folderPath, string fileName) - { - if (fileName != null && File.Exists(Path.Combine(folderPath, fileName))) - { - File.Delete(Path.Combine(folderPath, fileName)); - } - } -} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Services/IApp.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Services/IApp.cs deleted file mode 100644 index 92980dfaff..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Services/IApp.cs +++ /dev/null @@ -1,18 +0,0 @@ -// 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.CmdPal.Common.Services; - -/// -/// Interface for the current application singleton object exposing the API -/// that can be accessed from anywhere in the application. -/// -public interface IApp -{ - /// - /// Gets services registered at the application level. - /// - public T GetService() - where T : class; -} diff --git a/src/modules/cmdpal/Microsoft.CmdPal.Common/Services/LocalSettingsService.cs b/src/modules/cmdpal/Microsoft.CmdPal.Common/Services/LocalSettingsService.cs deleted file mode 100644 index e4cd2a174b..0000000000 --- a/src/modules/cmdpal/Microsoft.CmdPal.Common/Services/LocalSettingsService.cs +++ /dev/null @@ -1,120 +0,0 @@ -// 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.Collections.Generic; -using System.IO; -using System.Threading.Tasks; -using Microsoft.CmdPal.Common.Contracts; -using Microsoft.CmdPal.Common.Helpers; -using Microsoft.CmdPal.Common.Models; -using Microsoft.Extensions.Options; -using Windows.Storage; - -namespace Microsoft.CmdPal.Common.Services; - -public class LocalSettingsService : ILocalSettingsService -{ - // TODO! for now, we're hardcoding the path as effectively: - // %localappdata%\CmdPal\LocalSettings.json - private const string DefaultApplicationDataFolder = "CmdPal"; - private const string DefaultLocalSettingsFile = "LocalSettings.json"; - - private readonly IFileService _fileService; - private readonly LocalSettingsOptions _options; - - private readonly string _localApplicationData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); - private readonly string _applicationDataFolder; - private readonly string _localSettingsFile; - - private readonly bool _isMsix; - - private Dictionary _settings; - private bool _isInitialized; - - public LocalSettingsService(IFileService fileService, IOptions options) - { - _isMsix = false; // RuntimeHelper.IsMSIX; - - _fileService = fileService; - _options = options.Value; - - _applicationDataFolder = Path.Combine(_localApplicationData, _options.ApplicationDataFolder ?? DefaultApplicationDataFolder); - _localSettingsFile = _options.LocalSettingsFile ?? DefaultLocalSettingsFile; - - _settings = new Dictionary(); - } - - private async Task InitializeAsync() - { - if (!_isInitialized) - { - _settings = await Task.Run(() => _fileService.Read>(_applicationDataFolder, _localSettingsFile)) ?? new Dictionary(); - - _isInitialized = true; - } - } - - public async Task HasSettingAsync(string key) - { - if (_isMsix) - { - return ApplicationData.Current.LocalSettings.Values.ContainsKey(key); - } - else - { - await InitializeAsync(); - - if (_settings != null) - { - return _settings.ContainsKey(key); - } - } - - return false; - } - - public async Task ReadSettingAsync(string key) - { - if (_isMsix) - { - if (ApplicationData.Current.LocalSettings.Values.TryGetValue(key, out var obj)) - { - return await Json.ToObjectAsync((string)obj); - } - } - else - { - await InitializeAsync(); - - if (_settings != null && _settings.TryGetValue(key, out var obj)) - { - var s = obj.ToString(); - - if (s != null) - { - return await Json.ToObjectAsync(s); - } - } - } - - return default; - } - - public async Task SaveSettingAsync(string key, T value) - { - if (_isMsix) - { - ApplicationData.Current.LocalSettings.Values[key] = await Json.StringifyAsync(value!); - } - else - { - await InitializeAsync(); - - _settings[key] = await Json.StringifyAsync(value!); - - await Task.Run(() => _fileService.Save(_applicationDataFolder, _localSettingsFile, _settings)); - } - } -} From ad974bd6790597645b130df4e9013d5b0ddd2e36 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Sun, 27 Apr 2025 15:29:15 -0500 Subject: [PATCH 69/70] Wait to update SearchText until we've actually updated SearchText (#39093) Closes #38829 If we always UpdateProperty here, then there's a possible race condition, where we raise the PropertyChanged(SearchText) before the subclass actually retrieves the new SearchText from the model. In that race situation, if the UI thread handles the PropertyChanged before ListViewModel fetches the SearchText, it'll think that the old search text is the _new_ value. --- .../PageViewModel.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/PageViewModel.cs b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/PageViewModel.cs index 9a1cda196b..126efa83ca 100644 --- a/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/PageViewModel.cs +++ b/src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/PageViewModel.cs @@ -182,6 +182,7 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext return; // throw? } + var updateProperty = true; switch (propertyName) { case nameof(Name): @@ -198,9 +199,21 @@ public partial class PageViewModel : ExtensionObjectViewModel, IPageContext case nameof(Icon): this.Icon = new(model.Icon); break; + default: + updateProperty = false; + break; } - UpdateProperty(propertyName); + // GH #38829: If we always UpdateProperty here, then there's a possible + // race condition, where we raise the PropertyChanged(SearchText) + // before the subclass actually retrieves the new SearchText from the + // model. In that race situation, if the UI thread handles the + // PropertyChanged before ListViewModel fetches the SearchText, it'll + // think that the old search text is the _new_ value. + if (updateProperty) + { + UpdateProperty(propertyName); + } } public new void ShowException(Exception ex, string? extensionHint = null) From 9cb99be4e9548c48bad517ce7c075b6de3c1e11e Mon Sep 17 00:00:00 2001 From: Kai Tao <69313318+vanzue@users.noreply.github.com> Date: Tue, 29 Apr 2025 18:31:21 +0800 Subject: [PATCH 70/70] [Tool] Delete export pfx function to remove use of hard coded password (#39144) don't need export pfx functionality --- tools/build/cert-management.ps1 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/build/cert-management.ps1 b/tools/build/cert-management.ps1 index a085a5ca54..ed7031c1e9 100644 --- a/tools/build/cert-management.ps1 +++ b/tools/build/cert-management.ps1 @@ -152,8 +152,4 @@ function Export-CertificateFiles { if (-not $CerPath -and -not $PfxPath) { Write-Warning "No output path specified. Nothing was exported." } -} - -$cert = EnsureCertificate -$pswd = ConvertTo-SecureString -String "MySecurePassword123!" -AsPlainText -Force -Export-CertificateFiles -Certificate $cert -CerPath "$env:TEMP\cert.cer" -PfxPath "$env:TEMP\cert.pfx" -PfxPassword $pswd +} \ No newline at end of file