diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 7c72abb8a5..b51781c58e 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -50,6 +50,7 @@ body: - Always on Top - Awake - ColorPicker + - Command not found - Crop and Lock - Environment Variables - FancyZones diff --git a/.github/ISSUE_TEMPLATE/translation_issue.yml b/.github/ISSUE_TEMPLATE/translation_issue.yml index 5d9d292029..11517c195b 100644 --- a/.github/ISSUE_TEMPLATE/translation_issue.yml +++ b/.github/ISSUE_TEMPLATE/translation_issue.yml @@ -24,6 +24,7 @@ body: - Always on Top - Awake - ColorPicker + - Command not found - Crop and Lock - Environment Variables - FancyZones diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json index a6350ec764..097645b675 100644 --- a/.pipelines/ESRPSigning_core.json +++ b/.pipelines/ESRPSigning_core.json @@ -5,7 +5,9 @@ { "MatchedPath": [ "*.resources.dll", - + + "WinUI3Apps\\Assets\\Settings\\Scripts\\*.ps1", + "PowerToys.ActionRunner.exe", "PowerToys.Update.exe", "PowerToys.BackgroundActivatorDLL.dll", diff --git a/.pipelines/release.yml b/.pipelines/release.yml index 1993c2b3ce..d28596e0f6 100644 --- a/.pipelines/release.yml +++ b/.pipelines/release.yml @@ -8,7 +8,7 @@ resources: - repository: 1ESPipelineTemplates type: git name: 1ESPipelineTemplates/1ESPipelineTemplates - ref: refs/tags/release-2023-11-13-4 + ref: refs/tags/release parameters: - name: buildConfigurations diff --git a/.pipelines/versionAndSignCheck.ps1 b/.pipelines/versionAndSignCheck.ps1 index d5960efb64..67c5312f95 100644 --- a/.pipelines/versionAndSignCheck.ps1 +++ b/.pipelines/versionAndSignCheck.ps1 @@ -68,11 +68,6 @@ $items | ForEach-Object { Write-Host "Version not set: " + $_.FullName $totalFailure++; } - elseif ($_.VersionInfo.ProductName -contains "PowerToys" -and $_.VersionInfo.LegalCopyright -notmatch "Copyright \(C\) $((Get-Date).Year)") { - # PowerToys assemblies that aren't updated to the current year in the copyright - Write-Host "Copyright year out of date: " + $_.FullName - $totalFailure++; - } else { $auth = Get-AuthenticodeSignature $_.FullName if ($auth.SignerCertificate -eq $null) { @@ -86,4 +81,4 @@ if ($totalFailure -gt 0) { exit 1 } -exit 0 \ No newline at end of file +exit 0 diff --git a/Directory.Build.props b/Directory.Build.props index 14a45385d4..f932d0036d 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,9 +1,9 @@ - Copyright (C) 2024 Microsoft Corporation + Copyright (C) Microsoft Corporation. All rights reserved. Microsoft Corp. - Copyright (C) 2024 Microsoft Corporation + Copyright (C) Microsoft Corporation. All rights reserved. PowerToys Microsoft Corporation en-US @@ -86,4 +86,4 @@ - \ No newline at end of file + diff --git a/Directory.Packages.props b/Directory.Packages.props index 927f9a2886..221c1ed464 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -44,7 +44,7 @@ - + diff --git a/NOTICE.md b/NOTICE.md index a43a1eb23c..9a7db68301 100644 --- a/NOTICE.md +++ b/NOTICE.md @@ -1333,7 +1333,7 @@ EXHIBIT A -Mozilla Public License. - Microsoft.Windows.CsWinRT 2.0.4 - Microsoft.Windows.SDK.BuildTools 10.0.22621.2428 - Microsoft.Windows.SDK.Contracts 10.0.19041.1 -- Microsoft.WindowsAppSDK 1.4.231115000 +- Microsoft.WindowsAppSDK 1.4.231219000 - Microsoft.Xaml.Behaviors.WinUI.Managed 2.0.9 - Microsoft.Xaml.Behaviors.Wpf 1.1.39 - ModernWpfUI 0.9.4 diff --git a/doc/devdocs/modules/launcher/new-plugin-checklist.md b/doc/devdocs/modules/launcher/new-plugin-checklist.md index c3fcab39a8..1d76e85b75 100644 --- a/doc/devdocs/modules/launcher/new-plugin-checklist.md +++ b/doc/devdocs/modules/launcher/new-plugin-checklist.md @@ -1,12 +1,14 @@ # New plugin checklist + - [ ] The plugin is a project under `modules\launcher\Plugins` - [ ] Microsoft plugin project name pattern: `Microsoft.PowerToys.Run.Plugin.{PluginName}` - [ ] Community plugin project name pattern: `Community.PowerToys.Run.Plugin.{PluginName}` +- [ ] The plugin target framework should be `net8.0-windows` - [ ] The project file should import `Version.props` and specify `$(Version).0` - [ ] If the plugin uses any 3rd party dependencies the project file should import `DynamicPlugin.props` -- [ ] Make sure `*.csproj` specify only x64 platform target -- [ ] The plugin has to contain a `plugin.json` file of the following format in its root folder -``` +- [ ] The plugin has to contain a `plugin.json` file of the following format in its root folder: + +```json { "ID": string, // GUID string "ActionKeyword": string, // Direct activation phrase @@ -22,20 +24,22 @@ "DynamicLoading": bool // Sets whether the plugin should dynamically load any dependencies isolated from the core application. } ``` + - [ ] Make sure your `Main` class contains a public, static string property for the `PluginID`. The plugin id has to be the same as the one in the `plugin.json`file. + ```csharp public static string PluginID => "xxxxxxx"; // The part xxxxxxx stands for the plugin ID. ``` + - [ ] Do not use plugin name or PowerToys as prefixes for entities inside of the plugin project - [ ] The plugin has to have Unit tests. Use MSTest framework - [ ] Plugin's output code and assets have to be included in the installer [`Product.wxs`](/installer/PowerToysSetup/Product.wxs) - [ ] Test the plugin with a local build. Build the installer, install, check that the plugin works as expected - [ ] All plugin's binaries have to be included in the signed build [`pipeline.user.windows.yml`](/.pipelines/pipeline.user.windows.yml) -- [ ] The plugin target framework has to be .NET Core 3.1. All dependencies have to have .NET 5 version +- [ ] The plugin target framework has to be net8.0-windows. All dependencies should be compatible with .NET 8. Some localization steps can only be done after the first pass by the localization team to provide the localized resources. In the PR that adds a new plugin, reference a new issue to track the work for fully enabling localization for the new plugin. - - [ ] Add the resource folder to https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L825 - - [ ] Add the resource files under the section https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L882 - +- [ ] Add the resource folder to https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L825 +- [ ] Add the resource files under the section https://github.com/microsoft/PowerToys/blob/21247c0bb09a1bee3d14d6efa53d0c247f7236af/installer/PowerToysSetup/Product.wxs#L882 diff --git a/doc/thirdPartyRunPlugins.md b/doc/thirdPartyRunPlugins.md index 1ac63c7f87..0e9f4a62ab 100644 --- a/doc/thirdPartyRunPlugins.md +++ b/doc/thirdPartyRunPlugins.md @@ -34,4 +34,6 @@ Contact the developers of a plugin directly for assistance with a specific plugi | [Visual Studio](https://github.com/davidegiacometti/PowerToys-Run-VisualStudio) | [davidegiacometti](https://github.com/davidegiacometti) | Open Visual Studio recents | | [WinGet](https://github.com/bostrot/PowerToysRunPluginWinget) | [bostrot](https://github.com/bostrot) | Search and install packages from WinGet | | [Scoop](https://github.com/Quriz/PowerToysRunScoop) | [Quriz](https://github.com/Quriz) | Search and install packages from Scoop | -| [Spotify](https://github.com/waaverecords/PowerToys-Run-Spotify) | [waaverecords](https://github.com/waaverecords) | Search Spotify and control its player | \ No newline at end of file +| [Spotify](https://github.com/waaverecords/PowerToys-Run-Spotify) | [waaverecords](https://github.com/waaverecords) | Search Spotify and control its player | +| [Input Typer](https://github.com/CoreyHayward/PowerToys-Run-InputTyper) | [CoreyHayward](https://github.com/CoreyHayward) | Type the input as if sent from a keyboard | +| [Clipboard Manager](https://github.com/CoreyHayward/PowerToys-Run-ClipboardManager) | [CoreyHayward](https://github.com/CoreyHayward) | Search and paste text from your clipboard history | \ No newline at end of file diff --git a/src/common/GPOWrapper/GPOWrapper.cpp b/src/common/GPOWrapper/GPOWrapper.cpp index c3177d60db..a8eb3a5513 100644 --- a/src/common/GPOWrapper/GPOWrapper.cpp +++ b/src/common/GPOWrapper/GPOWrapper.cpp @@ -140,10 +140,18 @@ namespace winrt::PowerToys::GPOWrapper::implementation { return static_cast(powertoys_gpo::getConfiguredPeekEnabledValue()); } + GpoRuleConfigured GPOWrapper::GetDisableNewUpdateToastValue() + { + return static_cast(powertoys_gpo::getDisableNewUpdateToastValue()); + } GpoRuleConfigured GPOWrapper::GetDisableAutomaticUpdateDownloadValue() { return static_cast(powertoys_gpo::getDisableAutomaticUpdateDownloadValue()); } + GpoRuleConfigured GPOWrapper::GetDisableShowWhatsNewAfterUpdatesValue() + { + return static_cast(powertoys_gpo::getDisableShowWhatsNewAfterUpdatesValue()); + } GpoRuleConfigured GPOWrapper::GetAllowExperimentationValue() { return static_cast(powertoys_gpo::getAllowExperimentationValue()); diff --git a/src/common/GPOWrapper/GPOWrapper.h b/src/common/GPOWrapper/GPOWrapper.h index bd153ed258..981c6dc50e 100644 --- a/src/common/GPOWrapper/GPOWrapper.h +++ b/src/common/GPOWrapper/GPOWrapper.h @@ -41,7 +41,9 @@ namespace winrt::PowerToys::GPOWrapper::implementation static GpoRuleConfigured GetConfiguredPastePlainEnabledValue(); static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue(); static GpoRuleConfigured GetConfiguredPeekEnabledValue(); + static GpoRuleConfigured GetDisableNewUpdateToastValue(); static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue(); + static GpoRuleConfigured GetDisableShowWhatsNewAfterUpdatesValue(); static GpoRuleConfigured GetAllowExperimentationValue(); static GpoRuleConfigured GetRunPluginEnabledValue(winrt::hstring const& pluginID); static GpoRuleConfigured GetConfiguredEnvironmentVariablesEnabledValue(); diff --git a/src/common/GPOWrapper/GPOWrapper.idl b/src/common/GPOWrapper/GPOWrapper.idl index 3b4c0eca28..eed2f2f393 100644 --- a/src/common/GPOWrapper/GPOWrapper.idl +++ b/src/common/GPOWrapper/GPOWrapper.idl @@ -45,7 +45,9 @@ namespace PowerToys static GpoRuleConfigured GetConfiguredPastePlainEnabledValue(); static GpoRuleConfigured GetConfiguredVideoConferenceMuteEnabledValue(); static GpoRuleConfigured GetConfiguredPeekEnabledValue(); + static GpoRuleConfigured GetDisableNewUpdateToastValue(); static GpoRuleConfigured GetDisableAutomaticUpdateDownloadValue(); + static GpoRuleConfigured GetDisableShowWhatsNewAfterUpdatesValue(); static GpoRuleConfigured GetAllowExperimentationValue(); static GpoRuleConfigured GetRunPluginEnabledValue(String pluginID); static GpoRuleConfigured GetConfiguredEnvironmentVariablesEnabledValue(); diff --git a/src/common/ManagedCommon/ModuleType.cs b/src/common/ManagedCommon/ModuleType.cs index 0bbfaeeda3..3a489711b0 100644 --- a/src/common/ManagedCommon/ModuleType.cs +++ b/src/common/ManagedCommon/ModuleType.cs @@ -9,7 +9,6 @@ namespace ManagedCommon AlwaysOnTop, Awake, ColorPicker, - CmdNotFound, CropAndLock, EnvironmentVariables, FancyZones, diff --git a/src/common/utils/gpo.h b/src/common/utils/gpo.h index 016bd744cc..66fe34a10a 100644 --- a/src/common/utils/gpo.h +++ b/src/common/utils/gpo.h @@ -64,7 +64,9 @@ namespace powertoys_gpo { const std::wstring POLICY_DISABLE_PER_USER_INSTALLATION = L"PerUserInstallationDisabled"; const std::wstring POLICY_DISABLE_AUTOMATIC_UPDATE_DOWNLOAD = L"AutomaticUpdateDownloadDisabled"; const std::wstring POLICY_SUSPEND_NEW_UPDATE_TOAST = L"SuspendNewUpdateAvailableToast"; + const std::wstring POLICY_DISABLE_NEW_UPDATE_TOAST = L"DisableNewUpdateAvailableToast"; const std::wstring POLICY_DISABLE_PERIODIC_UPDATE_CHECK = L"PeriodicUpdateCheckDisabled"; + const std::wstring POLICY_DISABLE_SHOW_WHATS_NEW_AFTER_UPDATES = L"DoNotShowWhatsNewAfterUpdates"; // The registry value names for other PowerToys policies. const std::wstring POLICY_ALLOW_EXPERIMENTATION = L"AllowExperimentation"; @@ -405,11 +407,21 @@ namespace powertoys_gpo { return getConfiguredValue(POLICY_SUSPEND_NEW_UPDATE_TOAST); } + inline gpo_rule_configured_t getDisableNewUpdateToastValue() + { + return getConfiguredValue(POLICY_DISABLE_NEW_UPDATE_TOAST); + } + inline gpo_rule_configured_t getDisablePeriodicUpdateCheckValue() { return getConfiguredValue(POLICY_DISABLE_PERIODIC_UPDATE_CHECK); } + inline gpo_rule_configured_t getDisableShowWhatsNewAfterUpdatesValue() + { + return getConfiguredValue(POLICY_DISABLE_SHOW_WHATS_NEW_AFTER_UPDATES); + } + inline gpo_rule_configured_t getAllowExperimentationValue() { return getConfiguredValue(POLICY_ALLOW_EXPERIMENTATION); diff --git a/src/common/version/version.h b/src/common/version/version.h index b300619565..f1602e10c4 100644 --- a/src/common/version/version.h +++ b/src/common/version/version.h @@ -13,7 +13,7 @@ #define PRODUCT_VERSION_STRING FILE_VERSION_STRING #define COMPANY_NAME "Microsoft Corporation" -#define COPYRIGHT_NOTE "Copyright (C) 2024 Microsoft Corporation" +#define COPYRIGHT_NOTE "Copyright (C) Microsoft Corporation. All rights reserved." #define PRODUCT_NAME "PowerToys" #include @@ -43,4 +43,4 @@ inline std::wstring get_std_product_version() L"." + std::to_wstring(VERSION_REVISION) + L".0"; return version; -} \ No newline at end of file +} diff --git a/src/gpo/assets/PowerToys.admx b/src/gpo/assets/PowerToys.admx index 42ebfe3349..06757271a0 100644 --- a/src/gpo/assets/PowerToys.admx +++ b/src/gpo/assets/PowerToys.admx @@ -1,11 +1,11 @@ - + - + @@ -16,6 +16,7 @@ + @@ -439,6 +440,16 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/src/gpo/assets/en-US/PowerToys.adml b/src/gpo/assets/en-US/PowerToys.adml index 2eb3c700b3..0fb97927af 100644 --- a/src/gpo/assets/en-US/PowerToys.adml +++ b/src/gpo/assets/en-US/PowerToys.adml @@ -1,7 +1,7 @@ - + PowerToys PowerToys @@ -18,6 +18,7 @@ PowerToys version 0.75.0 or later PowerToys version 0.76.0 or later PowerToys version 0.77.0 or later + PowerToys version 0.78.0 or later This policy configures the enabled state for all PowerToys utilities. @@ -71,12 +72,26 @@ If enabled, the notification is suspended. If disabled or not configured, the notification is shown. Note: The notification about new major versions is always displayed. + +This policy has no effect if the update notification is disabled by the policy "Disable Action Center notification for new updates" or the user setting. + + This policy configures whether the action center notification for new updates is shown or not. + +If enabled, the notification is disabled. + +If disabled or not configured, the user can control if the notification is shown or not. This policy allows you to disable automatic update checks running in the background. (The manual check in PT Settings is not affected by this policy.) If enabled, the automatic update checks are disabled. If disabled or not configured, the automatic update checks are enabled. + + This policy allows you to configure if the window with the release notes is shown after updates. + +If enabled, the window with the release notes is not shown automatically. + +If disabled or not configured, the user can control this in the settings of PowerToys. This policy configures whether PowerToys experimentation is allowed. With experimentation allowed the user sees the new features being experimented if it gets selected as part of the test group. (Experimentation will only happen on Windows Insider builds.) @@ -147,7 +162,9 @@ Note: Changes require a restart of PowerToys Run. Video Conference Mute: Configure enabled state Disable per-user installation Disable automatic downloads + Do not show the release notes after updates Suspend Action Center notification for new updates + Disable Action Center notification for new updates Disable automatic update checks Allow Experimentation Configure enabled state for all plugins diff --git a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj index 8e57c6ef6a..840bb868a5 100644 --- a/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj +++ b/src/modules/MeasureTool/MeasureToolCore/PowerToys.MeasureToolCore.vcxproj @@ -1,7 +1,7 @@  - + true @@ -145,7 +145,7 @@ - + @@ -155,8 +155,8 @@ - - + + diff --git a/src/modules/MeasureTool/MeasureToolCore/packages.config b/src/modules/MeasureTool/MeasureToolCore/packages.config index 285cc434ce..627512b778 100644 --- a/src/modules/MeasureTool/MeasureToolCore/packages.config +++ b/src/modules/MeasureTool/MeasureToolCore/packages.config @@ -3,5 +3,5 @@ - + \ No newline at end of file diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp index 29ab5419ec..51b93c37a6 100644 --- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp +++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.cpp @@ -75,6 +75,11 @@ protected: static constexpr int FinalAlphaDenominator = 100; winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr }; + // Don't consider movements started past these milliseconds to detect shaking. + int m_shakeIntervalMs = FIND_MY_MOUSE_DEFAULT_SHAKE_INTERVAL_MS; + // By which factor must travelled distance be than the diagonal of the rectangle containing the movements. (value in percent) + int m_shakeFactor = FIND_MY_MOUSE_DEFAULT_SHAKE_FACTOR; + private: // Save the mouse movement that occurred in any direction. @@ -87,10 +92,6 @@ private: // Raw Input may give relative or absolute values. Need to take each case into account. bool m_seenAnAbsoluteMousePosition = false; POINT m_lastAbsolutePosition = { 0, 0 }; - // Don't consider movements started past these milliseconds to detect shaking. - static constexpr LONG ShakeIntervalMs = 1000; - // By which factor must travelled distance be than the diagonal of the rectangle containing the movements. - static constexpr float ShakeFactor = 4.0f; static inline byte GetSign(LONG const& num) { @@ -398,7 +399,7 @@ void SuperSonar::OnSonarKeyboardInput(RAWINPUT const& input) template void SuperSonar::DetectShake() { - ULONGLONG shakeStartTick = GetTickCount64() - ShakeIntervalMs; + ULONGLONG shakeStartTick = GetTickCount64() - m_shakeIntervalMs; // Prune the story of movements for those movements that started too long ago. std::erase_if(m_movementHistory, [shakeStartTick](const PointerRecentMovement& movement) { return movement.tick < shakeStartTick; }); @@ -429,7 +430,7 @@ void SuperSonar::DetectShake() double rectangleHeight = static_cast(maxY) - minY; double diagonal = sqrt(rectangleWidth * rectangleWidth + rectangleHeight * rectangleHeight); - if (diagonal > 0 && distanceTravelled / diagonal > ShakeFactor) + if (diagonal > 0 && distanceTravelled / diagonal > (m_shakeFactor/100.f)) { m_movementHistory.clear(); StartSonar(); @@ -767,6 +768,8 @@ public: m_sonarZoomFactor = settings.spotlightInitialZoom; m_excludedApps = settings.excludedApps; m_shakeMinimumDistance = settings.shakeMinimumDistance; + m_shakeIntervalMs = settings.shakeIntervalMs; + m_shakeFactor = settings.shakeFactor; } else { @@ -794,6 +797,8 @@ public: m_sonarZoomFactor = localSettings.spotlightInitialZoom; m_excludedApps = localSettings.excludedApps; m_shakeMinimumDistance = localSettings.shakeMinimumDistance; + m_shakeIntervalMs = localSettings.shakeIntervalMs; + m_shakeFactor = localSettings.shakeFactor; UpdateMouseSnooping(); // For the shake mouse activation method // Apply new settings to runtime composition objects. diff --git a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h index 149e52842b..d55b72a34d 100644 --- a/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h +++ b/src/modules/MouseUtils/FindMyMouse/FindMyMouse.h @@ -19,6 +19,8 @@ constexpr int FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS = 500; constexpr int FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM = 9; constexpr FindMyMouseActivationMethod FIND_MY_MOUSE_DEFAULT_ACTIVATION_METHOD = FindMyMouseActivationMethod::DoubleLeftControlKey; constexpr int FIND_MY_MOUSE_DEFAULT_SHAKE_MINIMUM_DISTANCE = 1000; +constexpr int FIND_MY_MOUSE_DEFAULT_SHAKE_INTERVAL_MS = 1000; +constexpr int FIND_MY_MOUSE_DEFAULT_SHAKE_FACTOR = 400; // 400 percent struct FindMyMouseSettings { @@ -31,6 +33,8 @@ struct FindMyMouseSettings int animationDurationMs = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS; int spotlightInitialZoom = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM; int shakeMinimumDistance = FIND_MY_MOUSE_DEFAULT_SHAKE_MINIMUM_DISTANCE; + int shakeIntervalMs = FIND_MY_MOUSE_DEFAULT_SHAKE_INTERVAL_MS; + int shakeFactor = FIND_MY_MOUSE_DEFAULT_SHAKE_FACTOR; std::vector excludedApps; }; diff --git a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp index 2d1aa55acc..d0102ba507 100644 --- a/src/modules/MouseUtils/FindMyMouse/dllmain.cpp +++ b/src/modules/MouseUtils/FindMyMouse/dllmain.cpp @@ -23,6 +23,8 @@ namespace const wchar_t JSON_KEY_SPOTLIGHT_INITIAL_ZOOM[] = L"spotlight_initial_zoom"; const wchar_t JSON_KEY_EXCLUDED_APPS[] = L"excluded_apps"; const wchar_t JSON_KEY_SHAKING_MINIMUM_DISTANCE[] = L"shaking_minimum_distance"; + const wchar_t JSON_KEY_SHAKING_INTERVAL_MS[] = L"shaking_interval_ms"; + const wchar_t JSON_KEY_SHAKING_FACTOR[] = L"shaking_factor"; const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"activation_shortcut"; } @@ -396,6 +398,42 @@ void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings) { Logger::warn("Failed to initialize Shaking Minimum Distance from settings. Will use default value"); } + try + { + // Parse Shaking Interval Milliseconds + auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SHAKING_INTERVAL_MS); + int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE)); + if (value >= 0) + { + findMyMouseSettings.shakeIntervalMs = value; + } + else + { + throw std::runtime_error("Invalid Shaking Interval Milliseconds value"); + } + } + catch (...) + { + Logger::warn("Failed to initialize Shaking Interval Milliseconds from settings. Will use default value"); + } + try + { + // Parse Shaking Factor + auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SHAKING_FACTOR); + int value = static_cast(jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE)); + if (value >= 0) + { + findMyMouseSettings.shakeFactor = value; + } + else + { + throw std::runtime_error("Invalid Shaking Factor value"); + } + } + catch (...) + { + Logger::warn("Failed to initialize Shaking Factor from settings. Will use default value"); + } try { diff --git a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.base.rc b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.base.rc index 75d478289a..c4e1b7cfc5 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.base.rc +++ b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.base.rc @@ -39,3 +39,11 @@ BEGIN END END +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_ICON1 ICON "../../Assets/AlwaysOnTop.ico" diff --git a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj index 3ca65747da..39233d7ed5 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj +++ b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj @@ -185,6 +185,9 @@ + + + diff --git a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj.filters b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj.filters index 878894a704..156373674f 100644 --- a/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj.filters +++ b/src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.vcxproj.filters @@ -125,4 +125,9 @@ + + + Resource Files + + \ No newline at end of file diff --git a/src/modules/alwaysontop/Assets/AlwaysOnTop.ico b/src/modules/alwaysontop/Assets/AlwaysOnTop.ico new file mode 100644 index 0000000000..fdfc40a14b Binary files /dev/null and b/src/modules/alwaysontop/Assets/AlwaysOnTop.ico differ diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter.UnitTest/InputInterpreterTests.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter.UnitTest/InputInterpreterTests.cs index 1da5c1d8da..99a1a265b9 100644 --- a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter.UnitTest/InputInterpreterTests.cs +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter.UnitTest/InputInterpreterTests.cs @@ -19,6 +19,12 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter.UnitTest [DataRow(new string[] { "1'5\"" }, new string[] { "1", "'", "5", "\"" })] [DataRow(new string[] { "5\"" }, new string[] { "5", "\"" })] [DataRow(new string[] { "1'5" }, new string[] { "1", "'", "5" })] + [DataRow(new string[] { "-1,5'" }, new string[] { "-1,5", "'" })] + [DataRow(new string[] { "-1.5'" }, new string[] { "-1.5", "'" })] + [DataRow(new string[] { "-1'" }, new string[] { "-1", "'" })] + [DataRow(new string[] { "-1'5\"" }, new string[] { "-1", "'", "5", "\"" })] + [DataRow(new string[] { "-5\"" }, new string[] { "-5", "\"" })] + [DataRow(new string[] { "-1'5" }, new string[] { "-1", "'", "5" })] public void RegexSplitsInput(string[] input, string[] expectedResult) { string[] shortsplit = InputInterpreter.RegexSplitter(input); @@ -27,6 +33,7 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter.UnitTest [DataTestMethod] [DataRow(new string[] { "1cm", "to", "mm" }, new string[] { "1", "cm", "to", "mm" })] + [DataRow(new string[] { "-1cm", "to", "mm" }, new string[] { "-1", "cm", "to", "mm" })] public void InsertsSpaces(string[] input, string[] expectedResult) { InputInterpreter.InputSpaceInserter(ref input); @@ -38,6 +45,10 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter.UnitTest [DataRow(new string[] { "1\"", "in", "cm" }, new string[] { "1", "inch", "in", "cm" })] [DataRow(new string[] { "1'6", "in", "cm" }, new string[] { "1.5", "foot", "in", "cm" })] [DataRow(new string[] { "1'6\"", "in", "cm" }, new string[] { "1.5", "foot", "in", "cm" })] + [DataRow(new string[] { "-1'", "in", "cm" }, new string[] { "-1", "foot", "in", "cm" })] + [DataRow(new string[] { "-1\"", "in", "cm" }, new string[] { "-1", "inch", "in", "cm" })] + [DataRow(new string[] { "-1'6", "in", "cm" }, new string[] { "-1.5", "foot", "in", "cm" })] + [DataRow(new string[] { "-1'6\"", "in", "cm" }, new string[] { "-1.5", "foot", "in", "cm" })] public void HandlesShorthandFeetInchNotation(string[] input, string[] expectedResult) { InputInterpreter.ShorthandFeetInchHandler(ref input, CultureInfo.InvariantCulture); @@ -69,6 +80,8 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter.UnitTest [DataTestMethod] [DataRow("a f in c")] [DataRow("12 f in")] + [DataRow("1-2 f in c")] + [DataRow("12- f in c")] public void ParseInvalidQueries(string queryString) { Query query = new Query(queryString); @@ -79,6 +92,8 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter.UnitTest [DataTestMethod] [DataRow("12 f in c", 12)] [DataRow("10m to cm", 10)] + [DataRow("-12 f in c", -12)] + [DataRow("-10m to cm", -10)] public void ParseValidQueries(string queryString, double result) { Query query = new Query(queryString); diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter/InputInterpreter.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter/InputInterpreter.cs index f9a784181a..5cdaf9683e 100644 --- a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter/InputInterpreter.cs +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter/InputInterpreter.cs @@ -14,11 +14,11 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter { public static class InputInterpreter { - private static string pattern = @"(?<=\d)(?![,.])(?=\D)|(?<=\D)(? @@ -31,7 +31,7 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter return; } - string[] parseInputWithoutSpace = Regex.Split(split[0], pattern); + string[] parseInputWithoutSpace = Regex.Split(split[0], Pattern); if (parseInputWithoutSpace.Length > 1) { @@ -80,6 +80,12 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter // ex: 1'2 and 1'2" if (shortsplit[1] == "\'") { + bool isNegative = shortsplit[0].StartsWith('-'); + if (isNegative) + { + shortsplit[0] = shortsplit[0].Remove(0, 1); + } + bool isFeet = double.TryParse(shortsplit[0], NumberStyles.AllowDecimalPoint, culture, out double feet); bool isInches = double.TryParse(shortsplit[2], NumberStyles.AllowDecimalPoint, culture, out double inches); @@ -89,9 +95,13 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter break; } - string convertedTotalInFeet = Length.FromFeetInches(feet, inches).Feet.ToString(culture); + double convertedTotalInFeet = Length.FromFeetInches(feet, inches).Feet; + if (isNegative) + { + convertedTotalInFeet *= -1; + } - string[] newInput = new string[] { convertedTotalInFeet, "foot", split[1], split[2] }; + string[] newInput = new string[] { convertedTotalInFeet.ToString(culture), "foot", split[1], split[2] }; split = newInput; } diff --git a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspacesApi.cs b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspacesApi.cs index bd318f0896..0be408dc49 100644 --- a/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspacesApi.cs +++ b/src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/WorkspacesHelper/VSCodeWorkspacesApi.cs @@ -46,6 +46,11 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper path = path[1..]; } + if (!DoesPathExist(path, workspaceEnv.Value, machineName)) + { + return null; + } + var folderName = Path.GetFileName(path); // Check we haven't returned '' if we have a path like C:\ @@ -67,6 +72,24 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper }; } + private bool DoesPathExist(string path, WorkspaceEnvironment workspaceEnv, string machineName) + { + if (workspaceEnv == WorkspaceEnvironment.Local || workspaceEnv == WorkspaceEnvironment.RemoteWSL) + { + var resolvedPath = path; + + if (workspaceEnv == WorkspaceEnvironment.RemoteWSL) + { + resolvedPath = $"\\\\wsl$\\{machineName}{resolvedPath.Replace('/', '\\')}"; + } + + return Directory.Exists(resolvedPath) || File.Exists(resolvedPath); + } + + // If the workspace environment is not Local or WSL, assume the path exists + return true; + } + public List Workspaces { get diff --git a/src/modules/launcher/PowerLauncher/Helper/NativeMethods.cs b/src/modules/launcher/PowerLauncher/Helper/NativeMethods.cs index c6dd2c33ad..5e6ff90c95 100644 --- a/src/modules/launcher/PowerLauncher/Helper/NativeMethods.cs +++ b/src/modules/launcher/PowerLauncher/Helper/NativeMethods.cs @@ -69,6 +69,9 @@ namespace PowerLauncher.Helper [DllImport("user32.DLL", CharSet = CharSet.Unicode)] internal static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); + [DllImport("shell32.dll")] + public static extern int SHQueryUserNotificationState(out UserNotificationState state); + public static string[] CommandLineToArgvW(string cmdLine) { IntPtr argv = IntPtr.Zero; @@ -242,4 +245,15 @@ namespace PowerLauncher.Helper TRAYMOUSEMESSAGE = 0x800, // WM_USER + 1024 APP = 0x8000, } + + internal enum UserNotificationState : int + { + QUNS_NOT_PRESENT = 1, + QUNS_BUSY, + QUNS_RUNNING_D3D_FULL_SCREEN, + QUNS_PRESENTATION_MODE, + QUNS_ACCEPTS_NOTIFICATIONS, + QUNS_QUIET_TIME, + QUNS_APP, + } } diff --git a/src/modules/launcher/PowerLauncher/Helper/WindowsInteropHelper.cs b/src/modules/launcher/PowerLauncher/Helper/WindowsInteropHelper.cs index 4c0819f203..612476daff 100644 --- a/src/modules/launcher/PowerLauncher/Helper/WindowsInteropHelper.cs +++ b/src/modules/launcher/PowerLauncher/Helper/WindowsInteropHelper.cs @@ -112,6 +112,15 @@ namespace PowerLauncher.Helper public static bool IsWindowFullscreen() { + // First, check to see if a game is fullscreen, if so, we definitely have + // a full-screen window + UserNotificationState state; + if (Marshal.GetExceptionForHR(NativeMethods.SHQueryUserNotificationState(out state)) == null && + state == UserNotificationState.QUNS_RUNNING_D3D_FULL_SCREEN) + { + return true; + } + // get current active window IntPtr hWnd = NativeMethods.GetForegroundWindow(); diff --git a/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs b/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs index 00278adba9..4e62d9d407 100644 --- a/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs +++ b/src/modules/launcher/PowerLauncher/MainWindow.xaml.cs @@ -55,6 +55,10 @@ namespace PowerLauncher _viewModel = mainVM; _nativeWaiterCancelToken = nativeWaiterCancelToken; _settings = settings; + + // Fixes #30850 + AppContext.SetSwitch("Switch.System.Windows.Controls.Grid.StarDefinitionsCanExceedAvailableSpace", true); + InitializeComponent(); if (OSVersionHelper.IsWindows11()) diff --git a/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj b/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj index 287570edfc..2f911fcd22 100644 --- a/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj +++ b/src/modules/powerrename/PowerRenameUILib/PowerRenameUI.vcxproj @@ -1,8 +1,8 @@  + - true true @@ -202,7 +202,7 @@ - + @@ -213,8 +213,8 @@ 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}. - - + + diff --git a/src/modules/powerrename/PowerRenameUILib/packages.config b/src/modules/powerrename/PowerRenameUILib/packages.config index 8820eb03ad..040eedefa7 100644 --- a/src/modules/powerrename/PowerRenameUILib/packages.config +++ b/src/modules/powerrename/PowerRenameUILib/packages.config @@ -5,5 +5,5 @@ - + \ No newline at end of file diff --git a/src/runner/UpdateUtils.cpp b/src/runner/UpdateUtils.cpp index c5f74e31ef..c2297e630d 100644 --- a/src/runner/UpdateUtils.cpp +++ b/src/runner/UpdateUtils.cpp @@ -140,9 +140,16 @@ void ProcessNewVersionInfo(const github_version_info& version_info, return; } - // Check notification GPO. - // We check only if notifications are allowed. This is the case if we are triggered by the periodic check. - if (show_notifications && powertoys_gpo::getSuspendNewUpdateToastValue() == powertoys_gpo::gpo_rule_configured_enabled) + // Check toast notification GPOs and settings. (We check only if notifications are allowed. This is the case if we are triggered by the periodic check.) + // Disable notification GPO or setting + bool disable_notification_setting = get_general_settings().showNewUpdatesToastNotification == false; + if (show_notifications && (disable_notification_setting || powertoys_gpo::getDisableNewUpdateToastValue() == powertoys_gpo::gpo_rule_configured_enabled)) + { + Logger::info(L"There is a new update available or ready to install. But the toast notification is disabled by setting or GPO."); + show_notifications = false; + } + // Suspend notification GPO + else if (show_notifications && powertoys_gpo::getSuspendNewUpdateToastValue() == powertoys_gpo::gpo_rule_configured_enabled) { Logger::info(L"GPO to suspend new update toast notification is enabled."); if (new_version_info.version.major <= VERSION_MAJOR && new_version_info.version.minor - VERSION_MINOR <= UPDATE_NOTIFICATION_TOAST_SUSPEND_MINOR_VERSION_COUNT) diff --git a/src/runner/general_settings.cpp b/src/runner/general_settings.cpp index 5c56702ab3..9925308507 100644 --- a/src/runner/general_settings.cpp +++ b/src/runner/general_settings.cpp @@ -15,7 +15,9 @@ // TODO: would be nice to get rid of these globals, since they're basically cached json settings static std::wstring settings_theme = L"system"; static bool run_as_elevated = false; +static bool show_new_updates_toast_notification = true; static bool download_updates_automatically = true; +static bool show_whats_new_after_updates = true; static bool enable_experimentation = true; static bool enable_warnings_elevated_apps = true; @@ -38,7 +40,9 @@ json::JsonObject GeneralSettings::to_json() result.SetNamedValue(L"is_elevated", json::value(isElevated)); result.SetNamedValue(L"run_elevated", json::value(isRunElevated)); + result.SetNamedValue(L"show_new_updates_toast_notification", json::value(showNewUpdatesToastNotification)); result.SetNamedValue(L"download_updates_automatically", json::value(downloadUpdatesAutomatically)); + result.SetNamedValue(L"show_whats_new_after_updates", json::value(showWhatsNewAfterUpdates)); result.SetNamedValue(L"enable_experimentation", json::value(enableExperimentation)); result.SetNamedValue(L"is_admin", json::value(isAdmin)); result.SetNamedValue(L"enable_warnings_elevated_apps", json::value(enableWarningsElevatedApps)); @@ -58,7 +62,9 @@ json::JsonObject load_general_settings() settings_theme = L"system"; } run_as_elevated = loaded.GetNamedBoolean(L"run_elevated", false); + show_new_updates_toast_notification = loaded.GetNamedBoolean(L"show_new_updates_toast_notification", true); download_updates_automatically = loaded.GetNamedBoolean(L"download_updates_automatically", true) && check_user_is_admin(); + show_whats_new_after_updates = loaded.GetNamedBoolean(L"show_whats_new_after_updates", true); enable_experimentation = loaded.GetNamedBoolean(L"enable_experimentation",true); enable_warnings_elevated_apps = loaded.GetNamedBoolean(L"enable_warnings_elevated_apps", true); @@ -73,7 +79,9 @@ GeneralSettings get_general_settings() .isRunElevated = run_as_elevated, .isAdmin = is_user_admin, .enableWarningsElevatedApps = enable_warnings_elevated_apps, + .showNewUpdatesToastNotification = show_new_updates_toast_notification, .downloadUpdatesAutomatically = download_updates_automatically && is_user_admin, + .showWhatsNewAfterUpdates = show_whats_new_after_updates, .enableExperimentation = enable_experimentation, .theme = settings_theme, .systemTheme = WindowsColors::is_dark_mode() ? L"dark" : L"light", @@ -97,7 +105,10 @@ void apply_general_settings(const json::JsonObject& general_configs, bool save) enable_warnings_elevated_apps = general_configs.GetNamedBoolean(L"enable_warnings_elevated_apps", true); + show_new_updates_toast_notification = general_configs.GetNamedBoolean(L"show_new_updates_toast_notification", true); + download_updates_automatically = general_configs.GetNamedBoolean(L"download_updates_automatically", true); + show_whats_new_after_updates = general_configs.GetNamedBoolean(L"show_whats_new_after_updates", true); enable_experimentation = general_configs.GetNamedBoolean(L"enable_experimentation", true); diff --git a/src/runner/general_settings.h b/src/runner/general_settings.h index c2b9dcc03d..f56271cf07 100644 --- a/src/runner/general_settings.h +++ b/src/runner/general_settings.h @@ -11,7 +11,9 @@ struct GeneralSettings bool isRunElevated; bool isAdmin; bool enableWarningsElevatedApps; + bool showNewUpdatesToastNotification; bool downloadUpdatesAutomatically; + bool showWhatsNewAfterUpdates; bool enableExperimentation; std::wstring theme; std::wstring systemTheme; diff --git a/src/runner/main.cpp b/src/runner/main.cpp index a16197655e..1a8f64e738 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -46,6 +46,7 @@ #include #include #include +#include // disabling warning 4458 - declaration of 'identifier' hides class member // to avoid warnings from GDI files - can't add winRT directory to external code @@ -89,9 +90,9 @@ void open_menu_from_another_instance(std::optional settings_window) PostMessageW(hwnd_main, WM_COMMAND, ID_SETTINGS_MENU_COMMAND, msg); } -int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow, bool openOobe, bool openScoobe) +int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow, bool openOobe, bool openScoobe, bool showRestartNotificationAfterUpdate) { - Logger::info("Runner is starting. Elevated={} openOobe={} openScoobe={}", isProcessElevated, openOobe, openScoobe); + Logger::info("Runner is starting. Elevated={} openOobe={} openScoobe={} showRestartNotificationAfterUpdate={}", isProcessElevated, openOobe, openScoobe, showRestartNotificationAfterUpdate); DPIAware::EnableDPIAwarenessForThisProcess(); #if _DEBUG && _WIN64 @@ -106,7 +107,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow int result = -1; try { - if (!openOobe && openScoobe) + if (!openOobe && showRestartNotificationAfterUpdate) { std::thread{ [] { @@ -386,11 +387,13 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR l } bool openScoobe = false; + bool showRestartNotificationAfterUpdate = false; try { std::wstring last_version_run = PTSettingsHelper::get_last_version_run(); const auto product_version = get_product_version(); openScoobe = product_version != last_version_run; + showRestartNotificationAfterUpdate = openScoobe; Logger::info(L"Scoobe: product_version={} last_version_run={}", product_version, last_version_run); } catch (const std::exception& e) @@ -422,6 +425,16 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR l const bool run_elevated_setting = general_settings.GetNamedBoolean(L"run_elevated", false); const bool with_restartedElevated_arg = cmdLine.find("--restartedElevated") != std::string::npos; + // Update scoobe behavior based on setting and gpo + bool scoobeSettingDisabled = general_settings.GetNamedBoolean(L"show_whats_new_after_updates", true) == false; + bool scoobeDisabledByGpo = powertoys_gpo::getDisableShowWhatsNewAfterUpdatesValue() == powertoys_gpo::gpo_rule_configured_enabled; + if (openScoobe && (scoobeSettingDisabled || scoobeDisabledByGpo)) + { + // Scoobe should show after an update, but is disabled by policy or setting + Logger::info(L"Scoobe: Showing scoobe after updates is disabled by setting or by GPO."); + openScoobe = false; + } + if (elevated && with_dont_elevate_arg && !run_elevated_setting) { Logger::info("Scheduling restart as non elevated"); @@ -436,7 +449,7 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR l Logger::info("Restart as elevated failed. Running non-elevated."); } - result = runner(elevated, open_settings, settings_window, openOobe, openScoobe); + result = runner(elevated, open_settings, settings_window, openOobe, openScoobe, showRestartNotificationAfterUpdate); if (result == 0) { diff --git a/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs b/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs index ba97a590d7..2256898b45 100644 --- a/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs +++ b/src/settings-ui/Settings.UI.Library/FindMyMouseProperties.cs @@ -43,6 +43,12 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("shaking_minimum_distance")] public IntProperty ShakingMinimumDistance { get; set; } + [JsonPropertyName("shaking_interval_ms")] + public IntProperty ShakingIntervalMs { get; set; } + + [JsonPropertyName("shaking_factor")] + public IntProperty ShakingFactor { get; set; } + public FindMyMouseProperties() { ActivationMethod = new IntProperty(0); @@ -56,6 +62,8 @@ namespace Microsoft.PowerToys.Settings.UI.Library SpotlightInitialZoom = new IntProperty(9); ExcludedApps = new StringProperty(); ShakingMinimumDistance = new IntProperty(1000); + ShakingIntervalMs = new IntProperty(1000); + ShakingFactor = new IntProperty(400); } } } diff --git a/src/settings-ui/Settings.UI.Library/GeneralSettings.cs b/src/settings-ui/Settings.UI.Library/GeneralSettings.cs index 68648bdfbc..f8d4030d3d 100644 --- a/src/settings-ui/Settings.UI.Library/GeneralSettings.cs +++ b/src/settings-ui/Settings.UI.Library/GeneralSettings.cs @@ -51,9 +51,15 @@ namespace Microsoft.PowerToys.Settings.UI.Library [JsonPropertyName("enabled")] public EnabledModules Enabled { get; set; } + [JsonPropertyName("show_new_updates_toast_notification")] + public bool ShowNewUpdatesToastNotification { get; set; } + [JsonPropertyName("download_updates_automatically")] public bool AutoDownloadUpdates { get; set; } + [JsonPropertyName("show_whats_new_after_updates")] + public bool ShowWhatsNewAfterUpdates { get; set; } + [JsonPropertyName("enable_experimentation")] public bool EnableExperimentation { get; set; } @@ -63,6 +69,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library IsAdmin = false; EnableWarningsElevatedApps = true; IsElevated = false; + ShowNewUpdatesToastNotification = true; AutoDownloadUpdates = false; EnableExperimentation = true; Theme = "system"; diff --git a/src/settings-ui/Settings.UI/Helpers/ModuleHelper.cs b/src/settings-ui/Settings.UI/Helpers/ModuleHelper.cs index 7daa62ae0d..25d5fb4f59 100644 --- a/src/settings-ui/Settings.UI/Helpers/ModuleHelper.cs +++ b/src/settings-ui/Settings.UI/Helpers/ModuleHelper.cs @@ -44,7 +44,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers case ModuleType.AlwaysOnTop: return generalSettingsConfig.Enabled.AlwaysOnTop; case ModuleType.Awake: return generalSettingsConfig.Enabled.Awake; case ModuleType.ColorPicker: return generalSettingsConfig.Enabled.ColorPicker; - case ModuleType.CmdNotFound: return generalSettingsConfig.Enabled.CmdNotFound; case ModuleType.CropAndLock: return generalSettingsConfig.Enabled.CropAndLock; case ModuleType.EnvironmentVariables: return generalSettingsConfig.Enabled.EnvironmentVariables; case ModuleType.FancyZones: return generalSettingsConfig.Enabled.FancyZones; @@ -77,7 +76,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers case ModuleType.AlwaysOnTop: generalSettingsConfig.Enabled.AlwaysOnTop = isEnabled; break; case ModuleType.Awake: generalSettingsConfig.Enabled.Awake = isEnabled; break; case ModuleType.ColorPicker: generalSettingsConfig.Enabled.ColorPicker = isEnabled; break; - case ModuleType.CmdNotFound: generalSettingsConfig.Enabled.CmdNotFound = isEnabled; break; case ModuleType.CropAndLock: generalSettingsConfig.Enabled.CropAndLock = isEnabled; break; case ModuleType.EnvironmentVariables: generalSettingsConfig.Enabled.EnvironmentVariables = isEnabled; break; case ModuleType.FancyZones: generalSettingsConfig.Enabled.FancyZones = isEnabled; break; @@ -109,7 +107,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers case ModuleType.AlwaysOnTop: return GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue(); case ModuleType.Awake: return GPOWrapper.GetConfiguredAwakeEnabledValue(); case ModuleType.ColorPicker: return GPOWrapper.GetConfiguredColorPickerEnabledValue(); - case ModuleType.CmdNotFound: return GPOWrapper.GetConfiguredCmdNotFoundEnabledValue(); case ModuleType.CropAndLock: return GPOWrapper.GetConfiguredCropAndLockEnabledValue(); case ModuleType.EnvironmentVariables: return GPOWrapper.GetConfiguredEnvironmentVariablesEnabledValue(); case ModuleType.FancyZones: return GPOWrapper.GetConfiguredFancyZonesEnabledValue(); @@ -142,7 +139,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers ModuleType.AlwaysOnTop => Color.FromArgb(255, 74, 196, 242), // #4ac4f2 ModuleType.Awake => Color.FromArgb(255, 40, 177, 233), // #28b1e9 ModuleType.ColorPicker => Color.FromArgb(255, 7, 129, 211), // #0781d3 - ModuleType.CmdNotFound => Color.FromArgb(255, 31, 164, 227), // #1fa4e3 ModuleType.CropAndLock => Color.FromArgb(255, 32, 166, 228), // #20a6e4 ModuleType.EnvironmentVariables => Color.FromArgb(255, 16, 132, 208), // #1084d0 ModuleType.FancyZones => Color.FromArgb(255, 65, 209, 247), // #41d1f7 @@ -175,7 +171,6 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers ModuleType.AlwaysOnTop => typeof(AlwaysOnTopPage), ModuleType.Awake => typeof(AwakePage), ModuleType.ColorPicker => typeof(ColorPickerPage), - ModuleType.CmdNotFound => typeof(CmdNotFoundPage), ModuleType.CropAndLock => typeof(CropAndLockPage), ModuleType.EnvironmentVariables => typeof(EnvironmentVariablesPage), ModuleType.FancyZones => typeof(FancyZonesPage), diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml index 2a5fb16385..857b027808 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/GeneralPage.xaml @@ -188,6 +188,29 @@ IsOpen="{x:Bind ViewModel.ShowAutoDownloadUpdatesGpoInformation, Mode=OneWay}" IsTabStop="{x:Bind ViewModel.ShowAutoDownloadUpdatesGpoInformation, Mode=OneWay}" Severity="Informational" /> + + + + + + + + + + diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml index 0228c9f2d4..39aa3e6e95 100644 --- a/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml +++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/MouseUtilsPage.xaml @@ -56,6 +56,26 @@ SpinButtonPlacementMode="Compact" Value="{x:Bind ViewModel.FindMyMouseShakingMinimumDistance, Mode=TwoWay}" /> + + + + + + The minimum distance for mouse shaking activation, for adjusting sensitivity + + Shake Interval (ms) + ms = milliseconds + + + The span of time during which we track mouse movement to detect shaking, for adjusting sensitivity + + + Shake factor (percent) + + + Mouse shaking is detected by checking how much the mouse pointer has travelled when compared to the diagonal of the movement area. Reducing this factor increases sensitivity. + Mouse Highlighter Refers to the utility name @@ -3998,7 +4011,16 @@ Activate by holding the key for the character you want to add an accent to, then Text size of result titles + + Show the release notes after updates + Command Not Found is not supported on the ARM64 architecture currently. We are actively working on a solution. - + + Notifications in the settings and the tray flyout are always shown + + + Show notifications for new updates + + \ No newline at end of file diff --git a/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs index 17b6e2b142..e449356beb 100644 --- a/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/GeneralViewModel.cs @@ -121,7 +121,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } _startup = GeneralSettingsConfig.Startup; + _showNewUpdatesToastNotification = GeneralSettingsConfig.ShowNewUpdatesToastNotification; _autoDownloadUpdates = GeneralSettingsConfig.AutoDownloadUpdates; + _showWhatsNewAfterUpdates = GeneralSettingsConfig.ShowWhatsNewAfterUpdates; _enableExperimentation = GeneralSettingsConfig.EnableExperimentation; _isElevated = isElevated; @@ -138,8 +140,10 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels _newAvailableVersionLink = UpdatingSettingsConfig.ReleasePageLink; _updateCheckedDate = UpdatingSettingsConfig.LastCheckedDateLocalized; - _experimentationIsGpoDisallowed = GPOWrapper.GetAllowExperimentationValue() == GpoRuleConfigured.Disabled; + _newUpdatesToastIsGpoDisabled = GPOWrapper.GetDisableNewUpdateToastValue() == GpoRuleConfigured.Enabled; _autoDownloadUpdatesIsGpoDisabled = GPOWrapper.GetDisableAutomaticUpdateDownloadValue() == GpoRuleConfigured.Enabled; + _experimentationIsGpoDisallowed = GPOWrapper.GetAllowExperimentationValue() == GpoRuleConfigured.Disabled; + _showWhatsNewAfterUpdatesIsGpoDisabled = GPOWrapper.GetDisableShowWhatsNewAfterUpdatesValue() == GpoRuleConfigured.Enabled; if (dispatcherAction != null) { @@ -154,8 +158,12 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private bool _enableWarningsElevatedApps; private int _themeIndex; + private bool _showNewUpdatesToastNotification; + private bool _newUpdatesToastIsGpoDisabled; private bool _autoDownloadUpdates; private bool _autoDownloadUpdatesIsGpoDisabled; + private bool _showWhatsNewAfterUpdates; + private bool _showWhatsNewAfterUpdatesIsGpoDisabled; private bool _enableExperimentation; private bool _experimentationIsGpoDisallowed; @@ -299,6 +307,29 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } } + public bool ShowNewUpdatesToastNotification + { + get + { + return _showNewUpdatesToastNotification && !_newUpdatesToastIsGpoDisabled; + } + + set + { + if (_showNewUpdatesToastNotification != value) + { + _showNewUpdatesToastNotification = value; + GeneralSettingsConfig.ShowNewUpdatesToastNotification = value; + NotifyPropertyChanged(); + } + } + } + + public bool IsNewUpdatesToastDisabledGpoConfigured + { + get => _newUpdatesToastIsGpoDisabled; + } + public bool AutoDownloadUpdates { get @@ -329,6 +360,29 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels get => _isAdmin && _autoDownloadUpdatesIsGpoDisabled; } + public bool ShowWhatsNewAfterUpdates + { + get + { + return _showWhatsNewAfterUpdates && !_showWhatsNewAfterUpdatesIsGpoDisabled; + } + + set + { + if (_showWhatsNewAfterUpdates != value) + { + _showWhatsNewAfterUpdates = value; + GeneralSettingsConfig.ShowWhatsNewAfterUpdates = value; + NotifyPropertyChanged(); + } + } + } + + public bool ShowWhatsNewAfterUpdatesIsGpoDisabled + { + get => _showWhatsNewAfterUpdatesIsGpoDisabled; + } + public bool EnableExperimentation { get diff --git a/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs b/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs index f7b9934e58..05d8184a46 100644 --- a/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs +++ b/src/settings-ui/Settings.UI/ViewModels/MouseUtilsViewModel.cs @@ -58,6 +58,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels _findMyMouseSpotlightInitialZoom = FindMyMouseSettingsConfig.Properties.SpotlightInitialZoom.Value; _findMyMouseExcludedApps = FindMyMouseSettingsConfig.Properties.ExcludedApps.Value; _findMyMouseShakingMinimumDistance = FindMyMouseSettingsConfig.Properties.ShakingMinimumDistance.Value; + _findMyMouseShakingIntervalMs = FindMyMouseSettingsConfig.Properties.ShakingIntervalMs.Value; + _findMyMouseShakingFactor = FindMyMouseSettingsConfig.Properties.ShakingFactor.Value; ArgumentNullException.ThrowIfNull(mouseHighlighterSettingsRepository); @@ -402,6 +404,42 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels } } + public int FindMyMouseShakingIntervalMs + { + get + { + return _findMyMouseShakingIntervalMs; + } + + set + { + if (value != _findMyMouseShakingIntervalMs) + { + _findMyMouseShakingIntervalMs = value; + FindMyMouseSettingsConfig.Properties.ShakingIntervalMs.Value = value; + NotifyFindMyMousePropertyChanged(); + } + } + } + + public int FindMyMouseShakingFactor + { + get + { + return _findMyMouseShakingFactor; + } + + set + { + if (value != _findMyMouseShakingFactor) + { + _findMyMouseShakingFactor = value; + FindMyMouseSettingsConfig.Properties.ShakingFactor.Value = value; + NotifyFindMyMousePropertyChanged(); + } + } + } + public void NotifyFindMyMousePropertyChanged([CallerMemberName] string propertyName = null) { OnPropertyChanged(propertyName); @@ -944,6 +982,8 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels private int _findMyMouseSpotlightInitialZoom; private string _findMyMouseExcludedApps; private int _findMyMouseShakingMinimumDistance; + private int _findMyMouseShakingIntervalMs; + private int _findMyMouseShakingFactor; private GpoRuleConfigured _highlighterEnabledGpoRuleConfiguration; private bool _highlighterEnabledStateIsGPOConfigured;