mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-07 11:46:30 +02:00
Merge branch 'microsoft/main' into dev/seraphima/tests/29246-fancyzones-tests-initial-step
This commit is contained in:
@@ -3,12 +3,12 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RootNamespace>EnvironmentVariables</RootNamespace>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<RuntimeIdentifiers>win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<EnableMsixTooling>true</EnableMsixTooling>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
@@ -34,10 +34,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
|
||||
@@ -7,6 +7,7 @@ using System.Runtime.InteropServices;
|
||||
using EnvironmentVariables.Helpers;
|
||||
using EnvironmentVariables.Helpers.Win32;
|
||||
using EnvironmentVariables.ViewModels;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using WinUIEx;
|
||||
|
||||
@@ -30,19 +31,20 @@ namespace EnvironmentVariables
|
||||
Title = title;
|
||||
AppTitleTextBlock.Text = title;
|
||||
|
||||
RegisterWindow();
|
||||
var handle = this.GetWindowHandle();
|
||||
RegisterWindow(handle);
|
||||
|
||||
WindowHelpers.BringToForeground(handle);
|
||||
}
|
||||
|
||||
private static readonly DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
private static NativeMethods.WinProc newWndProc;
|
||||
private static IntPtr oldWndProc = IntPtr.Zero;
|
||||
|
||||
private void RegisterWindow()
|
||||
private void RegisterWindow(IntPtr handle)
|
||||
{
|
||||
newWndProc = new NativeMethods.WinProc(WndProc);
|
||||
|
||||
var handle = this.GetWindowHandle();
|
||||
|
||||
oldWndProc = NativeMethods.SetWindowLongPtr(handle, NativeMethods.WindowLongIndexFlags.GWL_WNDPROC, newWndProc);
|
||||
}
|
||||
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<ToggleSwitch
|
||||
x:Uid="ToggleSwitch"
|
||||
IsOn="{x:Bind Mode=TwoWay, Path=IsEnabled}"
|
||||
IsOn="{x:Bind IsEnabled, Mode=TwoWay}"
|
||||
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}" />
|
||||
<Button Content="{ui:FontIcon Glyph=}" Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
@@ -465,14 +465,13 @@
|
||||
TextChanged="EditVariableDialogValueTxtBox_TextChanged"
|
||||
TextWrapping="Wrap" />
|
||||
<MenuFlyoutSeparator Visibility="{Binding ShowAsList, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<ListView
|
||||
<ItemsControl
|
||||
x:Name="EditVariableValuesList"
|
||||
Margin="-16,-8,0,12"
|
||||
Margin="0,-8,0,12"
|
||||
HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding ValuesList, Mode=TwoWay}"
|
||||
SelectionMode="None"
|
||||
Visibility="{Binding ShowAsList, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<ListView.ItemTemplate>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -523,8 +522,8 @@
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</ContentDialog>
|
||||
@@ -583,15 +582,14 @@
|
||||
HorizontalAlignment="Right"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
<ListView
|
||||
<ItemsControl
|
||||
x:Name="NewProfileVariablesListView"
|
||||
Grid.Row="1"
|
||||
Grid.ColumnSpan="2"
|
||||
Margin="-16,-8,0,12"
|
||||
Margin="0,-8,0,12"
|
||||
HorizontalAlignment="Stretch"
|
||||
ItemsSource="{Binding Variables, Mode=TwoWay}"
|
||||
SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
ItemsSource="{Binding Variables, Mode=TwoWay}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:Variable">
|
||||
<Grid Height="48" ColumnSpacing="8">
|
||||
<Grid.ColumnDefinitions>
|
||||
@@ -617,8 +615,8 @@
|
||||
Visibility="Collapsed" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{c604b37e-9d0e-4484-8778-e8b31b0e1b3a}</ProjectGuid>
|
||||
<RootNamespace>FileLocksmithLibInterop</RootNamespace>
|
||||
<TargetFramework>net7.0-windows</TargetFramework>
|
||||
<TargetFramework>net8.0-windows</TargetFramework>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\</OutDir>
|
||||
<TargetName>PowerToys.FileLocksmithLib.Interop</TargetName>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -5,14 +5,14 @@
|
||||
<AssemblyTitle>PowerToys.FileLocksmith</AssemblyTitle>
|
||||
<AssemblyDescription>PowerToys File Locksmith</AssemblyDescription>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
|
||||
<RootNamespace>PowerToys.FileLocksmithUI</RootNamespace>
|
||||
<AssemblyName>PowerToys.FileLocksmithUI</AssemblyName>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<RuntimeIdentifiers>win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
@@ -35,10 +35,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -5,11 +5,11 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<PublishDir>$(PowerToysRoot)\$(Platform)\$(Configuration)\WinUI3Apps</PublishDir>
|
||||
<RuntimeIdentifier>win10-$(Platform)</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-$(Platform)</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>False</PublishSingleFile>
|
||||
<PublishReadyToRun>False</PublishReadyToRun>
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<IsPackable>false</IsPackable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RootNamespace>Hosts</RootNamespace>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<RuntimeIdentifiers>win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
<WindowsPackageType>None</WindowsPackageType>
|
||||
@@ -34,10 +34,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Hosts.Settings
|
||||
private const string HostsModuleName = "Hosts";
|
||||
private const int MaxNumberOfRetry = 5;
|
||||
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
private readonly IFileSystemWatcher _watcher;
|
||||
private readonly object _loadingSettingsLock = new object();
|
||||
|
||||
|
||||
@@ -289,7 +289,7 @@ namespace Hosts.ViewModels
|
||||
Entries.RefreshFilter();
|
||||
}
|
||||
|
||||
// Ping and duplicate should't trigger a file save
|
||||
// Ping and duplicate should not trigger a file save
|
||||
if (e.PropertyName == nameof(Entry.Ping)
|
||||
|| e.PropertyName == nameof(Entry.Pinging)
|
||||
|| e.PropertyName == nameof(Entry.Duplicate))
|
||||
|
||||
@@ -51,9 +51,9 @@ private:
|
||||
|
||||
HANDLE m_hProcess = nullptr;
|
||||
|
||||
HANDLE m_hShowEvent;
|
||||
HANDLE m_hShowEvent{};
|
||||
|
||||
HANDLE m_hShowAdminEvent;
|
||||
HANDLE m_hShowAdminEvent{};
|
||||
|
||||
bool is_process_running()
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.230913002\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.230913002\build\native\Microsoft.WindowsAppSDK.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.756\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.756\build\Microsoft.Windows.SDK.BuildTools.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.231115000\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.231115000\build\native\Microsoft.WindowsAppSDK.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||
@@ -146,8 +146,8 @@
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.230913002\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.230913002\build\native\Microsoft.WindowsAppSDK.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.231115000\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.231115000\build\native\Microsoft.WindowsAppSDK.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.756\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.756\build\Microsoft.Windows.SDK.BuildTools.targets')" />
|
||||
</ImportGroup>
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
<PropertyGroup>
|
||||
@@ -156,9 +156,9 @@
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.220914.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.755\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.230913002\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.230913002\build\native\Microsoft.WindowsAppSDK.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.230913002\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.230913002\build\native\Microsoft.WindowsAppSDK.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.231115000\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.231115000\build\native\Microsoft.WindowsAppSDK.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.231115000\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.4.231115000\build\native\Microsoft.WindowsAppSDK.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.756\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.756\build\Microsoft.Windows.SDK.BuildTools.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.756\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.756\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -2,6 +2,6 @@
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.221104.6" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.220914.1" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.755" targetFramework="native" />
|
||||
<package id="Microsoft.WindowsAppSDK" version="1.4.230913002" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.756" targetFramework="native" />
|
||||
<package id="Microsoft.WindowsAppSDK" version="1.4.231115000" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -5,14 +5,14 @@
|
||||
<AssemblyTitle>PowerToys.MeasureTool</AssemblyTitle>
|
||||
<AssemblyDescription>PowerToys MeasureTool</AssemblyDescription>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
|
||||
<RootNamespace>PowerToys.MeasureToolUI</RootNamespace>
|
||||
<AssemblyName>PowerToys.MeasureToolUI</AssemblyName>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<Platforms>x86;x64;arm64</Platforms>
|
||||
<RuntimeIdentifiers>win10-x86;win10-x64;win10-arm64</RuntimeIdentifiers>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<GenerateSatelliteAssembliesForCore>true</GenerateSatelliteAssembliesForCore>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
@@ -35,10 +35,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<ProjectGuid>{D9C5DE64-6849-4278-91AD-9660AECF2876}</ProjectGuid>
|
||||
|
||||
@@ -16,10 +16,7 @@ internal static class LayoutHelper
|
||||
public static LayoutInfo CalculateLayoutInfo(
|
||||
LayoutConfig layoutConfig)
|
||||
{
|
||||
if (layoutConfig is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(layoutConfig));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(layoutConfig);
|
||||
|
||||
var builder = new LayoutInfo.Builder
|
||||
{
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -32,7 +32,7 @@
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>MouseJumpUI</RootNamespace>
|
||||
<AssemblyName>PowerToys.MouseJumpUI</AssemblyName>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
|
||||
@@ -45,6 +45,10 @@ namespace MouseWithoutBorders
|
||||
private static string lastDragDropFile;
|
||||
private static long clipboardCopiedTime;
|
||||
|
||||
internal static readonly char[] Comma = new char[] { ',' };
|
||||
internal static readonly char[] Star = new char[] { '*' };
|
||||
internal static readonly char[] NullSeparator = new char[] { '\0' };
|
||||
|
||||
internal static ID LastIDWithClipboardData { get; set; }
|
||||
|
||||
internal static string LastDragDropFile
|
||||
@@ -406,7 +410,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
try
|
||||
{
|
||||
remoteMachine = postAct.Contains("mspaint,") ? postAct.Split(new char[] { ',' })[1] : Common.LastMachineWithClipboardData;
|
||||
remoteMachine = postAct.Contains("mspaint,") ? postAct.Split(Comma)[1] : Common.LastMachineWithClipboardData;
|
||||
|
||||
remoteMachine = remoteMachine.Trim();
|
||||
|
||||
@@ -518,7 +522,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
fileName = Common.GetStringU(header).Replace("\0", string.Empty);
|
||||
Common.LogDebug("Header: " + fileName);
|
||||
string[] headers = fileName.Split(new char[] { '*' });
|
||||
string[] headers = fileName.Split(Star);
|
||||
|
||||
if (headers.Length < 2 || !long.TryParse(headers[0], out long dataSize))
|
||||
{
|
||||
@@ -973,7 +977,7 @@ namespace MouseWithoutBorders
|
||||
|
||||
foreach (string txt in texts)
|
||||
{
|
||||
if (string.IsNullOrEmpty(txt.Trim(new char[] { '\0' })))
|
||||
if (string.IsNullOrEmpty(txt.Trim(NullSeparator)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
internal partial class Common
|
||||
{
|
||||
private static SymmetricAlgorithm symAl;
|
||||
#pragma warning disable SYSLIB0021
|
||||
private static AesCryptoServiceProvider symAl;
|
||||
#pragma warning restore SYSLIB0021
|
||||
private static string myKey;
|
||||
private static uint magicNumber;
|
||||
private static Random ran = new(); // Used for non encryption related functionality.
|
||||
@@ -115,7 +117,7 @@ namespace MouseWithoutBorders
|
||||
byte[] rv;
|
||||
string myKey = Common.MyKey;
|
||||
|
||||
if (!LegalKeyDictionary.ContainsKey(myKey))
|
||||
if (!LegalKeyDictionary.TryGetValue(myKey, out byte[] value))
|
||||
{
|
||||
Rfc2898DeriveBytes key = new(
|
||||
myKey,
|
||||
@@ -127,7 +129,7 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = LegalKeyDictionary[myKey];
|
||||
rv = value;
|
||||
}
|
||||
|
||||
return rv;
|
||||
|
||||
@@ -313,7 +313,8 @@ namespace MouseWithoutBorders
|
||||
HasSwitchedMachineSinceLastCopy = true;
|
||||
|
||||
// Common.CreateLowIntegrityProcess("\"" + Path.GetDirectoryName(Application.ExecutablePath) + "\\MouseWithoutBordersHelper.exe\"", string.Empty, 0, false, 0);
|
||||
if (Process.GetProcessesByName(HelperProcessName)?.Any() != true)
|
||||
var processes = Process.GetProcessesByName(HelperProcessName);
|
||||
if (processes?.Length == 0)
|
||||
{
|
||||
Log("Unable to start helper process.");
|
||||
Common.ShowToolTip("Error starting Mouse Without Borders Helper, clipboard sharing will not work!", 5000, ToolTipIcon.Error);
|
||||
@@ -325,7 +326,8 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Process.GetProcessesByName(HelperProcessName)?.Any() == true)
|
||||
var processes = Process.GetProcessesByName(HelperProcessName);
|
||||
if (processes?.Length > 0)
|
||||
{
|
||||
Log("Helper process found running.");
|
||||
}
|
||||
@@ -432,7 +434,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
if (string.IsNullOrEmpty(Setting.Values.Username) && !Common.RunOnLogonDesktop)
|
||||
{
|
||||
if (Program.User.ToLower(CultureInfo.CurrentCulture).Contains("system"))
|
||||
if (Program.User.Contains("system", StringComparison.CurrentCultureIgnoreCase))
|
||||
{
|
||||
_ = Common.ImpersonateLoggedOnUserAndDoSomething(() =>
|
||||
{
|
||||
|
||||
@@ -84,12 +84,11 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Globalization", "CA1304:SpecifyCultureInfo", MessageId = "System.String.ToLower", Justification = "Dotnet port with style preservation")]
|
||||
internal static int CreateProcessInInputDesktopSession(string commandLine, string arg, string desktop, short wShowWindow, bool lowIntegrity = false)
|
||||
|
||||
// As user who runs explorer.exe
|
||||
{
|
||||
if (!Program.User.ToLower(CultureInfo.InvariantCulture).Contains("system"))
|
||||
if (!Program.User.Contains("system", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ProcessStartInfo s = new(commandLine, arg);
|
||||
s.WindowStyle = wShowWindow != 0 ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden;
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace MouseWithoutBorders
|
||||
{
|
||||
Process[] ps = Process.GetProcessesByName("MouseWithoutBordersSvc");
|
||||
|
||||
if (ps.Any())
|
||||
if (ps.Length != 0)
|
||||
{
|
||||
if (DateTime.UtcNow - lastStartServiceTime < TimeSpan.FromSeconds(5))
|
||||
{
|
||||
|
||||
@@ -353,6 +353,7 @@ namespace MouseWithoutBorders.Class
|
||||
private static bool ctrlDown;
|
||||
private static bool altDown;
|
||||
private static bool shiftDown;
|
||||
internal static readonly string[] Args = new string[] { "CAD" };
|
||||
|
||||
private static void ResetModifiersState(HotkeySettings matchingHotkey)
|
||||
{
|
||||
@@ -456,7 +457,7 @@ namespace MouseWithoutBorders.Class
|
||||
if (ctrlDown && altDown)
|
||||
{
|
||||
ctrlDown = altDown = false;
|
||||
new ServiceController("MouseWithoutBordersSvc").Start(new string[] { "CAD" });
|
||||
new ServiceController("MouseWithoutBordersSvc").Start(Args);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
else if (list.Count >= 4)
|
||||
{
|
||||
throw new ArgumentException("machineNames.Length > Common.MAX_MACHINE");
|
||||
throw new ArgumentException($"The number of machines exceeded the maximum allowed limit of {Common.MAX_MACHINE}. Actual count: {list.Count}.");
|
||||
}
|
||||
|
||||
_ = LearnMachine(name);
|
||||
@@ -178,7 +178,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
else if (list.Count >= 4)
|
||||
{
|
||||
throw new ArgumentException("infos.Length > Common.MAX_MACHINE");
|
||||
throw new ArgumentException($"The number of machines exceeded the maximum allowed limit of {Common.MAX_MACHINE}. Actual count: {list.Count}.");
|
||||
}
|
||||
|
||||
_ = LearnMachine(inf.Name);
|
||||
|
||||
@@ -8,6 +8,9 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
internal static class MachinePoolHelpers
|
||||
{
|
||||
internal static readonly char[] Comma = new char[] { ',' };
|
||||
internal static readonly char[] Colon = new char[] { ':' };
|
||||
|
||||
internal static MachineInf[] LoadMachineInfoFromMachinePoolStringSetting(string s)
|
||||
{
|
||||
if (s == null)
|
||||
@@ -15,7 +18,7 @@ namespace MouseWithoutBorders.Class
|
||||
throw new ArgumentNullException(s);
|
||||
}
|
||||
|
||||
string[] st = s.Split(new char[] { ',' });
|
||||
string[] st = s.Split(Comma);
|
||||
|
||||
if (st.Length < Common.MAX_MACHINE)
|
||||
{
|
||||
@@ -25,7 +28,7 @@ namespace MouseWithoutBorders.Class
|
||||
MachineInf[] rv = new MachineInf[Common.MAX_MACHINE];
|
||||
for (int i = 0; i < Common.MAX_MACHINE; i++)
|
||||
{
|
||||
string[] mc = st[i].Split(new char[] { ':' });
|
||||
string[] mc = st[i].Split(Colon);
|
||||
if (mc.Length == 2)
|
||||
{
|
||||
rv[i].Name = mc[0];
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace MouseWithoutBorders.Class
|
||||
{
|
||||
internal bool Changed;
|
||||
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
private readonly object _loadingSettingsLock = new object();
|
||||
private readonly IFileSystemWatcher _watcher;
|
||||
|
||||
|
||||
@@ -887,14 +887,14 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
if (!string.IsNullOrEmpty(Setting.Values.Name2IP))
|
||||
{
|
||||
string[] name2ip = Setting.Values.Name2IP.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
string[] name2ip = Setting.Values.Name2IP.Split(Separator, StringSplitOptions.RemoveEmptyEntries);
|
||||
string[] nameNip;
|
||||
|
||||
if (name2ip != null)
|
||||
{
|
||||
foreach (string st in name2ip)
|
||||
{
|
||||
nameNip = st.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
nameNip = st.Split(BlankSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if (nameNip != null && nameNip.Length >= 2 && nameNip[0].Trim().Equals(machineName, StringComparison.OrdinalIgnoreCase)
|
||||
&& IPAddress.TryParse(nameNip[1].Trim(), out IPAddress ip) && !validAddressesSt.Contains("[" + ip.ToString() + "]")
|
||||
@@ -1063,7 +1063,7 @@ namespace MouseWithoutBorders.Class
|
||||
|
||||
List<IPAddress> localIPv4Addresses = GetMyIPv4Addresses().ToList();
|
||||
|
||||
if (!localIPv4Addresses.Any())
|
||||
if (localIPv4Addresses.Count == 0)
|
||||
{
|
||||
Common.Log($"No IPv4 resolved from the local machine: {Common.MachineName}");
|
||||
return true;
|
||||
@@ -1234,6 +1234,8 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
|
||||
private long lastRemoteMachineID;
|
||||
internal static readonly string[] Separator = new string[] { "\r\n" };
|
||||
internal static readonly char[] BlankSeparator = new char[] { ' ' };
|
||||
|
||||
private void MainTCPRoutine(TcpSk tcp, string machineName, bool isClient)
|
||||
{
|
||||
|
||||
@@ -104,6 +104,7 @@ namespace MouseWithoutBorders.Class
|
||||
}
|
||||
|
||||
private static bool logged;
|
||||
internal static readonly string[] Separator = new[] { " " };
|
||||
|
||||
private void LogError(string log)
|
||||
{
|
||||
@@ -146,7 +147,7 @@ namespace MouseWithoutBorders.Class
|
||||
try
|
||||
{
|
||||
// Assuming the format of netstat's output is fixed.
|
||||
pid = int.Parse(portLogLine.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries).Last(), CultureInfo.CurrentCulture);
|
||||
pid = int.Parse(portLogLine.Split(Separator, StringSplitOptions.RemoveEmptyEntries).Last(), CultureInfo.CurrentCulture);
|
||||
process = Process.GetProcessById(pid);
|
||||
}
|
||||
catch (Exception)
|
||||
|
||||
@@ -123,13 +123,14 @@ namespace MouseWithoutBorders
|
||||
}
|
||||
|
||||
private string lastMessage = string.Empty;
|
||||
private static readonly string[] Separator = new string[] { "\r\n" };
|
||||
|
||||
internal void ShowTip(ToolTipIcon icon, string msg, int durationInMilliseconds)
|
||||
{
|
||||
int x = 0;
|
||||
string text = msg + $"\r\n {(lastMessage.Equals(msg, StringComparison.OrdinalIgnoreCase) ? string.Empty : $"\r\nPrevious message/error: {lastMessage}")} ";
|
||||
lastMessage = msg;
|
||||
int y = (-text.Split(new string[] { "\r\n" }, StringSplitOptions.None).Length * 15) - 30;
|
||||
int y = (-text.Split(Separator, StringSplitOptions.None).Length * 15) - 30;
|
||||
|
||||
toolTipManual.Hide(this);
|
||||
|
||||
|
||||
@@ -742,11 +742,13 @@ namespace MouseWithoutBorders
|
||||
LoadMachines();
|
||||
}
|
||||
|
||||
internal static readonly string[] Separator = new string[] { "\r\n" };
|
||||
|
||||
internal void ShowTip(ToolTipIcon icon, string text, int duration)
|
||||
{
|
||||
int x = 0;
|
||||
text += "\r\n ";
|
||||
int y = (-text.Split(new string[] { "\r\n" }, StringSplitOptions.None).Length * 15) - 30;
|
||||
int y = (-text.Split(Separator, StringSplitOptions.None).Length * 15) - 30;
|
||||
|
||||
toolTipManual.Hide(this);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\..\Version.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<OutputType>WinExe</OutputType>
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<OutputType>WinExe</OutputType>
|
||||
@@ -19,10 +19,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\..\Version.props" />
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<ImplicitUsings>true</ImplicitUsings>
|
||||
@@ -20,10 +20,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<DefineConstants>TRACE;DEBUG;SHOW_ON_WINLOGON CODE_ANALYSIS CUSTOMIZE_LOGON_SCREEN</DefineConstants>
|
||||
|
||||
@@ -148,6 +148,8 @@ internal sealed class ImageMethods
|
||||
return resultText.Trim();
|
||||
}
|
||||
|
||||
internal static readonly char[] Separator = new char[] { '\n', '\r' };
|
||||
|
||||
public static async Task<string> ExtractText(Bitmap bmp, Language? preferredLanguage, System.Windows.Point? singlePoint = null)
|
||||
{
|
||||
Language? selectedLanguage = preferredLanguage ?? GetOCRLanguage();
|
||||
@@ -211,7 +213,7 @@ internal sealed class ImageMethods
|
||||
|
||||
if (culture.TextInfo.IsRightToLeft)
|
||||
{
|
||||
string[] textListLines = text.ToString().Split(new char[] { '\n', '\r' });
|
||||
string[] textListLines = text.ToString().Split(Separator);
|
||||
|
||||
_ = text.Clear();
|
||||
foreach (string textLine in textListLines)
|
||||
|
||||
@@ -220,9 +220,6 @@ public class WrappingStream : Stream
|
||||
private void ThrowIfDisposed()
|
||||
{
|
||||
// throws an ObjectDisposedException if this object has been disposed
|
||||
if (_streamBase == null)
|
||||
{
|
||||
throw new ObjectDisposedException(GetType().Name);
|
||||
}
|
||||
ObjectDisposedException.ThrowIf(_streamBase == null, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ public class ResultTable
|
||||
return rowAreas;
|
||||
}
|
||||
|
||||
private static void CheckIntersectionsWithWordBorders(int hitGridSpacing, ICollection<WordBorder> wordBorders, ICollection<int> rowAreas, int i, Rect horizontalLineRect)
|
||||
private static void CheckIntersectionsWithWordBorders(int hitGridSpacing, ICollection<WordBorder> wordBorders, List<int> rowAreas, int i, Rect horizontalLineRect)
|
||||
{
|
||||
foreach (WordBorder wb in wordBorders)
|
||||
{
|
||||
|
||||
@@ -49,7 +49,9 @@ public partial class OCROverlay : Window
|
||||
Top = screenRectangle.Top >= 0 ? screenRectangle.Top : screenRectangle.Top + (screenRectangle.Height / 2);
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this, Wpf.Ui.Controls.WindowBackdropType.None);
|
||||
|
||||
PopulateLanguageMenu();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -28,7 +28,7 @@
|
||||
<PackageIcon>PowerOCRLogo.png</PackageIcon>
|
||||
<RootNamespace>PowerOCR</RootNamespace>
|
||||
<AssemblyName>PowerToys.PowerOCR</AssemblyName>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<ProjectTypeGuids>{2150E333-8FDC-42A3-9474-1A3956D46DE8}</ProjectTypeGuids>
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace PowerOCR.Settings
|
||||
[Export(typeof(IUserSettings))]
|
||||
public class UserSettings : IUserSettings
|
||||
{
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
private const string PowerOcrModuleName = "TextExtractor";
|
||||
private const string DefaultActivationShortcut = "Win + Shift + O";
|
||||
private const int MaxNumberOfRetry = 5;
|
||||
|
||||
41
src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.base.rc
Normal file
41
src/modules/alwaysontop/AlwaysOnTop/AlwaysOnTop.base.rc
Normal file
@@ -0,0 +1,41 @@
|
||||
#include <windows.h>
|
||||
#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"
|
||||
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
|
||||
END
|
||||
END
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
#include <common/utils/winapi_error.h>
|
||||
#include <common/utils/process_path.h>
|
||||
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/notifications/NotificationUtil.h>
|
||||
#include <Generated Files/resource.h>
|
||||
|
||||
#include <interop/shared_constants.h>
|
||||
|
||||
#include <trace.h>
|
||||
@@ -489,6 +493,10 @@ void AlwaysOnTop::HandleWinHookEvent(WinHookEvent* data) noexcept
|
||||
break;
|
||||
case EVENT_SYSTEM_FOREGROUND:
|
||||
{
|
||||
if (!is_process_elevated() && IsProcessOfWindowElevated(data->hwnd))
|
||||
{
|
||||
notifications::WarnIfElevationIsRequired(GET_RESOURCE_STRING(IDS_ALWAYSONTOP), GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED), GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_LEARN_MORE), GET_RESOURCE_STRING(IDS_SYSTEM_FOREGROUND_ELEVATED_DIALOG_DONT_SHOW_AGAIN));
|
||||
}
|
||||
RefreshBorders();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
<!-- Project configurations -->
|
||||
<!-- Props that should be disabled while building on CI server -->
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h AlwaysOnTop.base.rc AlwaysOnTop.rc" />
|
||||
</Target>
|
||||
<ItemDefinitionGroup Condition="'$(CIBuild)'!='true'">
|
||||
<ClCompile>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
@@ -141,9 +144,12 @@
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AlwaysOnTop.h" />
|
||||
<ClInclude Include="FrameDrawer.h" />
|
||||
<ClInclude Include="Generated Files/resource.h" />
|
||||
<ClInclude Include="ModuleConstants.h" />
|
||||
<ClInclude Include="NotificationUtil.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<None Include="resource.base.h" />
|
||||
<ClInclude Include="ScalingUtils.h" />
|
||||
<ClInclude Include="Settings.h" />
|
||||
<ClInclude Include="SettingsConstants.h" />
|
||||
@@ -167,10 +173,17 @@
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\notifications\notifications.vcxproj">
|
||||
<Project>{1d5be09d-78c0-4fd7-af00-ae7c1af7c525}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="AlwaysOnTop.rc" />
|
||||
<ResourceCompile Include="Generated Files/AlwaysOnTop.rc" />
|
||||
<None Include="AlwaysOnTop.base.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Resources.resx" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
|
||||
@@ -12,6 +12,9 @@
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{A74B5AAC-E913-410D-8941-D73346CF47AE}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -49,8 +52,22 @@
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files/AlwaysOnTop.rc">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Resources.resx">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="resource.base.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</None>
|
||||
<None Include="AlwaysOnTop.base.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
@@ -97,6 +114,9 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="ScalingUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Generated Files/resource.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
134
src/modules/alwaysontop/AlwaysOnTop/Resources.resx
Normal file
134
src/modules/alwaysontop/AlwaysOnTop/Resources.resx
Normal file
@@ -0,0 +1,134 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AlwaysOnTop" xml:space="preserve">
|
||||
<value>AlwaysOnTop</value>
|
||||
<comment>AlwaysOnTop is a product name, keep as is.</comment>
|
||||
</data>
|
||||
<data name="System_Foreground_Elevated" xml:space="preserve">
|
||||
<value>We've detected an application running with administrator privileges. This will prevent certain interactions with these applications.</value>
|
||||
<comment>administrator is context of user account.</comment>
|
||||
</data>
|
||||
<data name="System_Foreground_Elevated_Learn_More" xml:space="preserve">
|
||||
<value>Learn more</value>
|
||||
</data>
|
||||
<data name="System_Foreground_Elevated_Dialog_Dont_Show_Again" xml:space="preserve">
|
||||
<value>Don't show again</value>
|
||||
</data>
|
||||
</root>
|
||||
13
src/modules/alwaysontop/AlwaysOnTop/resource.base.h
Normal file
13
src/modules/alwaysontop/AlwaysOnTop/resource.base.h
Normal file
@@ -0,0 +1,13 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by AlwaysOnTop.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys.AlwaysOnTop"
|
||||
#define INTERNAL_NAME "PowerToys.AlwaysOnTop"
|
||||
#define ORIGINAL_FILENAME "PowerToys.AlwaysOnTop.exe"
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
||||
@@ -2,7 +2,7 @@
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
@@ -24,10 +24,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
|
||||
@@ -11,15 +11,9 @@ namespace Awake.Core
|
||||
{
|
||||
public static void AddRange<T>(this ICollection<T> target, IEnumerable<T> source)
|
||||
{
|
||||
if (target == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(target));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(target);
|
||||
|
||||
if (source == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
|
||||
foreach (var element in source)
|
||||
{
|
||||
|
||||
@@ -28,6 +28,9 @@ namespace Awake.Core
|
||||
/// </summary>
|
||||
public class Manager
|
||||
{
|
||||
private static readonly CompositeFormat AwakeMinutes = System.Text.CompositeFormat.Parse(Properties.Resources.AWAKE_MINUTES);
|
||||
private static readonly CompositeFormat AwakeHours = System.Text.CompositeFormat.Parse(Properties.Resources.AWAKE_HOURS);
|
||||
|
||||
private static BlockingCollection<ExecutionState> _stateQueue;
|
||||
|
||||
private static CancellationTokenSource _tokenSource;
|
||||
@@ -276,9 +279,9 @@ namespace Awake.Core
|
||||
{
|
||||
Dictionary<string, int> optionsList = new Dictionary<string, int>
|
||||
{
|
||||
{ string.Format(CultureInfo.InvariantCulture, Resources.AWAKE_MINUTES, 30), 1800 },
|
||||
{ string.Format(CultureInfo.InvariantCulture, AwakeMinutes, 30), 1800 },
|
||||
{ Resources.AWAKE_1_HOUR, 3600 },
|
||||
{ string.Format(CultureInfo.InvariantCulture, Resources.AWAKE_HOURS, 2), 7200 },
|
||||
{ string.Format(CultureInfo.InvariantCulture, AwakeHours, 2), 7200 },
|
||||
};
|
||||
return optionsList;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,11 @@ namespace Awake
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
|
||||
private static ManualResetEvent _exitSignal = new ManualResetEvent(false);
|
||||
internal static readonly string[] AliasesConfigOption = new[] { "--use-pt-config", "-c" };
|
||||
internal static readonly string[] AliasesDisplayOption = new[] { "--display-on", "-d" };
|
||||
internal static readonly string[] AliasesTimeOption = new[] { "--time-limit", "-t" };
|
||||
internal static readonly string[] AliasesPidOption = new[] { "--pid", "-p" };
|
||||
internal static readonly string[] AliasesExpireAtOption = new[] { "--expire-at", "-e" };
|
||||
|
||||
private static int Main(string[] args)
|
||||
{
|
||||
@@ -86,7 +91,7 @@ namespace Awake
|
||||
Logger.LogInfo("Parsing parameters...");
|
||||
|
||||
Option<bool> configOption = new(
|
||||
aliases: new[] { "--use-pt-config", "-c" },
|
||||
aliases: AliasesConfigOption,
|
||||
getDefaultValue: () => false,
|
||||
description: $"Specifies whether {Core.Constants.AppName} will be using the PowerToys configuration file for managing the state.")
|
||||
{
|
||||
@@ -95,7 +100,7 @@ namespace Awake
|
||||
};
|
||||
|
||||
Option<bool> displayOption = new(
|
||||
aliases: new[] { "--display-on", "-d" },
|
||||
aliases: AliasesDisplayOption,
|
||||
getDefaultValue: () => true,
|
||||
description: "Determines whether the display should be kept awake.")
|
||||
{
|
||||
@@ -104,7 +109,7 @@ namespace Awake
|
||||
};
|
||||
|
||||
Option<uint> timeOption = new(
|
||||
aliases: new[] { "--time-limit", "-t" },
|
||||
aliases: AliasesTimeOption,
|
||||
getDefaultValue: () => 0,
|
||||
description: "Determines the interval, in seconds, during which the computer is kept awake.")
|
||||
{
|
||||
@@ -113,7 +118,7 @@ namespace Awake
|
||||
};
|
||||
|
||||
Option<int> pidOption = new(
|
||||
aliases: new[] { "--pid", "-p" },
|
||||
aliases: AliasesPidOption,
|
||||
getDefaultValue: () => 0,
|
||||
description: $"Bind the execution of {Core.Constants.AppName} to another process. When the process ends, the system will resume managing the current sleep and display state.")
|
||||
{
|
||||
@@ -122,7 +127,7 @@ namespace Awake
|
||||
};
|
||||
|
||||
Option<string> expireAtOption = new(
|
||||
aliases: new[] { "--expire-at", "-e" },
|
||||
aliases: AliasesExpireAtOption,
|
||||
getDefaultValue: () => string.Empty,
|
||||
description: $"Determines the end date/time when {Core.Constants.AppName} will back off and let the system manage the current sleep and display state.")
|
||||
{
|
||||
|
||||
69
src/modules/cmdNotFound/CmdNotFound/CmdNotFound.csproj
Normal file
69
src/modules/cmdNotFound/CmdNotFound/CmdNotFound.csproj
Normal file
@@ -0,0 +1,69 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Authors>Microsoft Corporation</Authors>
|
||||
<Product>PowerToys</Product>
|
||||
<Nullable>enable</Nullable>
|
||||
<Description>PowerToys CommandNotFound</Description>
|
||||
<AssemblyName>PowerToys.CmdNotFound</AssemblyName>
|
||||
<GenerateDependencyFile>false</GenerateDependencyFile>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)</OutputPath>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<SelfContained>true</SelfContained>
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Optimize>false</Optimize>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'">
|
||||
<DefineConstants>TRACE;RELEASE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.ObjectPool">
|
||||
<ExcludeAssets>contentFiles</ExcludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; compile; build; native; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Management.Automation">
|
||||
<ExcludeAssets>contentFiles</ExcludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<Content Include="WinGetCommandNotFound.psd1">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
57
src/modules/cmdNotFound/CmdNotFound/Init.cs
Normal file
57
src/modules/cmdNotFound/CmdNotFound/Init.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
// 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.Management.Automation;
|
||||
using System.Management.Automation.Subsystem;
|
||||
using System.Management.Automation.Subsystem.Feedback;
|
||||
using System.Management.Automation.Subsystem.Prediction;
|
||||
|
||||
namespace WinGetCommandNotFound
|
||||
{
|
||||
public sealed class Init : IModuleAssemblyInitializer, IModuleAssemblyCleanup
|
||||
{
|
||||
internal const string Id = "e5351aa4-dfde-4d4d-bf0f-1a2f5a37d8d6";
|
||||
|
||||
public void OnImport()
|
||||
{
|
||||
if (!Platform.IsWindows || !IsWinGetInstalled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SubsystemManager.RegisterSubsystem(SubsystemKind.FeedbackProvider, WinGetCommandNotFoundFeedbackPredictor.Singleton);
|
||||
SubsystemManager.RegisterSubsystem(SubsystemKind.CommandPredictor, WinGetCommandNotFoundFeedbackPredictor.Singleton);
|
||||
}
|
||||
|
||||
public void OnRemove(PSModuleInfo psModuleInfo)
|
||||
{
|
||||
if (!IsWinGetInstalled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SubsystemManager.UnregisterSubsystem<IFeedbackProvider>(new Guid(Id));
|
||||
SubsystemManager.UnregisterSubsystem<ICommandPredictor>(new Guid(Id));
|
||||
}
|
||||
|
||||
private bool IsWinGetInstalled()
|
||||
{
|
||||
// Ensure WinGet is installed
|
||||
using (var pwsh = PowerShell.Create(RunspaceMode.CurrentRunspace))
|
||||
{
|
||||
var results = pwsh.AddCommand("Get-Command")
|
||||
.AddParameter("Name", "winget")
|
||||
.AddParameter("CommandType", "Application")
|
||||
.Invoke();
|
||||
|
||||
if (results.Count is 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// 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.Management.Automation;
|
||||
using System.Management.Automation.Runspaces;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
|
||||
namespace WinGetCommandNotFound
|
||||
{
|
||||
public sealed class PooledPowerShellObjectPolicy : IPooledObjectPolicy<PowerShell>
|
||||
{
|
||||
private static readonly string[] WingetClientModuleName = new[] { "Microsoft.WinGet.Client" };
|
||||
|
||||
public PowerShell Create()
|
||||
{
|
||||
var iss = InitialSessionState.CreateDefault2();
|
||||
iss.ImportPSModule(WingetClientModuleName);
|
||||
return PowerShell.Create(iss);
|
||||
}
|
||||
|
||||
public bool Return(PowerShell obj)
|
||||
{
|
||||
if (obj != null)
|
||||
{
|
||||
obj.Commands.Clear();
|
||||
obj.Streams.ClearStreams();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace WinGetCommandNotFound.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class CmdNotFoundFeedbackProvidedEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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.Diagnostics.Tracing;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.PowerToys.Telemetry.Events;
|
||||
|
||||
namespace WinGetCommandNotFound.Telemetry
|
||||
{
|
||||
[EventData]
|
||||
public class CmdNotFoundSuggestionProvidedEvent : EventBase, IEvent
|
||||
{
|
||||
public PartA_PrivTags PartA_PrivTags => PartA_PrivTags.ProductAndServiceUsage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
@{
|
||||
ModuleVersion = '0.1.0'
|
||||
GUID = '28c9afa2-92e5-413e-8e53-44b2d7a83ac6'
|
||||
Author = 'Carlos Zamora'
|
||||
CompanyName = "Microsoft Corporation"
|
||||
Copyright = "Copyright (c) Microsoft Corporation."
|
||||
Description = 'Enable suggestions on how to install missing commands via winget'
|
||||
PowerShellVersion = '7.4'
|
||||
NestedModules = @('PowerToys.CmdNotFound.dll')
|
||||
RequiredModules = @(@{ModuleName = 'Microsoft.WinGet.Client'; ModuleVersion = "0.2.1"; })
|
||||
}
|
||||
@@ -0,0 +1,217 @@
|
||||
// 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;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Management.Automation;
|
||||
using System.Management.Automation.Subsystem.Feedback;
|
||||
using System.Management.Automation.Subsystem.Prediction;
|
||||
using ManagedCommon;
|
||||
using Microsoft.Extensions.ObjectPool;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
|
||||
namespace WinGetCommandNotFound
|
||||
{
|
||||
public sealed class WinGetCommandNotFoundFeedbackPredictor : IFeedbackProvider, ICommandPredictor
|
||||
{
|
||||
private readonly Guid _guid;
|
||||
|
||||
private readonly ObjectPool<PowerShell> _pool;
|
||||
|
||||
private const int _maxSuggestions = 20;
|
||||
|
||||
private List<string>? _candidates;
|
||||
|
||||
private bool _warmedUp;
|
||||
|
||||
public static WinGetCommandNotFoundFeedbackPredictor Singleton { get; } = new WinGetCommandNotFoundFeedbackPredictor(Init.Id);
|
||||
|
||||
private WinGetCommandNotFoundFeedbackPredictor(string guid)
|
||||
{
|
||||
Logger.InitializeLogger("\\CmdNotFound\\Logs");
|
||||
|
||||
_guid = new Guid(guid);
|
||||
|
||||
var provider = new DefaultObjectPoolProvider();
|
||||
_pool = provider.Create(new PooledPowerShellObjectPolicy());
|
||||
_pool.Return(_pool.Get());
|
||||
Task.Run(() => WarmUp());
|
||||
}
|
||||
|
||||
public Guid Id => _guid;
|
||||
|
||||
public string Name => "Windows Package Manager - WinGet";
|
||||
|
||||
public string Description => "Finds missing commands that can be installed via WinGet.";
|
||||
|
||||
public Dictionary<string, string>? FunctionsToDefine => null;
|
||||
|
||||
private void WarmUp()
|
||||
{
|
||||
var ps = _pool.Get();
|
||||
try
|
||||
{
|
||||
ps.AddCommand("Find-WinGetPackage")
|
||||
.AddParameter("Count", 1)
|
||||
.Invoke();
|
||||
}
|
||||
finally
|
||||
{
|
||||
_pool.Return(ps);
|
||||
_warmedUp = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets feedback based on the given commandline and error record.
|
||||
/// </summary>
|
||||
public FeedbackItem? GetFeedback(FeedbackContext context, CancellationToken token)
|
||||
{
|
||||
var target = (string)context.LastError!.TargetObject;
|
||||
if (target is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool tooManySuggestions = false;
|
||||
string packageMatchFilterField = "command";
|
||||
var pkgList = FindPackages(target, ref tooManySuggestions, ref packageMatchFilterField);
|
||||
if (pkgList.Count == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Build list of suggestions
|
||||
_candidates = new List<string>();
|
||||
foreach (var pkg in pkgList)
|
||||
{
|
||||
_candidates.Add(string.Format(CultureInfo.InvariantCulture, "winget install --id {0}", pkg.Members["Id"].Value.ToString()));
|
||||
}
|
||||
|
||||
// Build footer message
|
||||
var footerMessage = tooManySuggestions ?
|
||||
string.Format(CultureInfo.InvariantCulture, "Additional results can be found using \"winget search --{0} {1}\"", packageMatchFilterField, target) :
|
||||
null;
|
||||
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.CmdNotFoundFeedbackProvidedEvent());
|
||||
|
||||
return new FeedbackItem(
|
||||
"Try installing this package using winget:",
|
||||
_candidates,
|
||||
footerMessage,
|
||||
FeedbackDisplayLayout.Portrait);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("GetFeedback failed to execute", ex);
|
||||
return new FeedbackItem($"Failed to execute PowerToys Command Not Found.{Environment.NewLine}This is a known issue if PowerShell 7 is installed from the Store or MSIX. If that isn't your case, please report an issue.", new List<string>(), FeedbackDisplayLayout.Portrait);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Collection<PSObject> FindPackages(string query, ref bool tooManySuggestions, ref string packageMatchFilterField)
|
||||
{
|
||||
if (!_warmedUp)
|
||||
{
|
||||
return new Collection<PSObject>();
|
||||
}
|
||||
|
||||
var ps = _pool.Get();
|
||||
try
|
||||
{
|
||||
var common = new Hashtable()
|
||||
{
|
||||
["Source"] = "winget",
|
||||
};
|
||||
|
||||
// 1) Search by command
|
||||
var pkgList = ps.AddCommand("Find-WinGetPackage")
|
||||
.AddParameter("Command", query)
|
||||
.AddParameter("MatchOption", "StartsWithCaseInsensitive")
|
||||
.AddParameters(common)
|
||||
.Invoke();
|
||||
if (pkgList.Count > 0)
|
||||
{
|
||||
tooManySuggestions = pkgList.Count > _maxSuggestions;
|
||||
packageMatchFilterField = "command";
|
||||
return pkgList;
|
||||
}
|
||||
|
||||
// 2) No matches found,
|
||||
// search by name
|
||||
ps.Commands.Clear();
|
||||
pkgList = ps.AddCommand("Find-WinGetPackage")
|
||||
.AddParameter("Name", query)
|
||||
.AddParameter("MatchOption", "ContainsCaseInsensitive")
|
||||
.AddParameters(common)
|
||||
.Invoke();
|
||||
if (pkgList.Count > 0)
|
||||
{
|
||||
tooManySuggestions = pkgList.Count > _maxSuggestions;
|
||||
packageMatchFilterField = "name";
|
||||
return pkgList;
|
||||
}
|
||||
|
||||
// 3) No matches found,
|
||||
// search by moniker
|
||||
ps.Commands.Clear();
|
||||
pkgList = ps.AddCommand("Find-WinGetPackage")
|
||||
.AddParameter("Moniker", query)
|
||||
.AddParameter("MatchOption", "ContainsCaseInsensitive")
|
||||
.AddParameters(common)
|
||||
.Invoke();
|
||||
tooManySuggestions = pkgList.Count > _maxSuggestions;
|
||||
packageMatchFilterField = "moniker";
|
||||
return pkgList;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_pool.Return(ps);
|
||||
}
|
||||
}
|
||||
|
||||
public bool CanAcceptFeedback(PredictionClient client, PredictorFeedbackKind feedback)
|
||||
{
|
||||
return feedback switch
|
||||
{
|
||||
PredictorFeedbackKind.CommandLineAccepted => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
public SuggestionPackage GetSuggestion(PredictionClient client, PredictionContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
if (_candidates is not null)
|
||||
{
|
||||
string input = context.InputAst.Extent.Text;
|
||||
List<PredictiveSuggestion>? result = null;
|
||||
|
||||
foreach (string c in _candidates)
|
||||
{
|
||||
if (c.StartsWith(input, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result ??= new List<PredictiveSuggestion>(_candidates.Count);
|
||||
result.Add(new PredictiveSuggestion(c));
|
||||
}
|
||||
}
|
||||
|
||||
if (result is not null)
|
||||
{
|
||||
PowerToysTelemetry.Log.WriteEvent(new Telemetry.CmdNotFoundSuggestionProvidedEvent());
|
||||
return new SuggestionPackage(result);
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public void OnCommandLineAccepted(PredictionClient client, IReadOnlyList<string> history)
|
||||
{
|
||||
// Reset the candidate state.
|
||||
_candidates = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../../../common/version/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#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
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (United States) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
#pragma code_page(1252)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// String Table
|
||||
//
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CMD_NOT_FOUND_NAME "Command Not Found"
|
||||
END
|
||||
|
||||
#endif // English (United States) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{0014d652-901f-4456-8d65-06fc5f997fb0}</ProjectGuid>
|
||||
<RootNamespace>CmdNotFoundModuleInterface</RootNamespace>
|
||||
<TargetName>PowerToys.CmdNotFoundModuleInterface</TargetName>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<ProjectName>CmdNotFoundModuleInterface</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Debug'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;CMDNOTFOUNDMODULEINTERFACE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>Shlwapi.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)'=='Release'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;CMDNOTFOUNDMODULEINTERFACE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>Shlwapi.lib;$(CoreLibraryDependencies);%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\Telemetry;..\..\;..\..\..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="CmdNotFoundModuleInterface.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0"
|
||||
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="CmdNotFoundModuleInterface.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
158
src/modules/cmdNotFound/CmdNotFoundModuleInterface/dllmain.cpp
Normal file
158
src/modules/cmdNotFound/CmdNotFoundModuleInterface/dllmain.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/logger/logger_settings.h>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
#include <common/utils/gpo.h>
|
||||
#include <common/utils/logger_helper.h>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/utils/resources.h>
|
||||
#include <interface/powertoy_module_interface.h>
|
||||
|
||||
#include "resource.h"
|
||||
#include "trace.h"
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE /*hModule*/, DWORD ul_reason_for_call, LPVOID /*lpReserved*/)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
Trace::RegisterProvider();
|
||||
break;
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
Trace::UnregisterProvider();
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
const static wchar_t* MODULE_NAME = L"Command Not Found";
|
||||
const static wchar_t* MODULE_DESC = L"A module that detects an error thrown by a command in PowerShell and suggests a relevant WinGet package to install, if available.";
|
||||
|
||||
inline const std::wstring ModuleKey = L"CmdNotFound";
|
||||
|
||||
class CmdNotFound : public PowertoyModuleIface
|
||||
{
|
||||
std::wstring app_name;
|
||||
std::wstring app_key;
|
||||
|
||||
private:
|
||||
bool m_enabled = false;
|
||||
|
||||
void install_module()
|
||||
{
|
||||
auto module_path = get_module_folderpath();
|
||||
|
||||
std::string command = "pwsh.exe";
|
||||
command += " ";
|
||||
command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + winrt::to_string(module_path) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\EnableModule.ps1" + "\"" + " -scriptPath \"" + winrt::to_string(module_path) + "\"";
|
||||
|
||||
int ret = system(command.c_str());
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
Logger::error("Running EnableModule.ps1 script failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info("Module installed successfully.");
|
||||
Trace::EnableCmdNotFoundGpo(true);
|
||||
}
|
||||
}
|
||||
|
||||
void uninstall_module()
|
||||
{
|
||||
auto module_path = get_module_folderpath();
|
||||
|
||||
std::string command = "pwsh.exe";
|
||||
command += " ";
|
||||
command += "-NoProfile -NonInteractive -NoLogo -WindowStyle Hidden -ExecutionPolicy Unrestricted -File \"" + winrt::to_string(module_path) + "\\WinUI3Apps\\Assets\\Settings\\Scripts\\DisableModule.ps1" + "\"";
|
||||
|
||||
int ret = system(command.c_str());
|
||||
|
||||
if (ret != 0)
|
||||
{
|
||||
Logger::error("Running EnableModule.ps1 script failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info("Module uninstalled successfully.");
|
||||
Trace::EnableCmdNotFoundGpo(false);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
CmdNotFound()
|
||||
{
|
||||
app_name = GET_RESOURCE_STRING(IDS_CMD_NOT_FOUND_NAME);
|
||||
app_key = ModuleKey;
|
||||
LoggerHelpers::init_logger(app_key, L"ModuleInterface", LogSettings::cmdNotFoundLoggerName);
|
||||
Logger::info("CmdNotFound object is constructing");
|
||||
|
||||
powertoys_gpo::gpo_rule_configured_t gpo_rule_configured_value = gpo_policy_enabled_configuration();
|
||||
if (gpo_rule_configured_value == powertoys_gpo::gpo_rule_configured_t::gpo_rule_configured_enabled)
|
||||
{
|
||||
install_module();
|
||||
m_enabled = true;
|
||||
}
|
||||
else if (gpo_rule_configured_value == powertoys_gpo::gpo_rule_configured_t::gpo_rule_configured_disabled)
|
||||
{
|
||||
uninstall_module();
|
||||
m_enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual powertoys_gpo::gpo_rule_configured_t gpo_policy_enabled_configuration() override
|
||||
{
|
||||
return powertoys_gpo::getConfiguredCmdNotFoundEnabledValue();
|
||||
}
|
||||
|
||||
virtual void destroy() override
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual const wchar_t* get_name() override
|
||||
{
|
||||
return MODULE_NAME;
|
||||
}
|
||||
|
||||
virtual const wchar_t* get_key() override
|
||||
{
|
||||
return app_key.c_str();
|
||||
}
|
||||
|
||||
virtual bool get_config(wchar_t* /*buffer*/, int* /*buffer_size*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void set_config(const wchar_t* config) override
|
||||
{
|
||||
}
|
||||
|
||||
virtual void enable()
|
||||
{
|
||||
}
|
||||
|
||||
virtual void disable()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool is_enabled() override
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
{
|
||||
return new CmdNotFound();
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
||||
16
src/modules/cmdNotFound/CmdNotFoundModuleInterface/pch.h
Normal file
16
src/modules/cmdNotFound/CmdNotFoundModuleInterface/pch.h
Normal file
@@ -0,0 +1,16 @@
|
||||
// pch.h: This is a precompiled header file.
|
||||
// Files listed below are compiled only once, improving build performance for future builds.
|
||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
// Windows Header Files
|
||||
#include <windows.h>
|
||||
|
||||
#include <ProjectTelemetry.h>
|
||||
|
||||
#endif //PCH_H
|
||||
@@ -0,0 +1,21 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by Awake.rc
|
||||
//
|
||||
#define IDS_CMD_NOT_FOUND_NAME 101
|
||||
|
||||
|
||||
#define FILE_DESCRIPTION "PowerToys Command Not Found"
|
||||
#define INTERNAL_NAME "PowerToys.CmdNotFoundModuleInterface"
|
||||
#define ORIGINAL_FILENAME "PowerToys.CmdNotFoundModuleInterface.dll"
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 102
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1001
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
30
src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.cpp
Normal file
30
src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "pch.h"
|
||||
#include "trace.h"
|
||||
|
||||
TRACELOGGING_DEFINE_PROVIDER(
|
||||
g_hProvider,
|
||||
"Microsoft.PowerToys",
|
||||
// {38e8889b-9731-53f5-e901-e8a7c1753074}
|
||||
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
|
||||
TraceLoggingOptionProjectTelemetry());
|
||||
|
||||
void Trace::RegisterProvider()
|
||||
{
|
||||
TraceLoggingRegister(g_hProvider);
|
||||
}
|
||||
|
||||
void Trace::UnregisterProvider()
|
||||
{
|
||||
TraceLoggingUnregister(g_hProvider);
|
||||
}
|
||||
|
||||
// Log if the user has CmdNotFound enabled or disabled
|
||||
void Trace::EnableCmdNotFoundGpo(const bool enabled) noexcept
|
||||
{
|
||||
TraceLoggingWrite(
|
||||
g_hProvider,
|
||||
"CmdNotFound_EnableCmdNotFound",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
|
||||
TraceLoggingBoolean(enabled, "Enabled"));
|
||||
}
|
||||
11
src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.h
Normal file
11
src/modules/cmdNotFound/CmdNotFoundModuleInterface/trace.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
class Trace
|
||||
{
|
||||
public:
|
||||
static void RegisterProvider();
|
||||
static void UnregisterProvider();
|
||||
|
||||
// Log if the user has CmdNotFound enabled or disabled
|
||||
static void EnableCmdNotFoundGpo(const bool enabled) noexcept;
|
||||
};
|
||||
@@ -20,7 +20,7 @@ namespace ColorPicker.Behaviors
|
||||
private static readonly TimeSpan _animationTimeSmaller = _animationTime;
|
||||
private static readonly IEasingFunction _easeFunctionSmaller = new QuadraticEase() { EasingMode = EasingMode.EaseIn };
|
||||
|
||||
private static void CustomAnimation(DependencyProperty prop, IAnimatable sender, double fromValue, double toValue)
|
||||
private static void CustomAnimation(DependencyProperty prop, FrameworkElement sender, double fromValue, double toValue)
|
||||
{
|
||||
// if the animation is to/from a value of 0, it will cancel the current animation
|
||||
DoubleAnimation move = null;
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
|
||||
<!-- SelfContained=true requires RuntimeIdentifier to be set -->
|
||||
<PropertyGroup Condition="'$(Platform)'=='x64'">
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Platform)'=='ARM64'">
|
||||
<RuntimeIdentifier>win10-arm64</RuntimeIdentifier>
|
||||
<RuntimeIdentifier>win-arm64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
@@ -25,7 +25,7 @@
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>ColorPicker</RootNamespace>
|
||||
<AssemblyName>PowerToys.ColorPickerUI</AssemblyName>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
|
||||
@@ -28,10 +28,7 @@ namespace ColorPicker.Common
|
||||
|
||||
public void AddRange(IEnumerable<T> list)
|
||||
{
|
||||
if (list == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(list));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(list);
|
||||
|
||||
_suppressNotification = true;
|
||||
|
||||
|
||||
@@ -329,7 +329,7 @@ namespace ColorPicker.Controls
|
||||
newHexString = newHexString.ToLowerInvariant();
|
||||
|
||||
// Return only with hashtag if user typed it before
|
||||
bool addHashtag = oldValue.StartsWith("#", StringComparison.InvariantCulture);
|
||||
bool addHashtag = oldValue.StartsWith('#');
|
||||
return addHashtag ? "#" + newHexString : newHexString;
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ namespace ColorPicker.Controls
|
||||
else
|
||||
{
|
||||
// Hex with or without hashtag and six characters
|
||||
return hexCodeText.StartsWith("#", StringComparison.InvariantCulture) ? hexCodeText : "#" + hexCodeText;
|
||||
return hexCodeText.StartsWith('#') ? hexCodeText : "#" + hexCodeText;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Windows.Media;
|
||||
using ColorPicker.Models;
|
||||
|
||||
@@ -21,6 +22,9 @@ namespace ColorPicker.Helpers
|
||||
|
||||
internal static class SerializationHelper
|
||||
{
|
||||
public static readonly JsonSerializerOptions DefaultOptions = new JsonSerializerOptions { WriteIndented = false };
|
||||
public static readonly JsonSerializerOptions IndentedOptions = new JsonSerializerOptions { WriteIndented = true };
|
||||
|
||||
public static Dictionary<string, Dictionary<string, string>> ConvertToDesiredColorFormats(
|
||||
IList colorsToExport,
|
||||
IEnumerable<ColorFormatModel> colorRepresentations,
|
||||
@@ -116,10 +120,7 @@ namespace ColorPicker.Helpers
|
||||
|
||||
public static string ToJson(this Dictionary<string, Dictionary<string, string>> source, bool indented = true)
|
||||
{
|
||||
var options = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = indented,
|
||||
};
|
||||
var options = indented ? IndentedOptions : DefaultOptions;
|
||||
|
||||
return JsonSerializer.Serialize(source, options);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace ColorPicker.Helpers
|
||||
ShowZoomWindow(point);
|
||||
}
|
||||
|
||||
private static BitmapSource BitmapToImageSource(Bitmap bitmap)
|
||||
private static BitmapImage BitmapToImageSource(Bitmap bitmap)
|
||||
{
|
||||
using (MemoryStream memory = new MemoryStream())
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace ColorPicker.Settings
|
||||
[Export(typeof(IUserSettings))]
|
||||
public class UserSettings : IUserSettings
|
||||
{
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
private const string ColorPickerModuleName = "ColorPicker";
|
||||
private const string ColorPickerHistoryFilename = "colorHistory.json";
|
||||
private const string DefaultActivationShortcut = "Ctrl + Break";
|
||||
@@ -36,6 +36,11 @@ namespace ColorPicker.Settings
|
||||
|
||||
private bool _loadingColorsHistory;
|
||||
|
||||
private static readonly JsonSerializerOptions _serializerOptions = new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true,
|
||||
};
|
||||
|
||||
[ImportingConstructor]
|
||||
public UserSettings(Helpers.IThrottledActionInvoker throttledActionInvoker)
|
||||
{
|
||||
@@ -58,7 +63,7 @@ namespace ColorPicker.Settings
|
||||
{
|
||||
if (!_loadingColorsHistory)
|
||||
{
|
||||
_settingsUtils.SaveSettings(JsonSerializer.Serialize(ColorHistory, new JsonSerializerOptions { WriteIndented = true }), ColorPickerModuleName, ColorPickerHistoryFilename);
|
||||
_settingsUtils.SaveSettings(JsonSerializer.Serialize(ColorHistory, _serializerOptions), ColorPickerModuleName, ColorPickerHistoryFilename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<Import Project="..\..\..\Version.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<ProjectGuid>{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}</ProjectGuid>
|
||||
|
||||
@@ -394,15 +394,6 @@ void FancyZones::WindowCreated(HWND window) noexcept
|
||||
return;
|
||||
}
|
||||
|
||||
// Hotfix
|
||||
// Avoid automatically moving popup windows, as they can be just popup menus.
|
||||
bool isPopup = FancyZonesWindowUtils::IsPopupWindow(window);
|
||||
bool hasThickFrame = FancyZonesWindowUtils::HasThickFrame(window);
|
||||
if (isPopup && !hasThickFrame)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid already stamped (zoned) windows
|
||||
const bool isZoned = !FancyZonesWindowProperties::RetrieveZoneIndexProperty(window).empty();
|
||||
if (isZoned)
|
||||
@@ -1005,41 +996,42 @@ void FancyZones::RefreshLayouts() noexcept
|
||||
|
||||
bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
|
||||
{
|
||||
auto window = GetForegroundWindow();
|
||||
if (!FancyZonesSettings::settings().overrideSnapHotkeys)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto window = GetForegroundWindow();
|
||||
if (!FancyZonesWindowProcessing::IsProcessable(window))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FancyZonesSettings::settings().overrideSnapHotkeys)
|
||||
HMONITOR monitor = WorkAreaKeyFromWindow(window);
|
||||
|
||||
auto workArea = m_workAreaConfiguration.GetWorkArea(monitor);
|
||||
if (!workArea)
|
||||
{
|
||||
HMONITOR monitor = WorkAreaKeyFromWindow(window);
|
||||
Logger::error(L"No work area for processing snap hotkey");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto workArea = m_workAreaConfiguration.GetWorkArea(monitor);
|
||||
if (!workArea)
|
||||
const auto& layout = workArea->GetLayout();
|
||||
if (!layout)
|
||||
{
|
||||
Logger::error(L"No layout for processing snap hotkey");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layout->Zones().size() > 0)
|
||||
{
|
||||
if (vkCode == VK_UP || vkCode == VK_DOWN)
|
||||
{
|
||||
Logger::error(L"No work area for processing snap hotkey");
|
||||
return false;
|
||||
return FancyZonesSettings::settings().moveWindowsBasedOnPosition;
|
||||
}
|
||||
|
||||
const auto& layout = workArea->GetLayout();
|
||||
if (!layout)
|
||||
else
|
||||
{
|
||||
Logger::error(L"No layout for processing snap hotkey");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layout->Zones().size() > 0)
|
||||
{
|
||||
if (vkCode == VK_UP || vkCode == VK_DOWN)
|
||||
{
|
||||
return FancyZonesSettings::settings().moveWindowsBasedOnPosition;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,7 +61,6 @@
|
||||
<ClInclude Include="ModuleConstants.h" />
|
||||
<ClInclude Include="MonitorUtils.h" />
|
||||
<ClInclude Include="WorkAreaConfiguration.h" />
|
||||
<ClInclude Include="NotificationUtil.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="Generated Files/resource.h" />
|
||||
<None Include="resource.base.h" />
|
||||
|
||||
@@ -153,9 +153,6 @@
|
||||
<ClInclude Include="HighlightedZones.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NotificationUtil.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HighlightedZones.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -5,52 +5,69 @@
|
||||
#include <FancyZonesLib/VirtualDesktop.h>
|
||||
#include <FancyZonesLib/WindowUtils.h>
|
||||
|
||||
bool FancyZonesWindowProcessing::IsProcessable(HWND window) noexcept
|
||||
FancyZonesWindowProcessing::ProcessabilityType FancyZonesWindowProcessing::DefineWindowType(HWND window) noexcept
|
||||
{
|
||||
const bool isSplashScreen = FancyZonesWindowUtils::IsSplashScreen(window);
|
||||
if (isSplashScreen)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool windowMinimized = IsIconic(window);
|
||||
if (windowMinimized)
|
||||
{
|
||||
return false;
|
||||
return ProcessabilityType::Minimized;
|
||||
}
|
||||
|
||||
const bool standard = FancyZonesWindowUtils::IsStandardWindow(window);
|
||||
if (!standard)
|
||||
auto style = GetWindowLong(window, GWL_STYLE);
|
||||
auto exStyle = GetWindowLong(window, GWL_EXSTYLE);
|
||||
|
||||
if (!FancyZonesWindowUtils::HasStyle(style, WS_VISIBLE))
|
||||
{
|
||||
return false;
|
||||
return ProcessabilityType::NotVisible;
|
||||
}
|
||||
|
||||
// popup could be the window we don't want to snap: start menu, notification popup, tray window, etc.
|
||||
// also, popup could be the windows we want to snap disregarding the "allowSnapPopupWindows" setting, e.g. Telegram
|
||||
bool isPopup = FancyZonesWindowUtils::IsPopupWindow(window) && !FancyZonesWindowUtils::HasThickFrameAndMinimizeMaximizeButtons(window);
|
||||
if (isPopup && !FancyZonesSettings::settings().allowSnapPopupWindows)
|
||||
if (FancyZonesWindowUtils::HasStyle(exStyle, WS_EX_TOOLWINDOW))
|
||||
{
|
||||
return false;
|
||||
return ProcessabilityType::ToolWindow;
|
||||
}
|
||||
|
||||
if (!FancyZonesWindowUtils::IsRoot(window))
|
||||
{
|
||||
// child windows such as buttons, combo boxes, etc.
|
||||
return ProcessabilityType::NonRootWindow;
|
||||
}
|
||||
|
||||
bool isPopup = FancyZonesWindowUtils::HasStyle(style, WS_POPUP);
|
||||
bool hasThickFrame = FancyZonesWindowUtils::HasStyle(style, WS_THICKFRAME);
|
||||
bool hasCaption = FancyZonesWindowUtils::HasStyle(style, WS_CAPTION);
|
||||
bool hasMinimizeMaximizeButtons = FancyZonesWindowUtils::HasStyle(style, WS_MINIMIZEBOX) || FancyZonesWindowUtils::HasStyle(style, WS_MAXIMIZEBOX);
|
||||
if (isPopup && !(hasThickFrame && (hasCaption || hasMinimizeMaximizeButtons)))
|
||||
{
|
||||
// popup windows we want to snap: e.g. Calculator, Telegram
|
||||
// popup windows we don't want to snap: start menu, notification popup, tray window, etc.
|
||||
// WS_CAPTION, WS_MINIMIZEBOX, WS_MAXIMIZEBOX are used for filtering out menus,
|
||||
// e.g., in Edge "Running as admin" menu when creating a new PowerToys issue.
|
||||
return ProcessabilityType::NonProcessablePopupWindow;
|
||||
}
|
||||
|
||||
// allow child windows
|
||||
auto hasOwner = FancyZonesWindowUtils::HasVisibleOwner(window);
|
||||
if (hasOwner && !FancyZonesSettings::settings().allowSnapChildWindows)
|
||||
{
|
||||
return false;
|
||||
return ProcessabilityType::ChildWindow;
|
||||
}
|
||||
|
||||
if (FancyZonesWindowUtils::IsExcluded(window))
|
||||
{
|
||||
return false;
|
||||
return ProcessabilityType::Excluded;
|
||||
}
|
||||
|
||||
// Switch between virtual desktops results with posting same windows messages that also indicate
|
||||
// creation of new window. We need to check if window being processed is on currently active desktop.
|
||||
if (!VirtualDesktop::instance().IsWindowOnCurrentDesktop(window))
|
||||
{
|
||||
return false;
|
||||
return ProcessabilityType::NotCurrentVirtualDesktop;
|
||||
}
|
||||
|
||||
return true;
|
||||
return ProcessabilityType::Processable;
|
||||
}
|
||||
|
||||
bool FancyZonesWindowProcessing::IsProcessable(HWND window) noexcept
|
||||
{
|
||||
return DefineWindowType(window) == ProcessabilityType::Processable;
|
||||
}
|
||||
|
||||
@@ -2,5 +2,20 @@
|
||||
|
||||
namespace FancyZonesWindowProcessing
|
||||
{
|
||||
enum class ProcessabilityType
|
||||
{
|
||||
Processable = 0,
|
||||
SplashScreen,
|
||||
Minimized,
|
||||
ToolWindow,
|
||||
NotVisible,
|
||||
NonRootWindow,
|
||||
NonProcessablePopupWindow,
|
||||
ChildWindow,
|
||||
Excluded,
|
||||
NotCurrentVirtualDesktop
|
||||
};
|
||||
|
||||
ProcessabilityType DefineWindowType(HWND window) noexcept;
|
||||
bool IsProcessable(HWND window) noexcept;
|
||||
}
|
||||
@@ -360,7 +360,7 @@ namespace MonitorUtils
|
||||
if (GetMonitorInfo(monitor, &destMi))
|
||||
{
|
||||
RECT newPosition = FitOnScreen(placement.rcNormalPosition, originMi.rcWork, destMi.rcWork);
|
||||
FancyZonesWindowUtils::SizeWindowToRect(window, newPosition);
|
||||
FancyZonesWindowUtils::SizeWindowToRect(window, newPosition, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/notifications/notifications.h>
|
||||
#include <common/notifications/dont_show_again.h>
|
||||
#include <common/utils/resources.h>
|
||||
|
||||
namespace FancyZonesNotifications
|
||||
{
|
||||
// Non-Localizable strings
|
||||
namespace NonLocalizable
|
||||
{
|
||||
const wchar_t FancyZonesRunAsAdminInfoPage[] = L"https://aka.ms/powertoysDetectedElevatedHelp";
|
||||
const wchar_t ToastNotificationButtonUrl[] = L"powertoys://cant_drag_elevated_disable/";
|
||||
}
|
||||
|
||||
inline void WarnIfElevationIsRequired()
|
||||
{
|
||||
using namespace notifications;
|
||||
using namespace NonLocalizable;
|
||||
|
||||
static bool warning_shown = false;
|
||||
if (!warning_shown && !is_toast_disabled(CantDragElevatedDontShowAgainRegistryPath, CantDragElevatedDisableIntervalInDays))
|
||||
{
|
||||
std::vector<action_t> actions = {
|
||||
link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_LEARN_MORE), FancyZonesRunAsAdminInfoPage },
|
||||
link_button{ GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN), ToastNotificationButtonUrl }
|
||||
};
|
||||
show_toast_with_activations(GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED),
|
||||
GET_RESOURCE_STRING(IDS_FANCYZONES),
|
||||
{},
|
||||
std::move(actions));
|
||||
warning_shown = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -215,7 +215,7 @@
|
||||
</data>
|
||||
<data name="FancyZones" xml:space="preserve">
|
||||
<value>FancyZones</value>
|
||||
<comment>FancyZone is a product name, keep as is.</comment>
|
||||
<comment>FancyZones is a product name, keep as is.</comment>
|
||||
</data>
|
||||
<data name="Cant_Drag_Elevated" xml:space="preserve">
|
||||
<value>We've detected an application running with administrator privileges. This will prevent certain interactions with these applications.</value>
|
||||
@@ -243,19 +243,19 @@
|
||||
</data>
|
||||
<data name="FancyZones_Data_Error" xml:space="preserve">
|
||||
<value>FancyZones persisted data path not found. Please report the bug to</value>
|
||||
<comment>"Report bug to" will have a URL after. FancyZone is a product name, keep as is.</comment>
|
||||
<comment>"Report bug to" will have a URL after. FancyZones is a product name, keep as is.</comment>
|
||||
</data>
|
||||
<data name="FancyZones_Editor_Launch_Error" xml:space="preserve">
|
||||
<value>The FancyZones editor failed to start. Please report the bug to</value>
|
||||
<comment>"Report bug to" will have a URL after. FancyZone is a product name, keep as is.</comment>
|
||||
<comment>"Report bug to" will have a URL after. FancyZones is a product name, keep as is.</comment>
|
||||
</data>
|
||||
<data name="FancyZones_Settings_Load_Error" xml:space="preserve">
|
||||
<value>Failed to load the FancyZones settings. Default settings will be used.</value>
|
||||
<comment>FancyZone is a product name, keep as is.</comment>
|
||||
<comment>FancyZones is a product name, keep as is.</comment>
|
||||
</data>
|
||||
<data name="FancyZones_Settings_Save_Error" xml:space="preserve">
|
||||
<value>Failed to save the FancyZones settings. Please retry again later, if the problem persists report the bug to</value>
|
||||
<comment>"Report bug to" will have a URL after. FancyZone is a product name, keep as is.</comment>
|
||||
<comment>"Report bug to" will have a URL after. FancyZones is a product name, keep as is.</comment>
|
||||
</data>
|
||||
<data name="Setting_Description_QuickLayoutSwitch" xml:space="preserve">
|
||||
<value>Enable quick layout switch</value>
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace NonLocalizable
|
||||
const wchar_t ShowOnAllMonitorsID[] = L"fancyzones_show_on_all_monitors";
|
||||
const wchar_t SpanZonesAcrossMonitorsID[] = L"fancyzones_span_zones_across_monitors";
|
||||
const wchar_t MakeDraggedWindowTransparentID[] = L"fancyzones_makeDraggedWindowTransparent";
|
||||
const wchar_t AllowPopupWindowSnapID[] = L"fancyzones_allowPopupWindowSnap";
|
||||
const wchar_t AllowChildWindowSnapID[] = L"fancyzones_allowChildWindowSnap";
|
||||
const wchar_t DisableRoundCornersOnSnapping[] = L"fancyzones_disableRoundCornersOnSnap";
|
||||
|
||||
@@ -127,7 +126,6 @@ void FancyZonesSettings::LoadSettings()
|
||||
SetBoolFlag(values, NonLocalizable::WindowSwitchingToggleID, SettingId::WindowSwitching, m_settings.windowSwitching);
|
||||
SetBoolFlag(values, NonLocalizable::SystemThemeID, SettingId::SystemTheme, m_settings.systemTheme);
|
||||
SetBoolFlag(values, NonLocalizable::ShowZoneNumberID, SettingId::ShowZoneNumber, m_settings.showZoneNumber);
|
||||
SetBoolFlag(values, NonLocalizable::AllowPopupWindowSnapID, SettingId::AllowSnapPopupWindows, m_settings.allowSnapPopupWindows);
|
||||
SetBoolFlag(values, NonLocalizable::AllowChildWindowSnapID, SettingId::AllowSnapChildWindows, m_settings.allowSnapChildWindows);
|
||||
SetBoolFlag(values, NonLocalizable::DisableRoundCornersOnSnapping, SettingId::DisableRoundCornersOnSnapping, m_settings.disableRoundCorners);
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ struct Settings
|
||||
bool makeDraggedWindowTransparent = true;
|
||||
bool systemTheme = true;
|
||||
bool showZoneNumber = true;
|
||||
bool allowSnapPopupWindows = false;
|
||||
bool allowSnapChildWindows = false;
|
||||
bool disableRoundCorners = false;
|
||||
std::wstring zoneColor = L"#AACDFF";
|
||||
|
||||
@@ -32,7 +32,6 @@ enum class SettingId
|
||||
NextTabHotkey,
|
||||
PrevTabHotkey,
|
||||
ExcludedApps,
|
||||
AllowSnapPopupWindows,
|
||||
AllowSnapChildWindows,
|
||||
DisableRoundCornersOnSnapping,
|
||||
};
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <FancyZonesLib/FancyZonesData/AppZoneHistory.h>
|
||||
#include <FancyZonesLib/FancyZonesWindowProcessing.h>
|
||||
#include <FancyZonesLib/FancyZonesWindowProperties.h>
|
||||
#include <FancyZonesLib/NotificationUtil.h>
|
||||
#include <FancyZonesLib/Settings.h>
|
||||
#include <FancyZonesLib/WindowUtils.h>
|
||||
#include <FancyZonesLib/WorkArea.h>
|
||||
@@ -12,6 +11,7 @@
|
||||
#include <FancyZonesLib/trace.h>
|
||||
|
||||
#include <common/utils/elevation.h>
|
||||
#include <common/notifications/NotificationUtil.h>
|
||||
|
||||
WindowMouseSnap::WindowMouseSnap(HWND window, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& activeWorkAreas) :
|
||||
m_window(window),
|
||||
@@ -20,8 +20,6 @@ WindowMouseSnap::WindowMouseSnap(HWND window, const std::unordered_map<HMONITOR,
|
||||
m_snappingMode(false)
|
||||
{
|
||||
m_windowProperties.hasNoVisibleOwner = !FancyZonesWindowUtils::HasVisibleOwner(m_window);
|
||||
m_windowProperties.isStandardWindow = FancyZonesWindowUtils::IsStandardWindow(m_window) &&
|
||||
(!FancyZonesWindowUtils::IsPopupWindow(m_window) || FancyZonesSettings::settings().allowSnapPopupWindows);
|
||||
}
|
||||
|
||||
WindowMouseSnap::~WindowMouseSnap()
|
||||
@@ -31,16 +29,15 @@ WindowMouseSnap::~WindowMouseSnap()
|
||||
|
||||
std::unique_ptr<WindowMouseSnap> WindowMouseSnap::Create(HWND window, const std::unordered_map<HMONITOR, std::unique_ptr<WorkArea>>& activeWorkAreas)
|
||||
{
|
||||
if (!FancyZonesWindowProcessing::IsProcessable(window) ||
|
||||
FancyZonesWindowUtils::IsCursorTypeIndicatingSizeEvent())
|
||||
if (FancyZonesWindowUtils::IsCursorTypeIndicatingSizeEvent() || !FancyZonesWindowProcessing::IsProcessable(window))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!is_process_elevated() && FancyZonesWindowUtils::IsProcessOfWindowElevated(window))
|
||||
if (!is_process_elevated() && IsProcessOfWindowElevated(window))
|
||||
{
|
||||
// Notifies user if unable to drag elevated window
|
||||
FancyZonesNotifications::WarnIfElevationIsRequired();
|
||||
notifications::WarnIfElevationIsRequired(GET_RESOURCE_STRING(IDS_FANCYZONES), GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED), GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_LEARN_MORE), GET_RESOURCE_STRING(IDS_CANT_DRAG_ELEVATED_DIALOG_DONT_SHOW_AGAIN));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -111,13 +108,8 @@ void WindowMouseSnap::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, bo
|
||||
void WindowMouseSnap::MoveSizeEnd()
|
||||
{
|
||||
if (m_snappingMode)
|
||||
{
|
||||
const bool hasNoVisibleOwner = !FancyZonesWindowUtils::HasVisibleOwner(m_window);
|
||||
const bool isStandardWindow = FancyZonesWindowUtils::IsStandardWindow(m_window);
|
||||
|
||||
if ((isStandardWindow == false && hasNoVisibleOwner == true &&
|
||||
m_windowProperties.isStandardWindow == true && m_windowProperties.hasNoVisibleOwner == true) ||
|
||||
FancyZonesWindowUtils::IsWindowMaximized(m_window))
|
||||
{
|
||||
if (FancyZonesWindowUtils::IsWindowMaximized(m_window))
|
||||
{
|
||||
// Abort the zoning, this is a Chromium based tab that is merged back with an existing window
|
||||
// or if the window is maximized by Windows when the cursor hits the screen top border
|
||||
|
||||
@@ -24,8 +24,6 @@ private:
|
||||
|
||||
struct WindowProperties
|
||||
{
|
||||
// True if from the styles the window looks like a standard window
|
||||
bool isStandardWindow = false;
|
||||
// True if the window is a top-level window that does not have a visible owner
|
||||
bool hasNoVisibleOwner = false;
|
||||
// Properties to restore after dragging
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace NonLocalizable
|
||||
{
|
||||
const wchar_t PowerToysAppFZEditor[] = L"POWERTOYS.FANCYZONESEDITOR.EXE";
|
||||
const wchar_t SplashClassName[] = L"MsoSplash";
|
||||
const char SplashClassName[] = "MsoSplash";
|
||||
const wchar_t CoreWindow[] = L"Windows.UI.Core.CoreWindow";
|
||||
const wchar_t SearchUI[] = L"SearchUI.exe";
|
||||
const wchar_t SystemAppsFolder[] = L"SYSTEMAPPS";
|
||||
@@ -122,17 +122,6 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsSplashScreen(HWND window)
|
||||
{
|
||||
wchar_t className[MAX_PATH];
|
||||
if (GetClassName(window, className, MAX_PATH) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return wcscmp(NonLocalizable::SplashClassName, className) == 0;
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsWindowMaximized(HWND window) noexcept
|
||||
{
|
||||
WINDOWPLACEMENT placement{};
|
||||
@@ -164,71 +153,9 @@ bool FancyZonesWindowUtils::HasVisibleOwner(HWND window) noexcept
|
||||
return rect.top != rect.bottom && rect.left != rect.right;
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsStandardWindow(HWND window)
|
||||
bool FancyZonesWindowUtils::IsRoot(HWND window) noexcept
|
||||
{
|
||||
// True if from the styles the window looks like a standard window
|
||||
|
||||
if (GetAncestor(window, GA_ROOT) != window)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto style = GetWindowLong(window, GWL_STYLE);
|
||||
auto exStyle = GetWindowLong(window, GWL_EXSTYLE);
|
||||
|
||||
bool isToolWindow = (exStyle & WS_EX_TOOLWINDOW) == WS_EX_TOOLWINDOW;
|
||||
bool isVisible = (style & WS_VISIBLE) == WS_VISIBLE;
|
||||
if (isToolWindow || !isVisible)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsPopupWindow(HWND window) noexcept
|
||||
{
|
||||
auto style = GetWindowLong(window, GWL_STYLE);
|
||||
return ((style & WS_POPUP) == WS_POPUP);
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::HasThickFrame(HWND window) noexcept
|
||||
{
|
||||
auto style = GetWindowLong(window, GWL_STYLE);
|
||||
return ((style & WS_THICKFRAME) == WS_THICKFRAME);
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::HasThickFrameAndMinimizeMaximizeButtons(HWND window) noexcept
|
||||
{
|
||||
auto style = GetWindowLong(window, GWL_STYLE);
|
||||
return ((style & WS_THICKFRAME) == WS_THICKFRAME && (style & WS_MINIMIZEBOX) == WS_MINIMIZEBOX && (style & WS_MAXIMIZEBOX) == WS_MAXIMIZEBOX);
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsProcessOfWindowElevated(HWND window)
|
||||
{
|
||||
DWORD pid = 0;
|
||||
GetWindowThreadProcessId(window, &pid);
|
||||
if (!pid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
wil::unique_handle hProcess{ OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
|
||||
FALSE,
|
||||
pid) };
|
||||
|
||||
wil::unique_handle token;
|
||||
|
||||
if (OpenProcessToken(hProcess.get(), TOKEN_QUERY, &token))
|
||||
{
|
||||
TOKEN_ELEVATION elevation;
|
||||
DWORD size;
|
||||
if (GetTokenInformation(token.get(), TokenElevation, &elevation, sizeof(elevation), &size))
|
||||
{
|
||||
return elevation.TokenIsElevated != 0;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return GetAncestor(window, GA_ROOT) == window;
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsExcluded(HWND window)
|
||||
@@ -248,12 +175,12 @@ bool FancyZonesWindowUtils::IsExcluded(HWND window)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsExcludedByUser(const HWND& hwnd, std::wstring& processPath) noexcept
|
||||
bool FancyZonesWindowUtils::IsExcludedByUser(const HWND& hwnd, const std::wstring& processPath) noexcept
|
||||
{
|
||||
return (check_excluded_app(hwnd, processPath, FancyZonesSettings::settings().excludedAppsArray));
|
||||
}
|
||||
|
||||
bool FancyZonesWindowUtils::IsExcludedByDefault(const HWND& hwnd, std::wstring& processPath) noexcept
|
||||
bool FancyZonesWindowUtils::IsExcludedByDefault(const HWND& hwnd, const std::wstring& processPath) noexcept
|
||||
{
|
||||
static std::vector<std::wstring> defaultExcludedFolders = { NonLocalizable::SystemAppsFolder };
|
||||
if (find_folder_in_path(processPath, defaultExcludedFolders))
|
||||
@@ -261,9 +188,14 @@ bool FancyZonesWindowUtils::IsExcludedByDefault(const HWND& hwnd, std::wstring&
|
||||
return true;
|
||||
}
|
||||
|
||||
std::array<char, 256> class_name;
|
||||
GetClassNameA(hwnd, class_name.data(), static_cast<int>(class_name.size()));
|
||||
if (is_system_window(hwnd, class_name.data()))
|
||||
std::array<char, 256> className;
|
||||
GetClassNameA(hwnd, className.data(), static_cast<int>(className.size()));
|
||||
if (is_system_window(hwnd, className.data()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(NonLocalizable::SplashClassName, className.data()) == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -294,7 +226,7 @@ void FancyZonesWindowUtils::SwitchToWindow(HWND window) noexcept
|
||||
}
|
||||
}
|
||||
|
||||
void FancyZonesWindowUtils::SizeWindowToRect(HWND window, RECT rect) noexcept
|
||||
void FancyZonesWindowUtils::SizeWindowToRect(HWND window, RECT rect, BOOL snapZone) noexcept
|
||||
{
|
||||
WINDOWPLACEMENT placement{};
|
||||
::GetWindowPlacement(window, &placement);
|
||||
@@ -306,8 +238,15 @@ void FancyZonesWindowUtils::SizeWindowToRect(HWND window, RECT rect) noexcept
|
||||
::GetWindowPlacement(window, &placement);
|
||||
}
|
||||
|
||||
BOOL maximizeLater = false;
|
||||
if (IsWindowVisible(window))
|
||||
{
|
||||
// If is not snap zone then need keep maximize state (move to active monitor)
|
||||
if (!snapZone && placement.showCmd == SW_SHOWMAXIMIZED)
|
||||
{
|
||||
maximizeLater = true;
|
||||
}
|
||||
|
||||
// Do not restore minimized windows. We change their placement though so they restore to the correct zone.
|
||||
if ((placement.showCmd != SW_SHOWMINIMIZED) &&
|
||||
(placement.showCmd != SW_MINIMIZE))
|
||||
@@ -335,6 +274,12 @@ void FancyZonesWindowUtils::SizeWindowToRect(HWND window, RECT rect) noexcept
|
||||
Logger::error(L"SetWindowPlacement failed, {}", get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
|
||||
// make sure window is moved to the correct monitor before maximize.
|
||||
if (maximizeLater)
|
||||
{
|
||||
placement.showCmd = SW_SHOWMAXIMIZED;
|
||||
}
|
||||
|
||||
// Do it again, allowing Windows to resize the window and set correct scaling
|
||||
// This fixes Issue #365
|
||||
result = ::SetWindowPlacement(window, &placement);
|
||||
|
||||
@@ -15,21 +15,23 @@
|
||||
|
||||
namespace FancyZonesWindowUtils
|
||||
{
|
||||
bool IsSplashScreen(HWND window);
|
||||
bool IsWindowMaximized(HWND window) noexcept;
|
||||
bool HasVisibleOwner(HWND window) noexcept;
|
||||
bool IsStandardWindow(HWND window);
|
||||
bool IsPopupWindow(HWND window) noexcept;
|
||||
bool HasThickFrame(HWND window) noexcept;
|
||||
bool HasThickFrameAndMinimizeMaximizeButtons(HWND window) noexcept;
|
||||
bool IsRoot(HWND window) noexcept;
|
||||
|
||||
constexpr bool HasStyle(LONG style, LONG styleToCheck) noexcept
|
||||
{
|
||||
return ((style & styleToCheck) == styleToCheck);
|
||||
}
|
||||
|
||||
bool IsProcessOfWindowElevated(HWND window); // If HWND is already dead, we assume it wasn't elevated
|
||||
|
||||
bool IsExcluded(HWND window);
|
||||
bool IsExcludedByUser(const HWND& hwnd, std::wstring& processPath) noexcept;
|
||||
bool IsExcludedByDefault(const HWND& hwnd, std::wstring& processPath) noexcept;
|
||||
bool IsExcludedByUser(const HWND& hwnd, const std::wstring& processPath) noexcept;
|
||||
bool IsExcludedByDefault(const HWND& hwnd, const std::wstring& processPath) noexcept;
|
||||
|
||||
void SwitchToWindow(HWND window) noexcept;
|
||||
void SizeWindowToRect(HWND window, RECT rect) noexcept; // Parameter rect must be in screen coordinates (e.g. obtained from GetWindowRect)
|
||||
void SizeWindowToRect(HWND window, RECT rect, BOOL snapZone = true) noexcept; // Parameter rect must be in screen coordinates (e.g. obtained from GetWindowRect)
|
||||
void SaveWindowSizeAndOrigin(HWND window) noexcept;
|
||||
void RestoreWindowSize(HWND window) noexcept;
|
||||
void RestoreWindowOrigin(HWND window) noexcept;
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
#define SpanZonesAcrossMonitorsKey "SpanZonesAcrossMonitors"
|
||||
#define MakeDraggedWindowTransparentKey "MakeDraggedWindowTransparent"
|
||||
#define AllowSnapChildWindows "AllowSnapChildWindows"
|
||||
#define AllowSnapPopupWindows "AllowSnapPopupWindows"
|
||||
#define DisableRoundCornersOnSnapping "DisableRoundCornersOnSnapping"
|
||||
#define ZoneColorKey "ZoneColor"
|
||||
#define ZoneBorderColorKey "ZoneBorderColor"
|
||||
@@ -323,7 +322,6 @@ void Trace::SettingsTelemetry(const Settings& settings) noexcept
|
||||
TraceLoggingBoolean(settings.spanZonesAcrossMonitors, SpanZonesAcrossMonitorsKey),
|
||||
TraceLoggingBoolean(settings.makeDraggedWindowTransparent, MakeDraggedWindowTransparentKey),
|
||||
TraceLoggingBoolean(settings.allowSnapChildWindows, AllowSnapChildWindows),
|
||||
TraceLoggingBoolean(settings.allowSnapPopupWindows, AllowSnapPopupWindows),
|
||||
TraceLoggingBoolean(settings.disableRoundCorners, DisableRoundCornersOnSnapping),
|
||||
TraceLoggingWideString(settings.zoneColor.c_str(), ZoneColorKey),
|
||||
TraceLoggingWideString(settings.zoneBorderColor.c_str(), ZoneBorderColorKey),
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
<ClCompile Include="Util.Spec.cpp" />
|
||||
<ClCompile Include="Util.cpp" />
|
||||
<ClCompile Include="WindowKeyboardSnap.Spec.cpp" />
|
||||
<ClCompile Include="WindowProcessingTests.Spec.cpp" />
|
||||
<ClCompile Include="WorkArea.Spec.cpp" />
|
||||
<ClCompile Include="WorkAreaIdTests.Spec.cpp" />
|
||||
<ClCompile Include="Zone.Spec.cpp" />
|
||||
|
||||
@@ -66,6 +66,9 @@
|
||||
<ClCompile Include="WindowKeyboardSnap.Spec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WindowProcessingTests.Spec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
|
||||
@@ -8,8 +8,7 @@ namespace Mocks
|
||||
class HwndCreator
|
||||
{
|
||||
public:
|
||||
HwndCreator(const std::wstring& title = L"");
|
||||
|
||||
HwndCreator(const std::wstring& title, const std::wstring& className, DWORD exStyle, DWORD style, HWND parentWindow);
|
||||
~HwndCreator();
|
||||
|
||||
HWND operator()(HINSTANCE hInst);
|
||||
@@ -20,23 +19,30 @@ namespace Mocks
|
||||
inline HINSTANCE getHInstance() const { return m_hInst; }
|
||||
inline const std::wstring& getTitle() const { return m_windowTitle; }
|
||||
inline const std::wstring& getWindowClassName() const { return m_windowClassName; }
|
||||
inline DWORD getExStyle() const noexcept { return m_exStyle; }
|
||||
inline DWORD getStyle() const noexcept { return m_style; }
|
||||
inline HWND getParentWindow() const noexcept { return m_parentWindow; }
|
||||
|
||||
private:
|
||||
std::wstring m_windowTitle;
|
||||
std::wstring m_windowClassName;
|
||||
DWORD m_exStyle{ 0 };
|
||||
DWORD m_style{ 0 };
|
||||
HWND m_parentWindow{ NULL };
|
||||
|
||||
std::mutex m_mutex;
|
||||
std::condition_variable m_conditionVar;
|
||||
bool m_conditionFlag;
|
||||
HANDLE m_thread;
|
||||
|
||||
HINSTANCE m_hInst;
|
||||
HINSTANCE m_hInst{};
|
||||
HWND m_hWnd;
|
||||
};
|
||||
|
||||
HWND WindowCreate(HINSTANCE hInst)
|
||||
HWND WindowCreate(HINSTANCE hInst, const std::wstring& title /*= L""*/, const std::wstring& className /*= L""*/,
|
||||
DWORD exStyle, DWORD style, HWND parentWindow)
|
||||
{
|
||||
return HwndCreator()(hInst);
|
||||
return HwndCreator(title, className, exStyle, style, parentWindow)(hInst);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,8 +91,21 @@ DWORD WINAPI ThreadProc(LPVOID lpParam)
|
||||
|
||||
if (RegisterDLLWindowClass(creator->getWindowClassName().c_str(), creator) != 0)
|
||||
{
|
||||
auto hWnd = CreateWindowEx(0, creator->getWindowClassName().c_str(), creator->getTitle().c_str(), WS_EX_APPWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 10, 10, nullptr, nullptr, creator->getHInstance(), NULL);
|
||||
SetWindowPos(hWnd, HWND_TOPMOST, 10, 10, 100, 100, SWP_SHOWWINDOW);
|
||||
auto hWnd = CreateWindowEx(creator->getExStyle(),
|
||||
creator->getWindowClassName().c_str(),
|
||||
creator->getTitle().c_str(),
|
||||
creator->getStyle(),
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
creator->getParentWindow(),
|
||||
nullptr,
|
||||
creator->getHInstance(),
|
||||
NULL);
|
||||
|
||||
ShowWindow(hWnd, SW_SHOW);
|
||||
// wait after ShowWindow to make sure that it's finished and shown
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
creator->setHwnd(hWnd);
|
||||
creator->setCondition(true);
|
||||
|
||||
@@ -95,8 +114,6 @@ DWORD WINAPI ThreadProc(LPVOID lpParam)
|
||||
TranslateMessage(&messages);
|
||||
DispatchMessage(&messages);
|
||||
}
|
||||
|
||||
creator->setHwnd(hWnd);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -108,8 +125,16 @@ DWORD WINAPI ThreadProc(LPVOID lpParam)
|
||||
|
||||
namespace Mocks
|
||||
{
|
||||
HwndCreator::HwndCreator(const std::wstring& title) :
|
||||
m_windowTitle(title), m_windowClassName(std::to_wstring(++s_classId)), m_conditionFlag(false), m_thread(nullptr), m_hInst(HINSTANCE{}), m_hWnd(nullptr)
|
||||
HwndCreator::HwndCreator(const std::wstring& title, const std::wstring& className, DWORD exStyle, DWORD style, HWND parentWindow) :
|
||||
m_windowTitle(title),
|
||||
m_windowClassName(className.empty() ? std::to_wstring(++s_classId) : className),
|
||||
m_exStyle(exStyle),
|
||||
m_style(style),
|
||||
m_parentWindow(parentWindow),
|
||||
m_conditionFlag(false),
|
||||
m_thread(nullptr),
|
||||
m_hInst(HINSTANCE{}),
|
||||
m_hWnd(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,8 @@ namespace Mocks
|
||||
return reinterpret_cast<HINSTANCE>(++s_nextInstance);
|
||||
}
|
||||
|
||||
HWND WindowCreate(HINSTANCE hInst);
|
||||
HWND WindowCreate(HINSTANCE hInst, const std::wstring& title = L"", const std::wstring& className = L""
|
||||
, DWORD exStyle = 0, DWORD style = 0, HWND parentWindow = nullptr);
|
||||
}
|
||||
|
||||
namespace Helpers
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include <FancyZonesLib/FancyZonesWindowProcessing.h>
|
||||
#include <FancyZonesLib/Settings.h>
|
||||
#include <FancyZonesLib/WindowUtils.h>
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
#include <CppUnitTestLogger.h>
|
||||
|
||||
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||||
|
||||
namespace Microsoft
|
||||
{
|
||||
namespace VisualStudio
|
||||
{
|
||||
namespace CppUnitTestFramework
|
||||
{
|
||||
template<>
|
||||
std::wstring ToString<FancyZonesWindowProcessing::ProcessabilityType>(const FancyZonesWindowProcessing::ProcessabilityType& type)
|
||||
{
|
||||
return std::to_wstring((int)type);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace FancyZonesUnitTests
|
||||
{
|
||||
TEST_CLASS (WindowProcessingUnitTests)
|
||||
{
|
||||
HINSTANCE hInst{};
|
||||
|
||||
TEST_METHOD_CLEANUP(CleanUp)
|
||||
{
|
||||
FancyZonesSettings::instance().SetSettings(Settings{});
|
||||
}
|
||||
|
||||
TEST_METHOD (MinimizedWindow)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst);
|
||||
ShowWindow(window, SW_MINIMIZE);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // let ShowWindow finish
|
||||
Assert::IsTrue(IsIconic(window));
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Minimized, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (ToolWindow)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", WS_EX_TOOLWINDOW);
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::ToolWindow, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (InvisibleWindow)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst);
|
||||
ShowWindow(window, SW_HIDE);
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // let ShowWindow finish
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::NotVisible, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD(NonRootWindow)
|
||||
{
|
||||
HWND rootWindow = Mocks::WindowCreate(hInst, L"RootWindow", L"", 0, WS_TILEDWINDOW | WS_CLIPCHILDREN);
|
||||
Assert::IsTrue(FancyZonesWindowUtils::IsRoot(rootWindow));
|
||||
|
||||
HWND window = CreateWindow(WC_COMBOBOX, TEXT(""), CBS_DROPDOWN | CBS_HASSTRINGS | WS_CHILD | WS_OVERLAPPED | WS_VISIBLE, 0, 0, 10, 10, rootWindow, NULL, hInst, NULL);
|
||||
Assert::IsFalse(FancyZonesWindowUtils::IsRoot(window));
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::NonRootWindow, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (Popup_App)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", 0, WS_TILEDWINDOW | WS_POPUP);
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Processable, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsTrue(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (Popup_Menu)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", 0, WS_POPUP | WS_TILED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::NonProcessablePopupWindow, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (Popup_MenuEdge)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", 0, WS_POPUP | WS_TILED | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_THICKFRAME | WS_SIZEBOX);
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::NonProcessablePopupWindow, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (Popup_Calculator)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", 0, WS_BORDER | WS_CLIPSIBLINGS | WS_DLGFRAME | WS_GROUP | WS_POPUP | WS_POPUPWINDOW | WS_SIZEBOX | WS_TABSTOP | WS_TILEDWINDOW);
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Processable, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsTrue(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (Popup_CalculatorTopmost)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", 0, WS_BORDER | WS_CAPTION | WS_CLIPSIBLINGS | WS_DLGFRAME | WS_OVERLAPPED | WS_POPUP | WS_POPUPWINDOW | WS_SIZEBOX | WS_SYSMENU | WS_THICKFRAME);
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Processable, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsTrue(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD(Popup_FacebookMessenger)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", 0, WS_GROUP | WS_MAXIMIZEBOX | WS_MINIMIZEBOX | WS_POPUP | WS_TABSTOP | WS_THICKFRAME);
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Processable, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsTrue(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (ChildWindow_OptionDisabled)
|
||||
{
|
||||
FancyZonesSettings::instance().SetSettings(Settings{ .allowSnapChildWindows = false });
|
||||
HWND parentWindow = Mocks::WindowCreate(hInst, L"", L"", 0, WS_TILEDWINDOW);
|
||||
if (!IsWindowVisible(parentWindow))
|
||||
{
|
||||
// skip the test if the parent window isn't visible.
|
||||
// test can run locally, but will fail in CI because of the configuration
|
||||
return;
|
||||
}
|
||||
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", 0, 0, parentWindow);
|
||||
Assert::IsTrue(IsWindowVisible(window), L"Child window not visible");
|
||||
Assert::IsTrue(FancyZonesWindowUtils::HasVisibleOwner(window), L"Child window doesn't have visible owner");
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::ChildWindow, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (ChildWindow_OptionEnabled)
|
||||
{
|
||||
FancyZonesSettings::instance().SetSettings(Settings{ .allowSnapChildWindows = true });
|
||||
HWND parentWindow = Mocks::WindowCreate(hInst, L"", L"", 0, WS_TILEDWINDOW);
|
||||
if (!IsWindowVisible(parentWindow))
|
||||
{
|
||||
// skip the test if the parent window isn't visible.
|
||||
// test can run locally, but will fail in CI because of the configuration
|
||||
return;
|
||||
}
|
||||
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", 0, 0, parentWindow);
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Processable, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsTrue(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (ExcludedApp_ByDefault)
|
||||
{
|
||||
// set class from the excluded list
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"SysListView32");
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Excluded, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (ExcludedApp_ByDefault_SplashScreen)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"MsoSplash");
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Excluded, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (ExcludedApp_ByUser)
|
||||
{
|
||||
// case sensitive, should be uppercase
|
||||
FancyZonesSettings::instance().SetSettings(Settings{ .excludedAppsArray = { L"TEST_EXCLUDED" } });
|
||||
|
||||
// exclude by window title
|
||||
HWND window = Mocks::WindowCreate(hInst, L"Test_Excluded");
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Excluded, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsFalse(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
|
||||
TEST_METHOD (ProcessableWindow)
|
||||
{
|
||||
HWND window = Mocks::WindowCreate(hInst, L"", L"", 0, WS_TILEDWINDOW);
|
||||
|
||||
Assert::AreEqual(FancyZonesWindowProcessing::ProcessabilityType::Processable, FancyZonesWindowProcessing::DefineWindowType(window));
|
||||
Assert::IsTrue(FancyZonesWindowProcessing::IsProcessable(window));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -249,7 +249,7 @@ namespace FancyZonesUnitTests
|
||||
AppliedLayouts::instance().ApplyLayout(m_workAreaId, layout);
|
||||
|
||||
const auto workArea = WorkArea::Create(m_hInst, m_workAreaId, m_parentUniqueId, m_workAreaRect);
|
||||
const auto window = Mocks::WindowCreate(m_hInst);
|
||||
const auto window = Mocks::WindowCreate(m_hInst, L"", L"", 0, WS_THICKFRAME);
|
||||
|
||||
SetWindowPos(window, nullptr, 150, 150, 450, 550, SWP_SHOWWINDOW);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net7.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetFramework>net8.0-windows10.0.20348.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
|
||||
@@ -74,8 +74,8 @@
|
||||
TabIndex="2" />
|
||||
<Button
|
||||
HorizontalAlignment="Stretch"
|
||||
Click="OnSaveApplyTemplate"
|
||||
Content="{x:Static props:Resources.Save_Apply}"
|
||||
Click="OnSave"
|
||||
Content="{x:Static props:Resources.Save}"
|
||||
Style="{StaticResource AccentButtonStyle}"
|
||||
TabIndex="1" />
|
||||
</Grid>
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace FancyZonesEditor
|
||||
private SnappyHelperBase snappyX;
|
||||
private SnappyHelperBase snappyY;
|
||||
|
||||
private SnappyHelperBase NewMagneticSnapper(bool isX, ResizeMode mode)
|
||||
private SnappyHelperMagnetic NewMagneticSnapper(bool isX, ResizeMode mode)
|
||||
{
|
||||
Rect workingArea = App.Overlay.WorkArea;
|
||||
int screenAxisOrigin = (int)(isX ? workingArea.Left : workingArea.Top);
|
||||
@@ -245,7 +245,7 @@ namespace FancyZonesEditor
|
||||
return new SnappyHelperMagnetic(Model.Zones, ZoneIndex, isX, mode, screenAxisOrigin, screenAxisSize);
|
||||
}
|
||||
|
||||
private SnappyHelperBase NewNonMagneticSnapper(bool isX, ResizeMode mode)
|
||||
private SnappyHelperNonMagnetic NewNonMagneticSnapper(bool isX, ResizeMode mode)
|
||||
{
|
||||
Rect workingArea = App.Overlay.WorkArea;
|
||||
int screenAxisOrigin = (int)(isX ? workingArea.Left : workingArea.Top);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using System.Windows.Automation.Peers;
|
||||
using System.Windows.Controls;
|
||||
|
||||
@@ -10,6 +11,8 @@ namespace FancyZonesEditor.Controls
|
||||
{
|
||||
internal sealed class CustomSliderAutomationPeer : SliderAutomationPeer
|
||||
{
|
||||
private static readonly CompositeFormat CustomSliderAnnounce = System.Text.CompositeFormat.Parse(Properties.Resources.Custom_slider_announce);
|
||||
|
||||
private string name = string.Empty;
|
||||
|
||||
public CustomSliderAutomationPeer(Slider owner)
|
||||
@@ -29,7 +32,7 @@ namespace FancyZonesEditor.Controls
|
||||
|
||||
string announce = string.Format(
|
||||
CultureInfo.CurrentCulture,
|
||||
Properties.Resources.Custom_slider_announce,
|
||||
CustomSliderAnnounce,
|
||||
name,
|
||||
element.Minimum,
|
||||
element.Maximum,
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace FancyZonesEditor
|
||||
EditingLayout = editingLayout;
|
||||
}
|
||||
|
||||
protected void OnSaveApplyTemplate(object sender, RoutedEventArgs e)
|
||||
protected void OnSave(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Logger.LogTrace();
|
||||
|
||||
@@ -31,15 +31,8 @@ namespace FancyZonesEditor
|
||||
|
||||
EditingLayout.Persist();
|
||||
|
||||
MainWindowSettingsModel settings = ((App)Application.Current).MainWindowSettings;
|
||||
settings.SetAppliedModel(EditingLayout);
|
||||
App.Overlay.Monitors[App.Overlay.CurrentDesktop].SetLayoutSettings(EditingLayout);
|
||||
|
||||
App.FancyZonesEditorIO.SerializeLayoutTemplates();
|
||||
App.FancyZonesEditorIO.SerializeCustomLayouts();
|
||||
App.FancyZonesEditorIO.SerializeAppliedLayouts();
|
||||
App.FancyZonesEditorIO.SerializeDefaultLayouts();
|
||||
App.FancyZonesEditorIO.SerializeLayoutHotkeys();
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user