mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-30 00:46:20 +01:00
Compare commits
40 Commits
leilzh/rep
...
leilzh/tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c79f3b4c39 | ||
|
|
c487638758 | ||
|
|
252dbb5853 | ||
|
|
655398e173 | ||
|
|
f7257bf1d1 | ||
|
|
4f209235af | ||
|
|
bdedc02ea5 | ||
|
|
b2d7182dcd | ||
|
|
82e9d42e02 | ||
|
|
012fd0eb8b | ||
|
|
041cdc57dc | ||
|
|
3bf0c04ad5 | ||
|
|
74d92df078 | ||
|
|
c2975dfe55 | ||
|
|
2255106a78 | ||
|
|
e53961c30b | ||
|
|
2ade73834d | ||
|
|
ecfc9e9ab2 | ||
|
|
3afaa18343 | ||
|
|
821f0b7aa7 | ||
|
|
fa111538ae | ||
|
|
be68bfd3ab | ||
|
|
790676844d | ||
|
|
64ad9b56ad | ||
|
|
512f55a481 | ||
|
|
7d257cf00c | ||
|
|
c5c64767c1 | ||
|
|
a40b7d23ff | ||
|
|
b539c75240 | ||
|
|
106923db84 | ||
|
|
6f68f5f34a | ||
|
|
aa8cfd505a | ||
|
|
349de60e47 | ||
|
|
abc5c3e249 | ||
|
|
ce058f1dc7 | ||
|
|
2d1676b7df | ||
|
|
d168ae5b9b | ||
|
|
1870fc31ee | ||
|
|
54f7e1e123 | ||
|
|
39fa4c37d3 |
3
.github/actions/spell-check/allow/names.txt
vendored
3
.github/actions/spell-check/allow/names.txt
vendored
@@ -91,6 +91,7 @@ Hemmerlein
|
||||
hlaueriksson
|
||||
Horvalds
|
||||
Howett
|
||||
hotkidfamily
|
||||
htcfreek
|
||||
Huynh
|
||||
Ionut
|
||||
@@ -98,6 +99,7 @@ jamrobot
|
||||
Jaswal
|
||||
Jaylyn
|
||||
jefflord
|
||||
Jeremic
|
||||
Jordi
|
||||
jyuwono
|
||||
kai
|
||||
@@ -222,6 +224,7 @@ openai
|
||||
Quickime
|
||||
regedit
|
||||
roslyn
|
||||
Skia
|
||||
Spotify
|
||||
Vanara
|
||||
wangyi
|
||||
|
||||
1
.github/actions/spell-check/excludes.txt
vendored
1
.github/actions/spell-check/excludes.txt
vendored
@@ -126,3 +126,4 @@
|
||||
^src/common/sysinternals/Eula/
|
||||
^tools/Verification scripts/Check preview handler registration\.ps1$
|
||||
ignore$
|
||||
^src/modules/registrypreview/RegistryPreviewUILib/Controls/HexBox/.*$
|
||||
|
||||
9
.github/actions/spell-check/expect.txt
vendored
9
.github/actions/spell-check/expect.txt
vendored
@@ -156,6 +156,7 @@ builttoroam
|
||||
BVal
|
||||
BValue
|
||||
byapp
|
||||
BYCOMMAND
|
||||
BYPOSITION
|
||||
CALCRECT
|
||||
CALG
|
||||
@@ -202,6 +203,7 @@ CLIPSIBLINGS
|
||||
closesocket
|
||||
clp
|
||||
CLSCTX
|
||||
CLSCTXLOCALSERVER
|
||||
clsids
|
||||
Clusion
|
||||
cmder
|
||||
@@ -815,6 +817,7 @@ LOCALDISPLAY
|
||||
localpackage
|
||||
LOCALSYSTEM
|
||||
LOCATIONCHANGE
|
||||
LOCKTYPE
|
||||
LOGFONT
|
||||
LOGFONTW
|
||||
logon
|
||||
@@ -910,6 +913,7 @@ metafile
|
||||
mfc
|
||||
Mgmt
|
||||
Microwaved
|
||||
middleclickaction
|
||||
midl
|
||||
mii
|
||||
mindaro
|
||||
@@ -1251,6 +1255,7 @@ prg
|
||||
prgh
|
||||
prgms
|
||||
pri
|
||||
primaryclickaction
|
||||
PRINTCLIENT
|
||||
printmanagement
|
||||
prm
|
||||
@@ -1426,6 +1431,7 @@ SDKDDK
|
||||
sdns
|
||||
searchterm
|
||||
SEARCHUI
|
||||
secondaryclickaction
|
||||
SECONDARYDISPLAY
|
||||
secpol
|
||||
securestring
|
||||
@@ -1510,6 +1516,7 @@ SICHINT
|
||||
SIDs
|
||||
siex
|
||||
sigdn
|
||||
Signedness
|
||||
SIGNINGSCENARIO
|
||||
signtool
|
||||
SINGLEKEY
|
||||
@@ -1659,6 +1666,7 @@ TDefault
|
||||
TDevice
|
||||
telephon
|
||||
templatenamespace
|
||||
TESTONLY
|
||||
testprocess
|
||||
TEXCOORD
|
||||
TEXTBOXNEWLINE
|
||||
@@ -1711,6 +1719,7 @@ trx
|
||||
tsa
|
||||
TSender
|
||||
TServer
|
||||
tskill
|
||||
tstoi
|
||||
TStr
|
||||
tweakme
|
||||
|
||||
@@ -41,6 +41,9 @@ Write-Output ""
|
||||
Write-Output "Restoring dotnet tools..."
|
||||
dotnet tool restore --disable-parallel --no-cache
|
||||
|
||||
# Use Regex syntax
|
||||
$PathExcludes = "(\\obj\\)|(\\bin\\)|(\\x64\\)|(\\Generated Files\\PowerRenameXAML\\)|(\\RegistryPreviewUILib\\Controls\\HexBox\\)"
|
||||
|
||||
if (-not $Passive)
|
||||
{
|
||||
# Look for unstaged changed files by default
|
||||
@@ -87,7 +90,7 @@ if (-not $Passive)
|
||||
}
|
||||
|
||||
Write-Output "Running Git Diff: $gitDiffCommand"
|
||||
$files = Invoke-Expression $gitDiffCommand | Select-String -Pattern "\.xaml$"
|
||||
$files = Invoke-Expression $gitDiffCommand | Select-String -Pattern "\.xaml$" | Where-Object { $_ -notmatch $PathExcludes }
|
||||
|
||||
if (-not $Passive -and -not $Main -and -not $Unstaged -and -not $Staged -and -not $LastCommit)
|
||||
{
|
||||
@@ -107,7 +110,7 @@ if (-not $Passive)
|
||||
else
|
||||
{
|
||||
Write-Output "Checking all files (passively)"
|
||||
$files = Get-ChildItem -Path "$PSScriptRoot\..\src\*.xaml" -Recurse | Select-Object -ExpandProperty FullName | Where-Object { $_ -notmatch "(\\obj\\)|(\\bin\\)|(\\x64\\)|(\\Generated Files\\PowerRenameXAML\\)" }
|
||||
$files = Get-ChildItem -Path "$PSScriptRoot\..\src\*.xaml" -Recurse | Select-Object -ExpandProperty FullName | Where-Object { $_ -notmatch $PathExcludes }
|
||||
|
||||
if ($files.count -gt 0)
|
||||
{
|
||||
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
${{ else }}:
|
||||
OutputBuildPlatform: ${{ platform }}
|
||||
variables:
|
||||
MakeAppxPath: 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x86\MakeAppx.exe'
|
||||
MakeAppxPath: 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x86\MakeAppx.exe'
|
||||
# Azure DevOps abhors a vacuum
|
||||
# If these are blank, expansion will fail later on... which will result in direct substitution of the variable *names*
|
||||
# later on. We'll just... set them to a single space and if we need to, check IsNullOrWhiteSpace.
|
||||
@@ -332,6 +332,7 @@ jobs:
|
||||
/p:VCRTForwarders-IncludeDebugCRT=false
|
||||
/p:PowerToysRoot=$(Build.SourcesDirectory)
|
||||
/p:PublishProfile=InstallationPublishProfile.pubxml
|
||||
/p:TargetFramework=net9.0-windows10.0.26100.0
|
||||
/bl:$(LogOutputDirectory)\publish-${{ join('_',split(project, '/')) }}.binlog
|
||||
$(RestoreAdditionalProjectSourcesArg)
|
||||
platform: $(BuildPlatform)
|
||||
@@ -394,10 +395,7 @@ jobs:
|
||||
testAssemblyVer2: |
|
||||
**\KeyboardManagerEngineTest.dll
|
||||
**\KeyboardManagerEditorTest.dll
|
||||
**\UnitTests-CommonLib.dll
|
||||
**\PowerRenameUnitTests.dll
|
||||
**\UnitTests-FancyZones.dll
|
||||
**\\WorkspacesLibUnitTests.dll
|
||||
**\*UnitTest*.dll
|
||||
!**\obj\**
|
||||
|
||||
- pwsh: |-
|
||||
|
||||
@@ -28,6 +28,8 @@ $versionExceptions = @(
|
||||
"ObjectModelCsProjection.dll",
|
||||
"RendererCsProjection.dll") -join '|';
|
||||
$nullVersionExceptions = @(
|
||||
"SkiaSharp.Views.WinUI.Native.dll",
|
||||
"libSkiaSharp.dll",
|
||||
"codicon.ttf",
|
||||
"e_sqlite3.dll",
|
||||
"getfilesiginforedist.dll",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.19041",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.20348",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.22621",
|
||||
"Microsoft.VisualStudio.Component.Windows10SDK.26100",
|
||||
"Microsoft.VisualStudio.ComponentGroup.UWP.VC",
|
||||
"Microsoft.VisualStudio.Component.UWP.VC.ARM64",
|
||||
"Microsoft.VisualStudio.Component.VC.Runtimes.ARM64.Spectre",
|
||||
|
||||
@@ -181,7 +181,6 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
|
||||
## PowerToys core team
|
||||
|
||||
- [@cinnamon-msft](https://github.com/cinnamon-msft) - Kayla Cinnamon - Lead
|
||||
- [@nguyen-dows](https://github.com/nguyen-dows) - Christopher Nguyen - Product Manager
|
||||
- [@craigloewen-msft](https://github.com/craigloewen-msft) - Craig Loewen - Product Manager
|
||||
- [@niels9001](https://github.com/niels9001/) - Niels Laute - Product Manager
|
||||
- [@dhowett](https://github.com/dhowett) - Dustin Howett - Dev lead
|
||||
@@ -213,6 +212,7 @@ ZoomIt source code was originally implemented by [Sysinternals](https://sysinter
|
||||
- [@ethanfangg](https://github.com/ethanfangg) - Ethan Fang - Product Manager
|
||||
- [@plante-msft](https://github.com/plante-msft) - Connor Plante - Product Manager
|
||||
- [@joadoumie](https://github.com/joadoumie) - Jordi Adoumie - Product Manager
|
||||
- [@nguyen-dows](https://github.com/nguyen-dows) - Christopher Nguyen - Product Manager
|
||||
- [@enricogior](https://github.com/enricogior) - Enrico Giordani - Dev Lead
|
||||
- [@bzoz](https://github.com/bzoz) - Bartosz Sosnowski - Dev
|
||||
- [@ivan100sic](https://github.com/ivan100sic) - Ivan Stošić - Dev
|
||||
|
||||
@@ -96,8 +96,8 @@
|
||||
|
||||
<!-- Global props OverrideWindowsTargetPlatformVersion-->
|
||||
<PropertyGroup Label="Globals">
|
||||
<WindowsTargetPlatformVersion>10.0.22621.0</WindowsTargetPlatformVersion>
|
||||
<TargetPlatformVersion>10.0.22621.0</TargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
<TargetPlatformVersion>10.0.26100.0</TargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -47,14 +47,14 @@
|
||||
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
|
||||
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="9.0.6" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.183" />
|
||||
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
|
||||
<!--
|
||||
TODO: in Common.Dotnet.CsWinRT.props, on upgrade, verify RemoveCsWinRTPackageAnalyzer is no longer needed.
|
||||
This is present due to a bug in CsWinRT where WPF projects cause the analyzer to fail.
|
||||
-->
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4188" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
|
||||
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
@@ -69,6 +69,8 @@
|
||||
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
|
||||
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
||||
<PackageVersion Include="SharpCompress" Version="0.37.2" />
|
||||
<!-- Don't update SkiaSharp.Views.WinUI to version 3.* branch as this brakes the HexBox control in Registry Preview. -->
|
||||
<PackageVersion Include="SkiaSharp.Views.WinUI" Version="2.88.9" />
|
||||
<PackageVersion Include="StreamJsonRpc" Version="2.21.69" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
||||
|
||||
37
NOTICE.md
37
NOTICE.md
@@ -1427,6 +1427,37 @@ EXHIBIT A -Mozilla Public License.
|
||||
|
||||
## Utility: Registry Preview
|
||||
|
||||
### HexBox.WinUI
|
||||
|
||||
We use HexBox.WinUI to show a preview of binary values.
|
||||
|
||||
**Source**: https://github.com/hotkidfamily/HexBox.WinUI
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Filip Jeremic
|
||||
Copyright (c) 2024~2025 hotkidfamily@gmail.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
### Monaco Editor
|
||||
|
||||
**Source**: https://github.com/Microsoft/monaco-editor
|
||||
@@ -1457,6 +1488,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
|
||||
## NuGet Packages used by PowerToys
|
||||
|
||||
- AdaptiveCards.ObjectModel.WinUI3 2.0.0-beta
|
||||
@@ -1501,9 +1533,9 @@ SOFTWARE.
|
||||
- Microsoft.Web.WebView2 1.0.2903.40
|
||||
- Microsoft.Win32.SystemEvents 9.0.6
|
||||
- Microsoft.Windows.Compatibility 9.0.6
|
||||
- Microsoft.Windows.CsWin32 0.2.46-beta
|
||||
- Microsoft.Windows.CsWin32 0.3.183
|
||||
- Microsoft.Windows.CsWinRT 2.2.0
|
||||
- Microsoft.Windows.SDK.BuildTools 10.0.22621.2428
|
||||
- Microsoft.Windows.SDK.BuildTools 10.0.26100.4188
|
||||
- Microsoft.WindowsAppSDK 1.7.250513003
|
||||
- Microsoft.WindowsPackageManager.ComInterop 1.10.340
|
||||
- Microsoft.Xaml.Behaviors.WinUI.Managed 2.0.9
|
||||
@@ -1517,6 +1549,7 @@ SOFTWARE.
|
||||
- ReverseMarkdown 4.1.0
|
||||
- ScipBe.Common.Office.OneNote 3.0.1
|
||||
- SharpCompress 0.37.2
|
||||
- SkiaSharp.Views.WinUI 2.88.9
|
||||
- StreamJsonRpc 2.21.69
|
||||
- StyleCop.Analyzers 1.2.0-beta.556
|
||||
- System.CodeDom 9.0.6
|
||||
|
||||
@@ -8,10 +8,10 @@ SET VCToolsVersion=!VCToolsVersion!
|
||||
SET ClearDevCommandPromptEnvVars=false
|
||||
|
||||
rem In case of Release we should not use Debug CRT in VCRT forwarders
|
||||
msbuild !PTRoot!\src\modules\previewpane\MonacoPreviewHandler\MonacoPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml
|
||||
msbuild !PTRoot!\src\modules\previewpane\MonacoPreviewHandler\MonacoPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net9.0-windows10.0.26100.0
|
||||
|
||||
msbuild !PTRoot!\src\modules\previewpane\MarkdownPreviewHandler\MarkdownPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml
|
||||
msbuild !PTRoot!\src\modules\previewpane\MarkdownPreviewHandler\MarkdownPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net9.0-windows10.0.26100.0
|
||||
|
||||
msbuild !PTRoot!\src\modules\previewpane\SvgPreviewHandler\SvgPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml
|
||||
msbuild !PTRoot!\src\modules\previewpane\SvgPreviewHandler\SvgPreviewHandler.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net9.0-windows10.0.26100.0
|
||||
|
||||
msbuild !PTRoot!\src\modules\previewpane\SvgThumbnailProvider\SvgThumbnailProvider.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml
|
||||
msbuild !PTRoot!\src\modules\previewpane\SvgThumbnailProvider\SvgThumbnailProvider.csproj -t:Publish -p:Configuration="Release" -p:Platform="!PlatformArg!" -p:AppxBundle=Never -p:PowerToysRoot=!PTRoot! -p:VCRTForwarders-IncludeDebugCRT=false -p:PublishProfile=InstallationPublishProfile.pubxml -p:TargetFramework=net9.0-windows10.0.26100.0
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<Import Project=".\Common.Dotnet.PrepareGeneratedFolder.targets" />
|
||||
|
||||
<PropertyGroup>
|
||||
<WindowsSdkPackageVersion>10.0.22621.57</WindowsSdkPackageVersion>
|
||||
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>
|
||||
<WindowsSdkPackageVersion>10.0.26100.68-preview</WindowsSdkPackageVersion>
|
||||
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
|
||||
@@ -76,3 +76,47 @@ using System.Diagnostics.CodeAnalysis;
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "Peek.FilePreviewer")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.INotifyPropertyChangedGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "type", Target = "~T:Peek.UI.Views.TitleBar")]
|
||||
[assembly: SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.ObservablePropertyGenerator", "MVVMTK0049:Using [INotifyPropertyChanged] is not AOT compatible for WinRT", Justification = "Updated MVVM toolkit package introduced this.", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib")]
|
||||
|
||||
// HexBox control in RegistryPreviewUILib (We decided to copy the original code and not fix all theses problems for easier updating.)
|
||||
[assembly: SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Design", "CA1051:Do not declare visible instance fields", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Globalization", "CA1305:Specify IFormatProvider", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Naming", "CA1720:Identifiers should not contain type names", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Performance", "CA1805:Do not initialize unnecessarily", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1623:Property summary documentation should match accessors", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1642:Constructor summary documentation should begin with standard text", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1648:<inheritdoc> has been used on an element that doesn't inherit from a base class or implement an interface.", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1500:Braces for multi-line statements should not share line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1502:Element should not be on a single line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1503:Braces should not be omitted", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1505:Opening braces should not be followed by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1507:Code should not contain multiple blank lines in a row", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1508:Closing braces should not be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1509:Opening braces should not be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1512:Single-line comments should not be followed by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1513:Closing brace should be followed by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1514:Element documentation header should be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:Single-line comment should be preceded by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1516:Elements should be separated by blank line", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1119:Statement should not use unnecessary parenthesis", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1401:Fields should be private", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1402:File may only contain a single type", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1407:Arithmetic expressions should declare precedence", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1413:Use trailing comma in multi-line initializers", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1306:Field names should begin with lower-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1312:Variable names should begin with lower-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1313:Parameter names should begin with lower-case letter", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:Using directives should be placed correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1108:Block statements should not contain embedded comments", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1116:Split parameters should start on line after declaration", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1117:Parameters should be on same line or separate lines", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1129:Do not use default value type constructor", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1000:Keywords should be spaced correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1003:Symbols should be spaced correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1005:Single line comments should begin with single space", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1024:Colons Should Be Spaced Correctly", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1025:Code should not contain multiple whitespace in a row", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("StyleCop.CSharp.SpacingRules", "SA1028:Code should not contain trailing whitespace", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
[assembly: SuppressMessage("Usage", "CsWinRT1028:Class is not marked partial", Justification = "<Code port with style preservation>", Scope = "namespaceanddescendants", Target = "RegistryPreviewUILib.HexBox")]
|
||||
|
||||
36
src/common/CalculatorEngineCommon/CalculatorEngineCommon.rc
Normal file
36
src/common/CalculatorEngineCommon/CalculatorEngineCommon.rc
Normal file
@@ -0,0 +1,36 @@
|
||||
#include <windows.h>
|
||||
#include "resource.h"
|
||||
#include "../version/version.h"
|
||||
|
||||
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
|
||||
@@ -98,6 +98,11 @@
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\version\version.vcxproj">
|
||||
<Project>{cc6e41ac-8174-4e8a-8d22-85dd7f4851df}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ExprtkEvaluator.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
@@ -105,6 +110,7 @@
|
||||
<ClInclude Include="Calculator.h">
|
||||
<DependentUpon>Calculator.idl</DependentUpon>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ExprtkEvaluator.cpp">
|
||||
@@ -128,6 +134,9 @@
|
||||
<ItemGroup>
|
||||
<None Include="PropertySheet.props" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="CalculatorEngineCommon.rc" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
||||
13
src/common/CalculatorEngineCommon/resource.h
Normal file
13
src/common/CalculatorEngineCommon/resource.h
Normal file
@@ -0,0 +1,13 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by CalculatorEngineCommon.rc
|
||||
|
||||
//////////////////////////////
|
||||
// Non-localizable
|
||||
|
||||
#define FILE_DESCRIPTION "CalculatorEngineCommon"
|
||||
#define INTERNAL_NAME "CalculatorEngineCommon"
|
||||
#define ORIGINAL_FILENAME "CalculatorEngineCommon.dll"
|
||||
|
||||
// Non-localizable
|
||||
//////////////////////////////
|
||||
@@ -10,7 +10,7 @@
|
||||
<ProjectGuid>{f5e1146e-b7b3-4e11-85fd-270a500bd78c}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>CropAndLock</RootNamespace>
|
||||
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.22621.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
@@ -154,6 +154,9 @@
|
||||
<ProjectReference Include="..\..\..\common\Telemetry\EtwTrace\EtwTrace.vcxproj">
|
||||
<Project>{8f021b46-362b-485c-bfba-ccf83e820cbd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\Themes\Themes.vcxproj">
|
||||
<Project>{98537082-0fdb-40de-abd8-0dc5a4269bab}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
|
||||
#include <common/Telemetry/EtwTrace/EtwTrace.h>
|
||||
|
||||
#include <common/Themes/theme_helpers.h>
|
||||
#include <common/Themes/theme_listener.h>
|
||||
|
||||
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
||||
|
||||
namespace winrt
|
||||
@@ -35,6 +38,23 @@ namespace util
|
||||
const std::wstring instanceMutexName = L"Local\\PowerToys_CropAndLock_InstanceMutex";
|
||||
bool m_running = true;
|
||||
|
||||
// Theming
|
||||
ThemeListener theme_listener{};
|
||||
// Keep a list of our cropped windows
|
||||
std::vector<std::shared_ptr<CropAndLockWindow>> croppedWindows;
|
||||
|
||||
void handleTheme()
|
||||
{
|
||||
auto theme = theme_listener.AppTheme;
|
||||
auto isDark = theme == Theme::Dark;
|
||||
Logger::info(L"Theme is now {}", isDark ? L"Dark" : L"Light");
|
||||
for (auto&& croppedWindow : croppedWindows)
|
||||
{
|
||||
ThemeHelpers::SetImmersiveDarkMode(croppedWindow->Handle(), isDark);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _In_ int)
|
||||
{
|
||||
// Initialize COM
|
||||
@@ -42,6 +62,8 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
|
||||
|
||||
Trace::CropAndLock::RegisterProvider();
|
||||
|
||||
theme_listener.AddChangedHandler(handleTheme);
|
||||
|
||||
Shared::Trace::ETWTrace trace;
|
||||
trace.UpdateState(true);
|
||||
|
||||
@@ -107,8 +129,6 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
|
||||
// Create our overlay window
|
||||
std::unique_ptr<OverlayWindow> overlayWindow;
|
||||
|
||||
// Keep a list of our cropped windows
|
||||
std::vector<std::shared_ptr<CropAndLockWindow>> croppedWindows;
|
||||
|
||||
// Handles and thread for the events sent from runner
|
||||
HANDLE m_reparent_event_handle;
|
||||
@@ -167,6 +187,7 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
|
||||
croppedWindow->CropAndLock(targetWindow, cropRect);
|
||||
croppedWindow->OnClosed(removeWindowCallback);
|
||||
croppedWindows.push_back(croppedWindow);
|
||||
handleTheme();
|
||||
};
|
||||
|
||||
overlayWindow.reset();
|
||||
|
||||
@@ -5,7 +5,7 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<PublishProtocol>FileSystem</PublishProtocol>
|
||||
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>
|
||||
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<PublishDir>$(PowerToysRoot)\$(Platform)\$(Configuration)\WinUI3Apps</PublishDir>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<PropertyGroup>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DefineConstants>TESTONLY</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@@ -611,6 +611,7 @@
|
||||
<ContentDialog
|
||||
x:Name="EntryDialog"
|
||||
x:Uid="EntryDialog"
|
||||
x:DataType="models:Entry"
|
||||
IsPrimaryButtonEnabled="{Binding Valid, Mode=OneWay}"
|
||||
Loaded="ContentDialog_Loaded_ApplyMargin"
|
||||
PrimaryButtonStyle="{StaticResource AccentButtonStyle}">
|
||||
|
||||
@@ -139,10 +139,23 @@ namespace HostsUILib.Views
|
||||
dialog.XamlRoot = XamlRoot;
|
||||
dialog.Style = Application.Current.Resources["DefaultContentDialogStyle"] as Style;
|
||||
dialog.Title = resourceLoader.GetString("WarningDialog_Title");
|
||||
dialog.Content = new TextBlock
|
||||
dialog.Content = new StackPanel
|
||||
{
|
||||
Text = resourceLoader.GetString("WarningDialog_Text"),
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
Children =
|
||||
{
|
||||
new TextBlock
|
||||
{
|
||||
Text = resourceLoader.GetString("WarningDialog_Text"),
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
},
|
||||
new HyperlinkButton
|
||||
{
|
||||
Content = resourceLoader.GetString("WarningDialog_LearnMore"),
|
||||
NavigateUri = new Uri("https://aka.ms/PowerToysOverview_HostsFileEditor"),
|
||||
Padding = new Thickness(0),
|
||||
Margin = new Thickness(0, 5, 0, 5),
|
||||
},
|
||||
},
|
||||
};
|
||||
dialog.PrimaryButtonText = resourceLoader.GetString("WarningDialog_AcceptBtn");
|
||||
dialog.PrimaryButtonStyle = Application.Current.Resources["AccentButtonStyle"] as Style;
|
||||
|
||||
@@ -11,6 +11,9 @@ using HostsUILib.Helpers;
|
||||
|
||||
namespace HostsUILib.Models
|
||||
{
|
||||
#if !TESTONLY
|
||||
[Microsoft.UI.Xaml.Data.Bindable]
|
||||
#endif
|
||||
public partial class Entry : ObservableObject
|
||||
{
|
||||
private static readonly char[] _spaceCharacters = new char[] { ' ', '\t' };
|
||||
|
||||
@@ -331,6 +331,9 @@
|
||||
<data name="WarningDialog_Title" xml:space="preserve">
|
||||
<value>Warning</value>
|
||||
</data>
|
||||
<data name="WarningDialog_LearnMore" xml:space="preserve">
|
||||
<value>Learn more</value>
|
||||
</data>
|
||||
<data name="WindowAdminTitle" xml:space="preserve">
|
||||
<value>Administrator: Hosts File Editor</value>
|
||||
<comment>Title of the window when running as administrator. "Hosts File Editor" is the name of the utility. "Hosts" refers to the system hosts file, do not loc</comment>
|
||||
|
||||
@@ -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.7.250513003\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||
@@ -139,7 +139,7 @@
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.targets" Condition="Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.targets')" />
|
||||
</ImportGroup>
|
||||
@@ -150,8 +150,8 @@
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.231216.1\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188\build\Microsoft.Windows.SDK.BuildTools.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2903.40\build\native\Microsoft.Web.WebView2.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.WindowsAppSDK.1.7.250513003\build\native\Microsoft.WindowsAppSDK.targets'))" />
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.231216.1" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.2428" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.26100.4188" targetFramework="native" />
|
||||
<package id="Microsoft.WindowsAppSDK" version="1.7.250513003" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -9,7 +9,7 @@
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{0db0f63a-d2f8-4da3-a650-2d0b8724218e}</ProjectGuid>
|
||||
<RootNamespace>NewPlusShellExtensionWin10</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.22621.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
|
||||
@@ -49,6 +49,8 @@ namespace WorkspacesEditor.Data
|
||||
public WindowPositionWrapper Position { get; set; }
|
||||
|
||||
public int Monitor { get; set; }
|
||||
|
||||
public string Version { get; set; }
|
||||
}
|
||||
|
||||
public struct MonitorConfigurationWrapper
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace WorkspacesEditor.Models
|
||||
Maximized = other.Maximized;
|
||||
Position = other.Position;
|
||||
MonitorNumber = other.MonitorNumber;
|
||||
Version = other.Version;
|
||||
|
||||
Parent = other.Parent;
|
||||
IsNotFound = other.IsNotFound;
|
||||
@@ -274,5 +275,7 @@ namespace WorkspacesEditor.Models
|
||||
CommandLineArguments = newCommandLineValue;
|
||||
OnPropertyChanged(new PropertyChangedEventArgs(nameof(AppMainParams)));
|
||||
}
|
||||
|
||||
public string Version { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,6 +246,7 @@ namespace WorkspacesEditor.Models
|
||||
AppPath = app.ApplicationPath,
|
||||
AppTitle = app.Title,
|
||||
PwaAppId = string.IsNullOrEmpty(app.PwaAppId) ? string.Empty : app.PwaAppId,
|
||||
Version = string.IsNullOrEmpty(app.Version) ? string.Empty : app.Version,
|
||||
PackageFullName = app.PackageFullName,
|
||||
AppUserModelId = app.AppUserModelId,
|
||||
Parent = this,
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace WorkspacesEditor.Utils
|
||||
CommandLineArguments = app.CommandLineArguments,
|
||||
IsElevated = app.IsElevated,
|
||||
CanLaunchElevated = app.CanLaunchElevated,
|
||||
Version = app.Version,
|
||||
Maximized = app.Maximized,
|
||||
Minimized = app.Minimized,
|
||||
Position = new ProjectData.ApplicationWrapper.WindowPositionWrapper
|
||||
|
||||
@@ -165,16 +165,52 @@ namespace AppLauncher
|
||||
|
||||
if (!launched && !app.pwaAppId.empty())
|
||||
{
|
||||
std::filesystem::path appPath(app.path);
|
||||
if (appPath.filename() == NonLocalizable::EdgeFilename)
|
||||
int version = 0;
|
||||
|
||||
if (app.version != L"")
|
||||
{
|
||||
appPathFinal = appPath.parent_path() / NonLocalizable::EdgePwaFilename;
|
||||
commandLineArgsFinal = NonLocalizable::PwaCommandLineAddition + app.pwaAppId + L" " + app.commandLineArgs;
|
||||
try
|
||||
{
|
||||
version = std::stoi(app.version);
|
||||
}
|
||||
catch (const std::invalid_argument&)
|
||||
{
|
||||
Logger::error(L"Invalid version format: {}", app.version);
|
||||
version = 0;
|
||||
}
|
||||
catch (const std::out_of_range&)
|
||||
{
|
||||
Logger::error(L"Version out of range: {}", app.version);
|
||||
version = 0;
|
||||
}
|
||||
}
|
||||
if (appPath.filename() == NonLocalizable::ChromeFilename)
|
||||
|
||||
if (version >= 1)
|
||||
{
|
||||
appPathFinal = appPath.parent_path() / NonLocalizable::ChromePwaFilename;
|
||||
commandLineArgsFinal = NonLocalizable::PwaCommandLineAddition + app.pwaAppId + L" " + app.commandLineArgs;
|
||||
auto res = LaunchApp(L"shell:AppsFolder\\" + app.appUserModelId, app.commandLineArgs, app.isElevated);
|
||||
if (res.isOk())
|
||||
{
|
||||
launched = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
launchErrors.push_back({ app.appUserModelId, res.error() });
|
||||
}
|
||||
}
|
||||
|
||||
if (!launched)
|
||||
{
|
||||
std::filesystem::path appPath(app.path);
|
||||
if (appPath.filename() == NonLocalizable::EdgeFilename)
|
||||
{
|
||||
appPathFinal = appPath.parent_path() / NonLocalizable::EdgePwaFilename;
|
||||
commandLineArgsFinal = NonLocalizable::PwaCommandLineAddition + app.pwaAppId + L" " + app.commandLineArgs;
|
||||
}
|
||||
if (appPath.filename() == NonLocalizable::ChromeFilename)
|
||||
{
|
||||
appPathFinal = appPath.parent_path() / NonLocalizable::ChromePwaFilename;
|
||||
commandLineArgsFinal = NonLocalizable::PwaCommandLineAddition + app.pwaAppId + L" " + app.commandLineArgs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,19 +76,6 @@ namespace WorkspacesLibUnitTests
|
||||
Assert::IsTrue(result == nonExistentWindowAumid);
|
||||
}
|
||||
|
||||
TEST_METHOD (PwaHelper_GetAUMIDFromWindow_InvalidWindow_ReturnsEmpty)
|
||||
{
|
||||
// Arrange
|
||||
Utils::PwaHelper helper;
|
||||
HWND invalidWindow = nullptr;
|
||||
|
||||
// Act
|
||||
std::wstring result = helper.GetAUMIDFromWindow(invalidWindow);
|
||||
|
||||
// Assert
|
||||
Assert::IsTrue(result.empty());
|
||||
}
|
||||
|
||||
TEST_METHOD (PwaHelper_GetEdgeAppId_ValidConstruction_DoesNotCrash)
|
||||
{
|
||||
// Arrange
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "pch.h"
|
||||
#include "PwaHelper.h"
|
||||
#include "WindowUtils.h"
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
@@ -51,7 +52,7 @@ namespace Utils
|
||||
localFolder = L""; // Ensure it is explicitly set to empty on failure
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return localFolder;
|
||||
}
|
||||
|
||||
@@ -193,7 +194,7 @@ namespace Utils
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
std::optional<std::wstring> PwaHelper::GetChromeAppId(const std::wstring& windowAumid) const
|
||||
{
|
||||
const auto appIdIndexStart = windowAumid.find(NonLocalizable::ChromeAppIdIdentifier);
|
||||
@@ -256,85 +257,4 @@ namespace Utils
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring PwaHelper::GetAUMIDFromWindow(HWND hwnd) const
|
||||
{
|
||||
std::wstring result{};
|
||||
if (hwnd == NULL)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<IPropertyStore> propertyStore;
|
||||
HRESULT hr = SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(&propertyStore));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
PROPVARIANT propVariant;
|
||||
PropVariantInit(&propVariant);
|
||||
|
||||
hr = propertyStore->GetValue(PKEY_AppUserModel_ID, &propVariant);
|
||||
if (SUCCEEDED(hr) && propVariant.vt == VT_LPWSTR && propVariant.pwszVal != nullptr)
|
||||
{
|
||||
result = propVariant.pwszVal;
|
||||
}
|
||||
|
||||
PropVariantClear(&propVariant);
|
||||
|
||||
Logger::info(L"Found a window with aumid {}", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::wstring PwaHelper::GetAUMIDFromProcessId(DWORD processId) const
|
||||
{
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
|
||||
if (hProcess == NULL)
|
||||
{
|
||||
Logger::error(L"Failed to open process handle. Error: {}", get_last_error_or_default(GetLastError()));
|
||||
return {};
|
||||
}
|
||||
|
||||
// Get the package full name for the process
|
||||
UINT32 packageFullNameLength = 0;
|
||||
LONG rc = GetPackageFullName(hProcess, &packageFullNameLength, nullptr);
|
||||
if (rc != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
Logger::error(L"Failed to get package full name length. Error code: {}", rc);
|
||||
CloseHandle(hProcess);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<wchar_t> packageFullName(packageFullNameLength);
|
||||
rc = GetPackageFullName(hProcess, &packageFullNameLength, packageFullName.data());
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
Logger::error(L"Failed to get package full name. Error code: {}", rc);
|
||||
CloseHandle(hProcess);
|
||||
return {};
|
||||
}
|
||||
|
||||
// Get the AUMID for the package
|
||||
UINT32 appModelIdLength = 0;
|
||||
rc = GetApplicationUserModelId(hProcess, &appModelIdLength, nullptr);
|
||||
if (rc != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
Logger::error(L"Failed to get AppUserModelId length. Error code: {}", rc);
|
||||
CloseHandle(hProcess);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<wchar_t> appModelId(appModelIdLength);
|
||||
rc = GetApplicationUserModelId(hProcess, &appModelIdLength, appModelId.data());
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
Logger::error(L"Failed to get AppUserModelId. Error code: {}", rc);
|
||||
CloseHandle(hProcess);
|
||||
return {};
|
||||
}
|
||||
|
||||
CloseHandle(hProcess);
|
||||
return std::wstring(appModelId.data());
|
||||
}
|
||||
}
|
||||
@@ -12,19 +12,16 @@ namespace Utils
|
||||
PwaHelper();
|
||||
~PwaHelper() = default;
|
||||
|
||||
std::wstring GetAUMIDFromWindow(HWND hWnd) const;
|
||||
|
||||
std::optional<std::wstring> GetEdgeAppId(const std::wstring& windowAumid) const;
|
||||
std::optional<std::wstring> GetChromeAppId(const std::wstring& windowAumid) const;
|
||||
std::optional<std::wstring> GetChromeAppId(const std::wstring& windowAumid) const;
|
||||
std::wstring SearchPwaName(const std::wstring& pwaAppId, const std::wstring& windowAumid) const;
|
||||
|
||||
|
||||
private:
|
||||
void InitAppIds(const std::wstring& browserDataFolder, const std::wstring& browserDirPrefix, const std::function<void(const std::wstring&)>& addingAppIdCallback);
|
||||
void InitEdgeAppIds();
|
||||
void InitChromeAppIds();
|
||||
|
||||
std::wstring GetAppIdFromCommandLineArgs(const std::wstring& commandLineArgs) const;
|
||||
std::wstring GetAUMIDFromProcessId(DWORD processId) const;
|
||||
|
||||
std::map<std::wstring, std::wstring> m_edgeAppIds;
|
||||
std::vector<std::wstring> m_chromeAppIds;
|
||||
|
||||
18
src/modules/Workspaces/WorkspacesLib/StringUtils.cpp
Normal file
18
src/modules/Workspaces/WorkspacesLib/StringUtils.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include "pch.h"
|
||||
|
||||
#include "StringUtils.h"
|
||||
|
||||
namespace StringUtils
|
||||
{
|
||||
bool CaseInsensitiveEquals(const std::wstring& str1, const std::wstring& str2)
|
||||
{
|
||||
if (str1.size() != str2.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::equal(str1.begin(), str1.end(), str2.begin(), [](wchar_t ch1, wchar_t ch2) {
|
||||
return towupper(ch1) == towupper(ch2);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -6,15 +6,5 @@
|
||||
|
||||
namespace StringUtils
|
||||
{
|
||||
inline bool CaseInsensitiveEquals(const std::wstring& str1, const std::wstring& str2)
|
||||
{
|
||||
if (str1.size() != str2.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return std::equal(str1.begin(), str1.end(), str2.begin(), [](wchar_t ch1, wchar_t ch2) {
|
||||
return towupper(ch1) == towupper(ch2);
|
||||
});
|
||||
}
|
||||
bool CaseInsensitiveEquals(const std::wstring& str1, const std::wstring& str2);
|
||||
}
|
||||
|
||||
105
src/modules/Workspaces/WorkspacesLib/WindowUtils.cpp
Normal file
105
src/modules/Workspaces/WorkspacesLib/WindowUtils.cpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#include "pch.h"
|
||||
#include "WindowUtils.h"
|
||||
#include <filesystem>
|
||||
|
||||
#include <appmodel.h>
|
||||
|
||||
#include <shellapi.h>
|
||||
#include <ShlObj.h>
|
||||
#include <shobjidl.h>
|
||||
#include <tlhelp32.h>
|
||||
#include <wrl.h>
|
||||
#include <propkey.h>
|
||||
|
||||
#include <wil/com.h>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
|
||||
#include <WorkspacesLib/AppUtils.h>
|
||||
#include <WorkspacesLib/CommandLineArgsHelper.h>
|
||||
#include <WorkspacesLib/StringUtils.h>
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
std::wstring GetAUMIDFromProcessId(DWORD processId)
|
||||
{
|
||||
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
|
||||
if (hProcess == NULL)
|
||||
{
|
||||
Logger::error(L"Failed to open process handle. Error: {}", get_last_error_or_default(GetLastError()));
|
||||
return {};
|
||||
}
|
||||
|
||||
// Get the package full name for the process
|
||||
UINT32 packageFullNameLength = 0;
|
||||
LONG rc = GetPackageFullName(hProcess, &packageFullNameLength, nullptr);
|
||||
if (rc != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
Logger::error(L"Failed to get package full name length. Error code: {}", rc);
|
||||
CloseHandle(hProcess);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<wchar_t> packageFullName(packageFullNameLength);
|
||||
rc = GetPackageFullName(hProcess, &packageFullNameLength, packageFullName.data());
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
Logger::error(L"Failed to get package full name. Error code: {}", rc);
|
||||
CloseHandle(hProcess);
|
||||
return {};
|
||||
}
|
||||
|
||||
// Get the AUMID for the package
|
||||
UINT32 appModelIdLength = 0;
|
||||
rc = GetApplicationUserModelId(hProcess, &appModelIdLength, nullptr);
|
||||
if (rc != ERROR_INSUFFICIENT_BUFFER)
|
||||
{
|
||||
Logger::error(L"Failed to get AppUserModelId length. Error code: {}", rc);
|
||||
CloseHandle(hProcess);
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<wchar_t> appModelId(appModelIdLength);
|
||||
rc = GetApplicationUserModelId(hProcess, &appModelIdLength, appModelId.data());
|
||||
if (rc != ERROR_SUCCESS)
|
||||
{
|
||||
Logger::error(L"Failed to get AppUserModelId. Error code: {}", rc);
|
||||
CloseHandle(hProcess);
|
||||
return {};
|
||||
}
|
||||
|
||||
CloseHandle(hProcess);
|
||||
return std::wstring(appModelId.data());
|
||||
}
|
||||
|
||||
std::wstring GetAUMIDFromWindow(HWND hwnd)
|
||||
{
|
||||
std::wstring result{};
|
||||
if (hwnd == NULL)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<IPropertyStore> propertyStore;
|
||||
HRESULT hr = SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(&propertyStore));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
PROPVARIANT propVariant;
|
||||
PropVariantInit(&propVariant);
|
||||
|
||||
hr = propertyStore->GetValue(PKEY_AppUserModel_ID, &propVariant);
|
||||
if (SUCCEEDED(hr) && propVariant.vt == VT_LPWSTR && propVariant.pwszVal != nullptr)
|
||||
{
|
||||
result = propVariant.pwszVal;
|
||||
}
|
||||
|
||||
PropVariantClear(&propVariant);
|
||||
|
||||
Logger::info(L"Found a window with aumid {}", result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
12
src/modules/Workspaces/WorkspacesLib/WindowUtils.h
Normal file
12
src/modules/Workspaces/WorkspacesLib/WindowUtils.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <WorkspacesLib/AppUtils.h>
|
||||
#include <wtypes.h>
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
std::wstring GetAUMIDFromWindow(HWND hWnd);
|
||||
std::wstring GetAUMIDFromProcessId(DWORD processId);
|
||||
};
|
||||
@@ -87,6 +87,7 @@ namespace WorkspacesData
|
||||
const static wchar_t* MaximizedID = L"maximized";
|
||||
const static wchar_t* PositionID = L"position";
|
||||
const static wchar_t* MonitorID = L"monitor";
|
||||
const static wchar_t* VersionID = L"version";
|
||||
}
|
||||
|
||||
json::JsonObject ToJson(const WorkspacesProject::Application& data)
|
||||
@@ -106,6 +107,7 @@ namespace WorkspacesData
|
||||
json.SetNamedValue(NonLocalizable::MaximizedID, json::value(data.isMaximized));
|
||||
json.SetNamedValue(NonLocalizable::PositionID, PositionJSON::ToJson(data.position));
|
||||
json.SetNamedValue(NonLocalizable::MonitorID, json::value(data.monitor));
|
||||
json.SetNamedValue(NonLocalizable::VersionID, json::value(data.version));
|
||||
|
||||
return json;
|
||||
}
|
||||
@@ -168,6 +170,11 @@ namespace WorkspacesData
|
||||
|
||||
result.position = position.value();
|
||||
}
|
||||
|
||||
if (json.HasKey(NonLocalizable::VersionID))
|
||||
{
|
||||
result.version = json.GetNamedString(NonLocalizable::VersionID);
|
||||
}
|
||||
}
|
||||
catch (const winrt::hresult_error&)
|
||||
{
|
||||
@@ -286,6 +293,7 @@ namespace WorkspacesData
|
||||
const static wchar_t* MoveExistingWindowsID = L"move-existing-windows";
|
||||
const static wchar_t* MonitorConfigurationID = L"monitor-configuration";
|
||||
const static wchar_t* AppsID = L"applications";
|
||||
const static wchar_t* Version = L"version";
|
||||
}
|
||||
|
||||
json::JsonObject ToJson(const WorkspacesProject& data)
|
||||
|
||||
@@ -33,6 +33,9 @@ namespace WorkspacesData
|
||||
std::wstring appUserModelId;
|
||||
std::wstring pwaAppId;
|
||||
std::wstring commandLineArgs;
|
||||
|
||||
// empty to 1,
|
||||
std::wstring version;
|
||||
bool isElevated{};
|
||||
bool canLaunchElevated{};
|
||||
bool isMinimized{};
|
||||
@@ -86,7 +89,7 @@ namespace WorkspacesData
|
||||
{
|
||||
WorkspacesData::WorkspacesProject::Application application;
|
||||
HWND window{};
|
||||
LaunchingState state { LaunchingState::Waiting };
|
||||
LaunchingState state{ LaunchingState::Waiting };
|
||||
};
|
||||
|
||||
using LaunchingAppStateMap = std::map<WorkspacesData::WorkspacesProject::Application, LaunchingAppState>;
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
<ClInclude Include="StringUtils.h" />
|
||||
<ClInclude Include="utils.h" />
|
||||
<ClInclude Include="WbemHelper.h" />
|
||||
<ClInclude Include="WindowUtils.h" />
|
||||
<ClInclude Include="WorkspacesData.h" />
|
||||
<ClInclude Include="trace.h" />
|
||||
</ItemGroup>
|
||||
@@ -59,8 +60,10 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="PwaHelper.cpp" />
|
||||
<ClCompile Include="SteamGameHelper.cpp" />
|
||||
<ClCompile Include="StringUtils.cpp" />
|
||||
<ClCompile Include="two_way_pipe_message_ipc.cpp" />
|
||||
<ClCompile Include="WbemHelper.cpp" />
|
||||
<ClCompile Include="WindowUtils.cpp" />
|
||||
<ClCompile Include="WorkspacesData.cpp" />
|
||||
<ClCompile Include="trace.cpp" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
<ClInclude Include="SteamHelper.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WindowUtils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
@@ -94,6 +97,12 @@
|
||||
<ClCompile Include="SteamGameHelper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WindowUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StringUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <WorkspacesLib/AppUtils.h>
|
||||
#include <WorkspacesLib/PwaHelper.h>
|
||||
#include <WorkspacesLib/WindowUtils.h>
|
||||
#include <WindowProperties/WorkspacesWindowPropertyUtils.h>
|
||||
|
||||
#include "Generated Files/resource.h"
|
||||
@@ -139,7 +140,7 @@ namespace SnapshotUtils
|
||||
bool isChrome = appData.IsChrome();
|
||||
if (isEdge || isChrome)
|
||||
{
|
||||
auto windowAumid = pwaHelper.GetAUMIDFromWindow(window);
|
||||
auto windowAumid = Utils::GetAUMIDFromWindow(window);
|
||||
std::optional<std::wstring> pwaAppId{};
|
||||
|
||||
if (isEdge)
|
||||
@@ -158,6 +159,8 @@ namespace SnapshotUtils
|
||||
|
||||
appData.pwaAppId = pwaAppId.value();
|
||||
appData.name = pwaName + L" (" + appData.name + L")";
|
||||
// If it's pwa app, appUserModelId should be their own pwa id.
|
||||
appData.appUserModelId = windowAumid;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -185,6 +188,7 @@ namespace SnapshotUtils
|
||||
.appUserModelId = appData.appUserModelId,
|
||||
.pwaAppId = appData.pwaAppId,
|
||||
.commandLineArgs = L"",
|
||||
.version = L"1",
|
||||
.isElevated = IsProcessElevated(pid),
|
||||
.canLaunchElevated = appData.canLaunchElevated,
|
||||
.isMinimized = isMinimized,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <WindowProperties/WorkspacesWindowPropertyUtils.h>
|
||||
#include <WorkspacesLib/PwaHelper.h>
|
||||
#include <WorkspacesLib/WindowUtils.h>
|
||||
|
||||
namespace NonLocalizable
|
||||
{
|
||||
@@ -203,7 +204,7 @@ std::optional<WindowWithDistance> WindowArranger::GetNearestWindow(const Workspa
|
||||
|
||||
if (!data->IsSteamGame() && !WindowUtils::HasThickFrame(window))
|
||||
{
|
||||
// Only care about steam games if it has no thick frame to remain consistent with
|
||||
// Only care about steam games if it has no thick frame to remain consistent with
|
||||
// the behavior as before.
|
||||
continue;
|
||||
}
|
||||
@@ -220,7 +221,7 @@ std::optional<WindowWithDistance> WindowArranger::GetNearestWindow(const Workspa
|
||||
bool isChrome = appData.IsChrome();
|
||||
if (isEdge || isChrome)
|
||||
{
|
||||
auto windowAumid = pwaHelper.GetAUMIDFromWindow(window);
|
||||
auto windowAumid = Utils::GetAUMIDFromWindow(window);
|
||||
std::optional<std::wstring> pwaAppId{};
|
||||
|
||||
if (isEdge)
|
||||
|
||||
@@ -117,16 +117,18 @@ private:
|
||||
|
||||
for (DWORD pid : processIds)
|
||||
{
|
||||
HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
|
||||
HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_TERMINATE, FALSE, pid);
|
||||
|
||||
if (hProcess != NULL)
|
||||
{
|
||||
SetEvent(m_hTerminateEvent);
|
||||
|
||||
// Wait for 1.5 seconds for the process to end correctly and stop etw tracer
|
||||
WaitForSingleObject(hProcess, 1500);
|
||||
// Wait for 1.5 seconds for the process to end correctly, allowing time for ETW tracer and extensions to stop
|
||||
if (WaitForSingleObject(hProcess, 1500) == WAIT_TIMEOUT)
|
||||
{
|
||||
TerminateProcess(hProcess, 0);
|
||||
}
|
||||
|
||||
TerminateProcess(hProcess, 0);
|
||||
CloseHandle(hProcess);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.2903.40" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.2.46-beta" />
|
||||
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.22621.2428" />
|
||||
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4188" />
|
||||
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
|
||||
<PackageVersion Include="Shmuelie.WinRTServer" Version="2.1.1" />
|
||||
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
<RootNamespace>TemplateCmdPalExtension</RootNamespace>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
|
||||
<WindowsSdkPackageVersion>10.0.22621.57</WindowsSdkPackageVersion>
|
||||
<TargetFramework>net9.0-windows10.0.22621.0</TargetFramework>
|
||||
<WindowsSdkPackageVersion>10.0.26100.68-preview</WindowsSdkPackageVersion>
|
||||
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RuntimeIdentifiers>win-x64;win-arm64</RuntimeIdentifiers>
|
||||
|
||||
@@ -102,6 +102,8 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
|
||||
}
|
||||
|
||||
HandleChangeAlias();
|
||||
OnPropertyChanged(nameof(AliasText));
|
||||
OnPropertyChanged(nameof(IsDirectAlias));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,6 +118,7 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem
|
||||
}
|
||||
|
||||
HandleChangeAlias();
|
||||
OnPropertyChanged(nameof(IsDirectAlias));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ public partial class App : Application
|
||||
"Local\\PowerToysCmdPal-ExitEvent-eb73f6be-3f22-4b36-aee3-62924ba40bfd", () =>
|
||||
{
|
||||
EtwTrace?.Dispose();
|
||||
AppWindow?.Close();
|
||||
Environment.Exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -57,7 +57,11 @@ public sealed partial class MainWindow : WindowEx,
|
||||
InitializeComponent();
|
||||
|
||||
_hwnd = new HWND(WinRT.Interop.WindowNative.GetWindowHandle(this).ToInt32());
|
||||
CommandPaletteHost.SetHostHwnd((ulong)_hwnd.Value);
|
||||
|
||||
unsafe
|
||||
{
|
||||
CommandPaletteHost.SetHostHwnd((ulong)_hwnd.Value);
|
||||
}
|
||||
|
||||
_keyboardListener = new KeyboardListener();
|
||||
_keyboardListener.Start();
|
||||
|
||||
@@ -105,6 +105,10 @@
|
||||
<ProjectCapability Include="Msix" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<RdXmlFile Include="rd.xml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||
<ProjectReference Include="..\ext\Microsoft.CmdPal.Ext.System\Microsoft.CmdPal.Ext.System.csproj" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Page
|
||||
x:Class="Microsoft.CmdPal.UI.Settings.ExtensionPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
@@ -92,12 +92,11 @@
|
||||
|
||||
<controls:SettingsCard x:Uid="Settings_ExtensionPage_Alias_SettingsCard" HeaderIcon="{ui:FontIcon Glyph=}">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBox Text="{x:Bind AliasText, Mode=TwoWay}" />
|
||||
<TextBox Text="{x:Bind AliasText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
|
||||
<ToggleSwitch
|
||||
x:Uid="Settings_ExtensionPage_Alias_ToggleSwitch"
|
||||
IsEnabled="{x:Bind AliasText, Converter={StaticResource StringEmptyToBoolConverter}, Mode=OneWay}"
|
||||
IsOn="{x:Bind IsDirectAlias, Mode=TwoWay}"
|
||||
OffContent="Indirect"
|
||||
OnContent="Direct" />
|
||||
IsOn="{x:Bind IsDirectAlias, Mode=TwoWay}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
|
||||
@@ -418,4 +418,10 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
||||
<data name="TrayMenu_Exit" xml:space="preserve">
|
||||
<value>Exit</value>
|
||||
</data>
|
||||
<data name="Settings_ExtensionPage_Alias_ToggleSwitch.OnContent" xml:space="preserve">
|
||||
<value>Direct</value>
|
||||
</data>
|
||||
<data name="Settings_ExtensionPage_Alias_ToggleSwitch.OffContent" xml:space="preserve">
|
||||
<value>Indirect</value>
|
||||
</data>
|
||||
</root>
|
||||
7
src/modules/cmdpal/Microsoft.CmdPal.UI/rd.xml
Normal file
7
src/modules/cmdpal/Microsoft.CmdPal.UI/rd.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
|
||||
<Application>
|
||||
<Assembly Name="Microsoft.WinUI">
|
||||
<Type Name="Microsoft.UI.Xaml.Controls.FontIconSource" Dynamic="Required All" />
|
||||
</Assembly>
|
||||
</Application>
|
||||
</Directives>
|
||||
@@ -19,7 +19,7 @@
|
||||
<AppContainerApplication>false</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.22621.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion Condition=" '$(WindowsTargetPlatformVersion)' == '' ">10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps.Commands;
|
||||
|
||||
internal sealed partial class CopyPathCommand : InvokableCommand
|
||||
{
|
||||
private static readonly IconInfo TheIcon = new("\ue8c8");
|
||||
|
||||
private readonly string _target;
|
||||
|
||||
public CopyPathCommand(string target)
|
||||
{
|
||||
Name = Resources.copy_path;
|
||||
Icon = TheIcon;
|
||||
|
||||
_target = target;
|
||||
}
|
||||
|
||||
private static readonly CompositeFormat CopyFailedFormat = CompositeFormat.Parse(Resources.copy_failed);
|
||||
|
||||
public override CommandResult Invoke()
|
||||
{
|
||||
try
|
||||
{
|
||||
ClipboardHelper.SetText(_target);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("Copy failed: " + ex.Message);
|
||||
return CommandResult.ShowToast(
|
||||
new ToastArgs
|
||||
{
|
||||
Message = string.Format(CultureInfo.CurrentCulture, CopyFailedFormat, ex.Message),
|
||||
Result = CommandResult.KeepOpen(),
|
||||
});
|
||||
}
|
||||
|
||||
return CommandResult.ShowToast(Resources.copied_to_clipboard);
|
||||
}
|
||||
}
|
||||
@@ -85,6 +85,10 @@ public class UWPApplication : IProgram
|
||||
// We don't add context menu to 'run as different user', because UWP applications normally installed per user and not for all users.
|
||||
}
|
||||
|
||||
commands.Add(
|
||||
new CommandContextItem(
|
||||
new CopyPathCommand(Location)));
|
||||
|
||||
commands.Add(
|
||||
new CommandContextItem(
|
||||
new OpenPathCommand(Location)
|
||||
@@ -217,11 +221,10 @@ public class UWPApplication : IProgram
|
||||
var capacity = 1024U;
|
||||
PWSTR outBuffer = new PWSTR((char*)(void*)Marshal.AllocHGlobal((int)capacity * sizeof(char)));
|
||||
var source = $"@{{{packageFullName}? {parsed}}}";
|
||||
void* reserved = null;
|
||||
|
||||
try
|
||||
{
|
||||
PInvoke.SHLoadIndirectString(source, outBuffer, capacity, ref reserved).ThrowOnFailure();
|
||||
PInvoke.SHLoadIndirectString(source, outBuffer.AsSpan()).ThrowOnFailure();
|
||||
|
||||
var loaded = outBuffer.ToString();
|
||||
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
|
||||
@@ -231,7 +234,7 @@ public class UWPApplication : IProgram
|
||||
try
|
||||
{
|
||||
var sourceFallback = $"@{{{packageFullName}?{parsedFallback}}}";
|
||||
PInvoke.SHLoadIndirectString(sourceFallback, outBuffer, capacity, ref reserved).ThrowOnFailure();
|
||||
PInvoke.SHLoadIndirectString(sourceFallback, outBuffer.AsSpan()).ThrowOnFailure();
|
||||
var loaded = outBuffer.ToString();
|
||||
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
|
||||
}
|
||||
|
||||
@@ -198,6 +198,9 @@ public class Win32Program : IProgram
|
||||
new RunAsUserCommand(!string.IsNullOrEmpty(LnkFilePath) ? LnkFilePath : FullPath, ParentDirectory)));
|
||||
}
|
||||
|
||||
commands.Add(new CommandContextItem(
|
||||
new CopyPathCommand(FullPath)));
|
||||
|
||||
commands.Add(new CommandContextItem(
|
||||
new OpenPathCommand(ParentDirectory)));
|
||||
|
||||
|
||||
@@ -78,6 +78,33 @@ namespace Microsoft.CmdPal.Ext.Apps.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copied to clipboard!.
|
||||
/// </summary>
|
||||
internal static string copied_to_clipboard {
|
||||
get {
|
||||
return ResourceManager.GetString("copied_to_clipboard", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copy failed ({0}). Please try again..
|
||||
/// </summary>
|
||||
internal static string copy_failed {
|
||||
get {
|
||||
return ResourceManager.GetString("copy_failed", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Copy path.
|
||||
/// </summary>
|
||||
internal static string copy_path {
|
||||
get {
|
||||
return ResourceManager.GetString("copy_path", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Include apps found on the desktop.
|
||||
/// </summary>
|
||||
|
||||
@@ -163,12 +163,22 @@
|
||||
<data name="open_location" xml:space="preserve">
|
||||
<value>Open location</value>
|
||||
</data>
|
||||
<data name="copy_path" xml:space="preserve">
|
||||
<value>Copy path</value>
|
||||
</data>
|
||||
<data name="run_as_administrator" xml:space="preserve">
|
||||
<value>Run as administrator</value>
|
||||
</data>
|
||||
<data name="run_as_different_user" xml:space="preserve">
|
||||
<value>Run as different user</value>
|
||||
</data>
|
||||
<data name="copy_failed" xml:space="preserve">
|
||||
<value>Copy failed ({0}). Please try again.</value>
|
||||
<comment>{0} is the error message</comment>
|
||||
</data>
|
||||
<data name="copied_to_clipboard" xml:space="preserve">
|
||||
<value>Copied to clipboard!</value>
|
||||
</data>
|
||||
<data name="enable_start_menu_source" xml:space="preserve">
|
||||
<value>Include apps found in the Start Menu</value>
|
||||
</data>
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Native;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.Foundation;
|
||||
using Windows.Win32.System.Com;
|
||||
using WinRT;
|
||||
using WinRT.Interop;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
|
||||
internal static class ActionRuntimeFactory
|
||||
{
|
||||
private const string ActionRuntimeClsidStr = "C36FEF7E-35F3-4192-9F2C-AF1FD425FB85";
|
||||
|
||||
// typeof(Windows.AI.Actions.IActionRuntime).GUID
|
||||
private static readonly Guid IActionRuntimeIID = Guid.Parse("206EFA2C-C909-508A-B4B0-9482BE96DB9C");
|
||||
|
||||
public static unsafe global::Windows.AI.Actions.ActionRuntime CreateActionRuntime()
|
||||
{
|
||||
IntPtr abiPtr = default;
|
||||
try
|
||||
{
|
||||
Guid classId = Guid.Parse(ActionRuntimeClsidStr);
|
||||
Guid iid = IActionRuntimeIID;
|
||||
|
||||
var hresult = NativeMethods.CoCreateInstance(ref Unsafe.AsRef(in classId), IntPtr.Zero, NativeHelpers.CLSCTXLOCALSERVER, ref iid, out abiPtr);
|
||||
Marshal.ThrowExceptionForHR((int)hresult);
|
||||
|
||||
return MarshalInterface<global::Windows.AI.Actions.ActionRuntime>.FromAbi(abiPtr);
|
||||
}
|
||||
finally
|
||||
{
|
||||
MarshalInspectable<object>.DisposeAbi(abiPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.AI.Actions.Hosting;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer.Commands;
|
||||
|
||||
internal sealed partial class ExecuteActionCommand : InvokableCommand
|
||||
{
|
||||
private readonly ActionInstance actionInstance;
|
||||
|
||||
internal ExecuteActionCommand(ActionInstance actionInstance)
|
||||
{
|
||||
this.actionInstance = actionInstance;
|
||||
this.Name = actionInstance.DisplayInfo.Description;
|
||||
this.Icon = new IconInfo(actionInstance.Definition.IconFullPath);
|
||||
}
|
||||
|
||||
public override CommandResult Invoke()
|
||||
{
|
||||
var task = Task.Run(InvokeAsync);
|
||||
task.Wait();
|
||||
|
||||
return task.Result;
|
||||
}
|
||||
|
||||
private async Task<CommandResult> InvokeAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
await actionInstance.InvokeAsync();
|
||||
return CommandResult.GoHome();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return CommandResult.ShowToast("Failed to invoke action " + actionInstance.Definition.Id + ": " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,8 +4,11 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Commands;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Pages;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.Foundation.Metadata;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
|
||||
@@ -38,9 +41,24 @@ internal sealed partial class IndexerListItem : ListItem
|
||||
}
|
||||
}
|
||||
|
||||
MoreCommands = [
|
||||
IContextItem[] moreCommands = [
|
||||
..context,
|
||||
new CommandContextItem(new OpenWithCommand(indexerItem)),
|
||||
new CommandContextItem(new OpenWithCommand(indexerItem))];
|
||||
|
||||
if (ApiInformation.IsApiContractPresent("Windows.AI.Actions.ActionsContract", 4))
|
||||
{
|
||||
var actionsListContextItem = new ActionsListContextItem(indexerItem.FullPath);
|
||||
if (actionsListContextItem.AnyActions())
|
||||
{
|
||||
moreCommands = [
|
||||
.. moreCommands,
|
||||
actionsListContextItem
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
MoreCommands = [
|
||||
.. moreCommands,
|
||||
new CommandContextItem(new ShowFileInFolderCommand(indexerItem.FullPath) { Name = Resources.Indexer_Command_ShowInFolder }),
|
||||
new CommandContextItem(new CopyPathCommand(indexerItem)),
|
||||
new CommandContextItem(new OpenInConsoleCommand(indexerItem)),
|
||||
|
||||
@@ -34,6 +34,9 @@
|
||||
<Content Update="Assets\FileExplorer.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\Actions.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="Assets\FileExplorer.svg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
@@ -11,6 +11,7 @@ public sealed partial class NativeHelpers
|
||||
public const uint SEEMASKINVOKEIDLIST = 12;
|
||||
|
||||
public const uint CLSCTXINPROCALL = 0x17;
|
||||
public const uint CLSCTXLOCALSERVER = 0x4;
|
||||
|
||||
public struct PropertyKeys
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"$schema": "https://aka.ms/CsWin32.schema.json",
|
||||
"allowMarshaling": false,
|
||||
"emitSingleFile": false,
|
||||
"public": true
|
||||
"comInterop": {
|
||||
"preserveSigMethods": [ "*" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Commands;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.AI.Actions;
|
||||
using Windows.System;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer.Pages;
|
||||
|
||||
internal sealed partial class ActionsListContextItem : CommandContextItem
|
||||
{
|
||||
private readonly string fullPath;
|
||||
private readonly List<CommandContextItem> actions = [];
|
||||
private static readonly Lock UpdateMoreCommandsLock = new();
|
||||
private static ActionRuntime actionRuntime;
|
||||
|
||||
public ActionsListContextItem(string fullPath)
|
||||
: base(new NoOpCommand())
|
||||
{
|
||||
Title = Resources.Indexer_Command_Actions;
|
||||
Icon = Icons.Actions;
|
||||
RequestedShortcut = KeyChordHelpers.FromModifiers(alt: true, vkey: VirtualKey.A);
|
||||
this.fullPath = fullPath;
|
||||
UpdateMoreCommands();
|
||||
}
|
||||
|
||||
public bool AnyActions() => actions.Count != 0;
|
||||
|
||||
private void ActionCatalog_Changed(global::Windows.AI.Actions.Hosting.ActionCatalog sender, object args)
|
||||
{
|
||||
UpdateMoreCommands();
|
||||
}
|
||||
|
||||
private void UpdateMoreCommands()
|
||||
{
|
||||
try
|
||||
{
|
||||
lock (UpdateMoreCommandsLock)
|
||||
{
|
||||
if (actionRuntime == null)
|
||||
{
|
||||
actionRuntime = ActionRuntimeFactory.CreateActionRuntime();
|
||||
Task.Delay(500).Wait();
|
||||
}
|
||||
|
||||
actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed;
|
||||
actionRuntime.ActionCatalog.Changed += ActionCatalog_Changed;
|
||||
}
|
||||
|
||||
var extension = System.IO.Path.GetExtension(fullPath).ToLower(CultureInfo.InvariantCulture);
|
||||
ActionEntity entity = null;
|
||||
if (extension != null)
|
||||
{
|
||||
if (extension == ".jpg" || extension == ".jpeg" || extension == ".png")
|
||||
{
|
||||
entity = actionRuntime.EntityFactory.CreatePhotoEntity(fullPath);
|
||||
}
|
||||
else if (extension == ".docx" || extension == ".doc" || extension == ".pdf" || extension == ".txt")
|
||||
{
|
||||
entity = actionRuntime.EntityFactory.CreateDocumentEntity(fullPath);
|
||||
}
|
||||
}
|
||||
|
||||
if (entity == null)
|
||||
{
|
||||
entity = actionRuntime.EntityFactory.CreateFileEntity(fullPath);
|
||||
}
|
||||
|
||||
lock (actions)
|
||||
{
|
||||
actions.Clear();
|
||||
foreach (var actionInstance in actionRuntime.ActionCatalog.GetActionsForInputs([entity]))
|
||||
{
|
||||
actions.Add(new CommandContextItem(new ExecuteActionCommand(actionInstance)));
|
||||
}
|
||||
|
||||
MoreCommands = [.. actions];
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
actionRuntime = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ internal sealed class Icons
|
||||
|
||||
internal static IconInfo FileExplorer { get; } = IconHelpers.FromRelativePath("Assets\\FileExplorer.png");
|
||||
|
||||
internal static IconInfo Actions { get; } = IconHelpers.FromRelativePath("Assets\\Actions.png");
|
||||
|
||||
internal static IconInfo OpenFile { get; } = new("\uE8E5"); // OpenFile
|
||||
|
||||
internal static IconInfo Document { get; } = new("\uE8A5"); // Document
|
||||
|
||||
@@ -60,6 +60,15 @@ namespace Microsoft.CmdPal.Ext.Indexer.Properties {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Actions.
|
||||
/// </summary>
|
||||
internal static string Indexer_Command_Actions {
|
||||
get {
|
||||
return ResourceManager.GetString("Indexer_Command_Actions", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Browse.
|
||||
/// </summary>
|
||||
|
||||
@@ -138,6 +138,9 @@
|
||||
<data name="Indexer_Command_OpenWith" xml:space="preserve">
|
||||
<value>Open with</value>
|
||||
</data>
|
||||
<data name="Indexer_Command_Actions" xml:space="preserve">
|
||||
<value>Actions...</value>
|
||||
</data>
|
||||
<data name="Indexer_Command_ShowInFolder" xml:space="preserve">
|
||||
<value>Show in folder</value>
|
||||
</data>
|
||||
|
||||
@@ -110,6 +110,13 @@ internal static class Commands
|
||||
});
|
||||
}
|
||||
|
||||
results.Add(new ListItem(new ExecuteCommandConfirmation(Resources.Microsoft_plugin_sys_RestartShell_name!, confirmCommands, Resources.Microsoft_plugin_sys_RestartShell_confirmation!, static () => OpenInShellHelper.OpenInShell("cmd", "/C tskill explorer && start explorer", runWithHiddenWindow: true)))
|
||||
{
|
||||
Title = Resources.Microsoft_plugin_sys_RestartShell!,
|
||||
Subtitle = Resources.Microsoft_plugin_sys_RestartShell_description!,
|
||||
Icon = Icons.RestartShellIcon,
|
||||
});
|
||||
|
||||
// UEFI command/result. It is only available on systems booted in UEFI mode.
|
||||
if (isUefi)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,8 @@ public static partial class Icons
|
||||
|
||||
public static IconInfo RestartIcon { get; } = new IconInfo("\uE777");
|
||||
|
||||
public static IconInfo RestartShellIcon { get; } = new IconInfo("\uEC50");
|
||||
|
||||
public static IconInfo ShutdownIcon { get; } = new IconInfo("\uE7E8");
|
||||
|
||||
public static IconInfo SleepIcon { get; } = new IconInfo("\uE708");
|
||||
|
||||
@@ -645,6 +645,42 @@ namespace Microsoft.CmdPal.Ext.System {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Restart Windows Explorer.
|
||||
/// </summary>
|
||||
public static string Microsoft_plugin_sys_RestartShell {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_sys_RestartShell", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to You are about to restart Windows Explorer, are you sure?.
|
||||
/// </summary>
|
||||
public static string Microsoft_plugin_sys_RestartShell_confirmation {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_sys_RestartShell_confirmation", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to End and restart the Windows Explorer shell process.
|
||||
/// </summary>
|
||||
public static string Microsoft_plugin_sys_RestartShell_description {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_sys_RestartShell_description", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Restart.
|
||||
/// </summary>
|
||||
public static string Microsoft_plugin_sys_RestartShell_name {
|
||||
get {
|
||||
return ResourceManager.GetString("Microsoft_plugin_sys_RestartShell_name", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to ip; mac; address.
|
||||
/// </summary>
|
||||
|
||||
@@ -417,4 +417,16 @@
|
||||
<data name="Microsoft_plugin_ext_fallback_display_title" xml:space="preserve">
|
||||
<value>Open System Command</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_sys_RestartShell" xml:space="preserve">
|
||||
<value>Restart Windows Explorer</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_sys_RestartShell_description" xml:space="preserve">
|
||||
<value>End and restart the Windows Explorer shell process</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_sys_RestartShell_name" xml:space="preserve">
|
||||
<value>Restart</value>
|
||||
</data>
|
||||
<data name="Microsoft_plugin_sys_RestartShell_confirmation" xml:space="preserve">
|
||||
<value>You are about to restart Windows Explorer, are you sure?</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -68,6 +68,7 @@ internal sealed partial class FallbackTimeDateItem : FallbackCommandItem
|
||||
Title = result.Title;
|
||||
Subtitle = result.Subtitle;
|
||||
Icon = result.Icon;
|
||||
Command = result.Command;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -18,8 +18,6 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
|
||||
|
||||
private IList<ListItem> _results = new List<ListItem>();
|
||||
|
||||
private bool initialized;
|
||||
|
||||
private SettingsManager _settingsManager;
|
||||
|
||||
public TimeDateExtensionPage(SettingsManager settingsManager)
|
||||
@@ -35,12 +33,9 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
DoExecuteSearch(string.Empty);
|
||||
}
|
||||
DoExecuteSearch(string.Empty);
|
||||
|
||||
lock (_resultsLock)
|
||||
lock (_resultsLock)
|
||||
{
|
||||
ListItem[] results = _results.ToArray();
|
||||
return results;
|
||||
@@ -49,11 +44,6 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
|
||||
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
{
|
||||
if (newSearch == oldSearch)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
DoExecuteSearch(newSearch);
|
||||
}
|
||||
|
||||
@@ -84,7 +74,6 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
|
||||
{
|
||||
lock (_resultsLock)
|
||||
{
|
||||
initialized = true;
|
||||
this._results = result;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ManagedCommon;
|
||||
@@ -188,17 +189,20 @@ public static class DefaultBrowserInfo
|
||||
{
|
||||
var buffer = stackalloc char[128];
|
||||
var capacity = 128;
|
||||
void* reserved = null;
|
||||
var firstChar = str[0];
|
||||
var strPtr = &firstChar;
|
||||
|
||||
// S_OK == 0
|
||||
if (global::Windows.Win32.PInvoke.SHLoadIndirectString(
|
||||
str,
|
||||
fixed (char* pszSourceLocal = str)
|
||||
{
|
||||
if (global::Windows.Win32.PInvoke.SHLoadIndirectString(
|
||||
pszSourceLocal,
|
||||
buffer,
|
||||
(uint)capacity,
|
||||
ref reserved)
|
||||
== 0)
|
||||
{
|
||||
return new string(buffer);
|
||||
default) == 0)
|
||||
{
|
||||
return new string(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Utilities
|
||||
var FOLDERID_LocalAppData = new Guid("F1B32785-6FBA-4FCF-9D55-7B8E7F157091");
|
||||
var hr = PInvoke.SHGetKnownFolderPath(
|
||||
FOLDERID_LocalAppData,
|
||||
(uint)KNOWN_FOLDER_FLAG.KF_FLAG_FORCE_APP_DATA_REDIRECTION,
|
||||
KNOWN_FOLDER_FLAG.KF_FLAG_FORCE_APP_DATA_REDIRECTION,
|
||||
null,
|
||||
out var localAppDataFolder);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<PathToRoot>..\..\..\..\..\</PathToRoot>
|
||||
<WasdkNuget>$(PathToRoot)packages\Microsoft.WindowsAppSDK.1.7.250513003</WasdkNuget>
|
||||
<CppWinRTNuget>$(PathToRoot)packages\Microsoft.Windows.CppWinRT.2.0.240111.5</CppWinRTNuget>
|
||||
<WindowsSdkBuildToolsNuget>$(PathToRoot)packages\Microsoft.Windows.SDK.BuildTools.10.0.22621.2428</WindowsSdkBuildToolsNuget>
|
||||
<WindowsSdkBuildToolsNuget>$(PathToRoot)packages\Microsoft.Windows.SDK.BuildTools.10.0.26100.4188</WindowsSdkBuildToolsNuget>
|
||||
<WebView2Nuget>$(PathToRoot)packages\Microsoft.Web.WebView2.1.0.2903.40</WebView2Nuget>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props" Condition="Exists('$(WasdkNuget)\build\native\Microsoft.WindowsAppSDK.props')" />
|
||||
@@ -24,7 +24,7 @@
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<WindowsTargetPlatformMinVersion>10.0.19041.0</WindowsTargetPlatformMinVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.22621.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<packages>
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.2903.40" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.240111.5" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.22621.2428" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.SDK.BuildTools" version="10.0.26100.4188" targetFramework="native" />
|
||||
<package id="Microsoft.WindowsAppSDK" version="1.7.250513003" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -107,21 +107,14 @@ namespace ColorPicker.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
public void OnColorPickerMouseDown()
|
||||
public void OpenColorEditor()
|
||||
{
|
||||
if (_userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenColorPickerAndThenEditor || _userSettings.ActivationAction.Value == ColorPickerActivationAction.OpenEditor)
|
||||
lock (_colorPickerVisibilityLock)
|
||||
{
|
||||
lock (_colorPickerVisibilityLock)
|
||||
{
|
||||
HideColorPicker();
|
||||
}
|
||||
HideColorPicker();
|
||||
}
|
||||
|
||||
ShowColorPickerEditor();
|
||||
}
|
||||
else
|
||||
{
|
||||
EndUserSession();
|
||||
}
|
||||
ShowColorPickerEditor();
|
||||
}
|
||||
|
||||
public static void SetTopMost()
|
||||
|
||||
@@ -16,10 +16,12 @@ namespace ColorPicker.Mouse
|
||||
// position and bool indicating zoom in or zoom out
|
||||
event EventHandler<Tuple<System.Windows.Point, bool>> OnMouseWheel;
|
||||
|
||||
event MouseUpEventHandler OnMouseDown;
|
||||
event PrimaryMouseDownEventHandler OnPrimaryMouseDown;
|
||||
|
||||
event SecondaryMouseUpEventHandler OnSecondaryMouseUp;
|
||||
|
||||
event MiddleMouseDownEventHandler OnMiddleMouseDown;
|
||||
|
||||
System.Windows.Point CurrentPosition { get; }
|
||||
|
||||
Color CurrentColor { get; }
|
||||
|
||||
@@ -7,17 +7,18 @@ using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Input;
|
||||
|
||||
using ColorPicker.Helpers;
|
||||
using ManagedCommon;
|
||||
|
||||
using static ColorPicker.NativeMethods;
|
||||
|
||||
namespace ColorPicker.Mouse
|
||||
{
|
||||
public delegate void MouseUpEventHandler(object sender, System.Drawing.Point p);
|
||||
public delegate void PrimaryMouseDownEventHandler(object sender, IntPtr wParam);
|
||||
|
||||
public delegate void SecondaryMouseUpEventHandler(object sender, IntPtr wParam);
|
||||
|
||||
public delegate void MiddleMouseDownEventHandler(object sender, IntPtr wParam);
|
||||
|
||||
internal class MouseHook
|
||||
{
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
|
||||
@@ -30,23 +31,25 @@ namespace ColorPicker.Mouse
|
||||
private const int WM_RBUTTONUP = 0x0205;
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
|
||||
private const int WM_RBUTTONDOWN = 0x0204;
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop object")]
|
||||
private const int WM_MBUTTONDOWN = 0x0207;
|
||||
|
||||
private IntPtr _mouseHookHandle;
|
||||
private HookProc _mouseDelegate;
|
||||
|
||||
private event MouseUpEventHandler MouseDown;
|
||||
private event PrimaryMouseDownEventHandler PrimaryMouseDown;
|
||||
|
||||
public event MouseUpEventHandler OnMouseDown
|
||||
public event PrimaryMouseDownEventHandler OnPrimaryMouseDown
|
||||
{
|
||||
add
|
||||
{
|
||||
Subscribe();
|
||||
MouseDown += value;
|
||||
PrimaryMouseDown += value;
|
||||
}
|
||||
|
||||
remove
|
||||
{
|
||||
MouseDown -= value;
|
||||
PrimaryMouseDown -= value;
|
||||
Unsubscribe();
|
||||
}
|
||||
}
|
||||
@@ -68,6 +71,23 @@ namespace ColorPicker.Mouse
|
||||
}
|
||||
}
|
||||
|
||||
private event MiddleMouseDownEventHandler MiddleMouseDown;
|
||||
|
||||
public event MiddleMouseDownEventHandler OnMiddleMouseDown
|
||||
{
|
||||
add
|
||||
{
|
||||
Subscribe();
|
||||
MiddleMouseDown += value;
|
||||
}
|
||||
|
||||
remove
|
||||
{
|
||||
MiddleMouseDown -= value;
|
||||
Unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
private event MouseWheelEventHandler MouseWheel;
|
||||
|
||||
public event MouseWheelEventHandler OnMouseWheel
|
||||
@@ -126,9 +146,9 @@ namespace ColorPicker.Mouse
|
||||
MSLLHOOKSTRUCT mouseHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
|
||||
if (wParam.ToInt32() == WM_LBUTTONDOWN)
|
||||
{
|
||||
if (MouseDown != null)
|
||||
if (PrimaryMouseDown != null)
|
||||
{
|
||||
MouseDown.Invoke(null, new System.Drawing.Point(mouseHookStruct.pt.x, mouseHookStruct.pt.y));
|
||||
PrimaryMouseDown.Invoke(null, wParam);
|
||||
}
|
||||
|
||||
return new IntPtr(-1);
|
||||
@@ -150,6 +170,16 @@ namespace ColorPicker.Mouse
|
||||
return new IntPtr(-1);
|
||||
}
|
||||
|
||||
if (wParam.ToInt32() == WM_MBUTTONDOWN)
|
||||
{
|
||||
if (MiddleMouseDown != null)
|
||||
{
|
||||
MiddleMouseDown.Invoke(null, wParam);
|
||||
}
|
||||
|
||||
return new IntPtr(-1);
|
||||
}
|
||||
|
||||
if (wParam.ToInt32() == WM_MOUSEWHEEL)
|
||||
{
|
||||
if (MouseWheel != null)
|
||||
|
||||
@@ -56,10 +56,12 @@ namespace ColorPicker.Mouse
|
||||
|
||||
public event EventHandler<Tuple<System.Windows.Point, bool>> OnMouseWheel;
|
||||
|
||||
public event MouseUpEventHandler OnMouseDown;
|
||||
public event PrimaryMouseDownEventHandler OnPrimaryMouseDown;
|
||||
|
||||
public event SecondaryMouseUpEventHandler OnSecondaryMouseUp;
|
||||
|
||||
public event MiddleMouseDownEventHandler OnMiddleMouseDown;
|
||||
|
||||
public System.Windows.Point CurrentPosition
|
||||
{
|
||||
get
|
||||
@@ -148,9 +150,10 @@ namespace ColorPicker.Mouse
|
||||
_timer.Start();
|
||||
}
|
||||
|
||||
_mouseHook.OnMouseDown += MouseHook_OnMouseDown;
|
||||
_mouseHook.OnPrimaryMouseDown += MouseHook_OnPrimaryMouseDown;
|
||||
_mouseHook.OnMouseWheel += MouseHook_OnMouseWheel;
|
||||
_mouseHook.OnSecondaryMouseUp += MouseHook_OnSecondaryMouseUp;
|
||||
_mouseHook.OnMiddleMouseDown += MouseHook_OnMiddleMouseDown;
|
||||
|
||||
if (_userSettings.ChangeCursor.Value)
|
||||
{
|
||||
@@ -169,10 +172,10 @@ namespace ColorPicker.Mouse
|
||||
OnMouseWheel?.Invoke(this, new Tuple<System.Windows.Point, bool>(_previousMousePosition, zoomIn));
|
||||
}
|
||||
|
||||
private void MouseHook_OnMouseDown(object sender, Point p)
|
||||
private void MouseHook_OnPrimaryMouseDown(object sender, IntPtr wParam)
|
||||
{
|
||||
DisposeHook();
|
||||
OnMouseDown?.Invoke(this, p);
|
||||
OnPrimaryMouseDown?.Invoke(this, wParam);
|
||||
}
|
||||
|
||||
private void MouseHook_OnSecondaryMouseUp(object sender, IntPtr wParam)
|
||||
@@ -181,6 +184,12 @@ namespace ColorPicker.Mouse
|
||||
OnSecondaryMouseUp?.Invoke(this, wParam);
|
||||
}
|
||||
|
||||
private void MouseHook_OnMiddleMouseDown(object sender, IntPtr wParam)
|
||||
{
|
||||
DisposeHook();
|
||||
OnMiddleMouseDown?.Invoke(this, wParam);
|
||||
}
|
||||
|
||||
private void CopiedColorRepresentation_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
_colorFormatChanged = true;
|
||||
@@ -194,9 +203,10 @@ namespace ColorPicker.Mouse
|
||||
}
|
||||
|
||||
_previousMousePosition = new System.Windows.Point(-1, 1);
|
||||
_mouseHook.OnMouseDown -= MouseHook_OnMouseDown;
|
||||
_mouseHook.OnPrimaryMouseDown -= MouseHook_OnPrimaryMouseDown;
|
||||
_mouseHook.OnMouseWheel -= MouseHook_OnMouseWheel;
|
||||
_mouseHook.OnSecondaryMouseUp -= MouseHook_OnSecondaryMouseUp;
|
||||
_mouseHook.OnMiddleMouseDown -= MouseHook_OnMiddleMouseDown;
|
||||
|
||||
if (_userSettings.ChangeCursor.Value)
|
||||
{
|
||||
|
||||
@@ -21,6 +21,12 @@ namespace ColorPicker.Settings
|
||||
|
||||
SettingItem<ColorPickerActivationAction> ActivationAction { get; }
|
||||
|
||||
SettingItem<ColorPickerClickAction> PrimaryClickAction { get; }
|
||||
|
||||
SettingItem<ColorPickerClickAction> MiddleClickAction { get; }
|
||||
|
||||
SettingItem<ColorPickerClickAction> SecondaryClickAction { get; }
|
||||
|
||||
RangeObservableCollection<string> ColorHistory { get; }
|
||||
|
||||
SettingItem<int> ColorHistoryLimit { get; }
|
||||
|
||||
@@ -49,7 +49,10 @@ namespace ColorPicker.Settings
|
||||
ChangeCursor = new SettingItem<bool>(true);
|
||||
ActivationShortcut = new SettingItem<string>(DefaultActivationShortcut);
|
||||
CopiedColorRepresentation = new SettingItem<string>(ColorRepresentationType.HEX.ToString());
|
||||
ActivationAction = new SettingItem<ColorPickerActivationAction>(ColorPickerActivationAction.OpenEditor);
|
||||
ActivationAction = new SettingItem<ColorPickerActivationAction>(ColorPickerActivationAction.OpenColorPicker);
|
||||
PrimaryClickAction = new SettingItem<ColorPickerClickAction>(ColorPickerClickAction.PickColorThenEditor);
|
||||
MiddleClickAction = new SettingItem<ColorPickerClickAction>(ColorPickerClickAction.PickColorAndClose);
|
||||
SecondaryClickAction = new SettingItem<ColorPickerClickAction>(ColorPickerClickAction.Close);
|
||||
ColorHistoryLimit = new SettingItem<int>(20);
|
||||
ColorHistory.CollectionChanged += ColorHistory_CollectionChanged;
|
||||
ShowColorName = new SettingItem<bool>(false);
|
||||
@@ -78,6 +81,12 @@ namespace ColorPicker.Settings
|
||||
|
||||
public SettingItem<ColorPickerActivationAction> ActivationAction { get; private set; }
|
||||
|
||||
public SettingItem<ColorPickerClickAction> PrimaryClickAction { get; private set; }
|
||||
|
||||
public SettingItem<ColorPickerClickAction> MiddleClickAction { get; private set; }
|
||||
|
||||
public SettingItem<ColorPickerClickAction> SecondaryClickAction { get; private set; }
|
||||
|
||||
public RangeObservableCollection<string> ColorHistory { get; private set; } = new RangeObservableCollection<string>();
|
||||
|
||||
public SettingItem<int> ColorHistoryLimit { get; }
|
||||
@@ -121,6 +130,9 @@ namespace ColorPicker.Settings
|
||||
CopiedColorRepresentation.Value = settings.Properties.CopiedColorRepresentation;
|
||||
CopiedColorRepresentationFormat = new SettingItem<string>(string.Empty);
|
||||
ActivationAction.Value = settings.Properties.ActivationAction;
|
||||
PrimaryClickAction.Value = settings.Properties.PrimaryClickAction;
|
||||
MiddleClickAction.Value = settings.Properties.MiddleClickAction;
|
||||
SecondaryClickAction.Value = settings.Properties.SecondaryClickAction;
|
||||
ColorHistoryLimit.Value = settings.Properties.ColorHistoryLimit;
|
||||
ShowColorName.Value = settings.Properties.ShowColorName;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ using ColorPicker.Settings;
|
||||
using ColorPicker.ViewModelContracts;
|
||||
using Common.UI;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
|
||||
using PowerToys.Interop;
|
||||
|
||||
namespace ColorPicker.ViewModels
|
||||
@@ -79,9 +80,10 @@ namespace ColorPicker.ViewModels
|
||||
{
|
||||
SetColorDetails(mouseInfoProvider.CurrentColor);
|
||||
mouseInfoProvider.MouseColorChanged += Mouse_ColorChanged;
|
||||
mouseInfoProvider.OnMouseDown += MouseInfoProvider_OnMouseDown;
|
||||
mouseInfoProvider.OnPrimaryMouseDown += MouseInfoProvider_OnPrimaryMouseDown;
|
||||
mouseInfoProvider.OnMouseWheel += MouseInfoProvider_OnMouseWheel;
|
||||
mouseInfoProvider.OnSecondaryMouseUp += MouseInfoProvider_OnSecondaryMouseUp;
|
||||
mouseInfoProvider.OnMiddleMouseDown += MouseInfoProvider_OnMiddleMouseDown;
|
||||
}
|
||||
|
||||
_userSettings.ShowColorName.PropertyChanged += (s, e) => { OnPropertyChanged(nameof(ShowColorName)); };
|
||||
@@ -113,7 +115,7 @@ namespace ColorPicker.ViewModels
|
||||
|
||||
private void AppStateHandler_EnterPressed(object sender, EventArgs e)
|
||||
{
|
||||
MouseInfoProvider_OnMouseDown(null, default(System.Drawing.Point));
|
||||
MouseInfoProvider_OnPrimaryMouseDown(null, default);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -167,18 +169,50 @@ namespace ColorPicker.ViewModels
|
||||
SetColorDetails(color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tell the color picker that the user have press a mouse button (after release the button)
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of this event</param>
|
||||
/// <param name="p">The current <see cref="System.Drawing.Point"/> of the mouse cursor</param>
|
||||
private void MouseInfoProvider_OnMouseDown(object sender, System.Drawing.Point p)
|
||||
private void MouseInfoProvider_OnPrimaryMouseDown(object sender, IntPtr wParam)
|
||||
{
|
||||
ClipboardHelper.CopyToClipboard(ColorText);
|
||||
HandleMouseClickAction(_userSettings.PrimaryClickAction.Value);
|
||||
}
|
||||
|
||||
var color = GetColorString();
|
||||
private void MouseInfoProvider_OnMiddleMouseDown(object sender, IntPtr wParam)
|
||||
{
|
||||
HandleMouseClickAction(_userSettings.MiddleClickAction.Value);
|
||||
}
|
||||
|
||||
var oldIndex = _userSettings.ColorHistory.IndexOf(color);
|
||||
private void MouseInfoProvider_OnSecondaryMouseUp(object sender, IntPtr wParam)
|
||||
{
|
||||
HandleMouseClickAction(_userSettings.SecondaryClickAction.Value);
|
||||
}
|
||||
|
||||
private void HandleMouseClickAction(ColorPickerClickAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case ColorPickerClickAction.PickColorThenEditor:
|
||||
ClipboardHelper.CopyToClipboard(ColorText);
|
||||
UpdateColorHistory(GetColorString());
|
||||
|
||||
_appStateHandler.OpenColorEditor();
|
||||
|
||||
break;
|
||||
|
||||
case ColorPickerClickAction.PickColorAndClose:
|
||||
ClipboardHelper.CopyToClipboard(ColorText);
|
||||
UpdateColorHistory(GetColorString());
|
||||
|
||||
_appStateHandler.EndUserSession();
|
||||
|
||||
break;
|
||||
|
||||
case ColorPickerClickAction.Close:
|
||||
_appStateHandler.EndUserSession();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateColorHistory(string color)
|
||||
{
|
||||
int oldIndex = _userSettings.ColorHistory.IndexOf(color);
|
||||
if (oldIndex != -1)
|
||||
{
|
||||
_userSettings.ColorHistory.Move(oldIndex, 0);
|
||||
@@ -192,13 +226,6 @@ namespace ColorPicker.ViewModels
|
||||
{
|
||||
_userSettings.ColorHistory.RemoveAt(_userSettings.ColorHistory.Count - 1);
|
||||
}
|
||||
|
||||
_appStateHandler.OnColorPickerMouseDown();
|
||||
}
|
||||
|
||||
private void MouseInfoProvider_OnSecondaryMouseUp(object sender, IntPtr wParam)
|
||||
{
|
||||
_appStateHandler.EndUserSession();
|
||||
}
|
||||
|
||||
private string GetColorString()
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml;
|
||||
@@ -24,8 +23,8 @@ namespace Peek.FilePreviewer.Controls
|
||||
private static readonly COLORREF LightThemeBgColor = new(0x00f3f3f3);
|
||||
private static readonly COLORREF DarkThemeBgColor = new(0x00202020);
|
||||
|
||||
private static readonly HBRUSH LightThemeBgBrush = PInvoke.CreateSolidBrush(LightThemeBgColor);
|
||||
private static readonly HBRUSH DarkThemeBgBrush = PInvoke.CreateSolidBrush(DarkThemeBgColor);
|
||||
private static readonly HBRUSH LightThemeBgBrush = PInvoke_FilePreviewer.CreateSolidBrush(LightThemeBgColor);
|
||||
private static readonly HBRUSH DarkThemeBgBrush = PInvoke_FilePreviewer.CreateSolidBrush(DarkThemeBgColor);
|
||||
|
||||
[ObservableProperty]
|
||||
private IPreviewHandler? source;
|
||||
@@ -88,19 +87,19 @@ namespace Peek.FilePreviewer.Controls
|
||||
|
||||
if (HandlerVisibility == Visibility.Visible)
|
||||
{
|
||||
PInvoke.ShowWindow(containerHwnd, SHOW_WINDOW_CMD.SW_SHOW);
|
||||
PInvoke_FilePreviewer.ShowWindow(containerHwnd, SHOW_WINDOW_CMD.SW_SHOW);
|
||||
IsEnabled = true;
|
||||
|
||||
// Clears the background from the last previewer
|
||||
// The brush can only be drawn here because flashes will occur during resize
|
||||
PInvoke.SetClassLongPtr(containerHwnd, GET_CLASS_LONG_INDEX.GCLP_HBRBACKGROUND, containerBgBrush);
|
||||
PInvoke.UpdateWindow(containerHwnd);
|
||||
PInvoke.SetClassLongPtr(containerHwnd, GET_CLASS_LONG_INDEX.GCLP_HBRBACKGROUND, IntPtr.Zero);
|
||||
PInvoke.InvalidateRect(containerHwnd, (RECT*)null, true);
|
||||
PInvoke_FilePreviewer.SetClassLongPtr(containerHwnd, GET_CLASS_LONG_INDEX.GCLP_HBRBACKGROUND, containerBgBrush);
|
||||
PInvoke_FilePreviewer.UpdateWindow(containerHwnd);
|
||||
PInvoke_FilePreviewer.SetClassLongPtr(containerHwnd, GET_CLASS_LONG_INDEX.GCLP_HBRBACKGROUND, IntPtr.Zero);
|
||||
PInvoke_FilePreviewer.InvalidateRect(containerHwnd, (RECT*)null, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
PInvoke.ShowWindow(containerHwnd, SHOW_WINDOW_CMD.SW_HIDE);
|
||||
PInvoke_FilePreviewer.ShowWindow(containerHwnd, SHOW_WINDOW_CMD.SW_HIDE);
|
||||
IsEnabled = false;
|
||||
}
|
||||
}
|
||||
@@ -132,14 +131,14 @@ namespace Peek.FilePreviewer.Controls
|
||||
visuals.SetTextColor(fgColor);
|
||||
|
||||
// Changing the previewer colors might not always redraw itself
|
||||
PInvoke.InvalidateRect(containerHwnd, (RECT*)null, true);
|
||||
PInvoke_FilePreviewer.InvalidateRect(containerHwnd, (RECT*)null, true);
|
||||
}
|
||||
}
|
||||
|
||||
private LRESULT ContainerWndProc(HWND hWnd, uint msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
// Here for future use :)
|
||||
return PInvoke.DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
return PInvoke_FilePreviewer.DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
}
|
||||
|
||||
private void EnsureContainerHwndCreated()
|
||||
@@ -157,14 +156,14 @@ namespace Peek.FilePreviewer.Controls
|
||||
|
||||
fixed (char* pContainerClassName = "PeekShellPreviewHandlerContainer")
|
||||
{
|
||||
PInvoke.RegisterClass(new WNDCLASSW()
|
||||
PInvoke_FilePreviewer.RegisterClass(new WNDCLASSW()
|
||||
{
|
||||
lpfnWndProc = containerWndProc,
|
||||
lpszClassName = pContainerClassName,
|
||||
});
|
||||
|
||||
// Create the container window to host the preview handler
|
||||
containerHwnd = PInvoke.CreateWindowEx(
|
||||
containerHwnd = PInvoke_FilePreviewer.CreateWindowEx(
|
||||
WINDOW_EX_STYLE.WS_EX_LAYERED,
|
||||
pContainerClassName,
|
||||
null,
|
||||
@@ -178,7 +177,7 @@ namespace Peek.FilePreviewer.Controls
|
||||
HINSTANCE.Null);
|
||||
|
||||
// Allows the preview handlers to display properly
|
||||
PInvoke.SetLayeredWindowAttributes(containerHwnd, default, byte.MaxValue, LAYERED_WINDOW_ATTRIBUTES_FLAGS.LWA_ALPHA);
|
||||
PInvoke_FilePreviewer.SetLayeredWindowAttributes(containerHwnd, default, byte.MaxValue, LAYERED_WINDOW_ATTRIBUTES_FLAGS.LWA_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,12 +185,12 @@ namespace Peek.FilePreviewer.Controls
|
||||
{
|
||||
EnsureContainerHwndCreated();
|
||||
|
||||
var dpi = (float)PInvoke.GetDpiForWindow(containerHwnd) / 96;
|
||||
var dpi = (float)PInvoke_FilePreviewer.GetDpiForWindow(containerHwnd) / 96;
|
||||
|
||||
// Resize the container window
|
||||
PInvoke.SetWindowPos(
|
||||
PInvoke_FilePreviewer.SetWindowPos(
|
||||
containerHwnd,
|
||||
(HWND)0, // HWND_TOP
|
||||
(HWND)(nint)0, // HWND_TOP
|
||||
(int)(Math.Abs(args.EffectiveViewport.X) * dpi),
|
||||
(int)(Math.Abs(args.EffectiveViewport.Y) * dpi),
|
||||
(int)(ActualWidth * dpi),
|
||||
@@ -210,7 +209,7 @@ namespace Peek.FilePreviewer.Controls
|
||||
}
|
||||
|
||||
// Resizing the previewer might not always redraw itself
|
||||
PInvoke.InvalidateRect(containerHwnd, (RECT*)null, false);
|
||||
PInvoke_FilePreviewer.InvalidateRect(containerHwnd, (RECT*)null, false);
|
||||
}
|
||||
|
||||
private void UserControl_GotFocus(object sender, RoutedEventArgs e)
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{StaticResource TextFillColorSecondaryBrush}"
|
||||
Visibility="{x:Bind IsWarningMessageVisible(VideoPreviewer.MissingCodecName), Mode=OneWay}">
|
||||
Visibility="{x:Bind IsWarningMessageVisible(VideoPreviewer, Previewer.State), Mode=OneWay}">
|
||||
<Paragraph>
|
||||
<Run Text="{x:Bind GetWarningMessage(VideoPreviewer.MissingCodecName), Mode=OneWay}" />
|
||||
<Hyperlink Click="CodecSearchHyperlink_Click">
|
||||
|
||||
@@ -150,9 +150,9 @@ namespace Peek.FilePreviewer
|
||||
return isValidPreview ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
public Visibility IsWarningMessageVisible(string? missingCodecName)
|
||||
public Visibility IsWarningMessageVisible(IPreviewer? previewer, PreviewState? state)
|
||||
{
|
||||
var shouldShow = !string.IsNullOrEmpty(missingCodecName);
|
||||
var shouldShow = previewer is IVideoPreviewer videoPreviewer && MatchPreviewState(state, PreviewState.Loaded) && !string.IsNullOrEmpty(videoPreviewer.MissingCodecName);
|
||||
|
||||
return shouldShow ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "https://aka.ms/CsWin32.schema.json",
|
||||
"public": false
|
||||
"$schema": "https://aka.ms/CsWin32.schema.json",
|
||||
"public": false,
|
||||
"className": "PInvoke_FilePreviewer"
|
||||
}
|
||||
@@ -53,9 +53,9 @@ namespace Peek.FilePreviewer.Previewers.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
public void Seek(long dlibMove, STREAM_SEEK dwOrigin, [Optional] ulong* plibNewPosition)
|
||||
public void Seek(long dlibMove, SeekOrigin dwOrigin, [Optional] ulong* plibNewPosition)
|
||||
{
|
||||
long position = Stream.Seek(dlibMove, (SeekOrigin)dwOrigin);
|
||||
long position = Stream.Seek(dlibMove, dwOrigin);
|
||||
if (plibNewPosition != null)
|
||||
{
|
||||
*plibNewPosition = (ulong)position;
|
||||
@@ -82,7 +82,7 @@ namespace Peek.FilePreviewer.Previewers.Helpers
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void LockRegion(ulong libOffset, ulong cb, uint dwLockType)
|
||||
public void LockRegion(ulong libOffset, ulong cb, LOCKTYPE dwLockType)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
@@ -92,7 +92,7 @@ namespace Peek.FilePreviewer.Previewers.Helpers
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public void Stat(STATSTG* pstatstg, uint grfStatFlag)
|
||||
public void Stat(STATSTG* pstatstg, STATFLAG grfStatFlag)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ namespace Peek.FilePreviewer.Previewers
|
||||
// TODO: Figure out how to get it to run in a low integrity level
|
||||
if (!HandlerFactories.TryGetValue(clsid, out var factory))
|
||||
{
|
||||
var hr = PInvoke.CoGetClassObject(clsid, CLSCTX.CLSCTX_LOCAL_SERVER, null, typeof(IClassFactory).GUID, out var pFactory);
|
||||
var hr = PInvoke_FilePreviewer.CoGetClassObject(clsid, CLSCTX.CLSCTX_LOCAL_SERVER, null, typeof(IClassFactory).GUID, out var pFactory);
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
|
||||
// Storing the factory in memory helps makes the handlers load faster
|
||||
@@ -149,7 +149,7 @@ namespace Peek.FilePreviewer.Previewers
|
||||
}
|
||||
else if (previewHandler is IInitializeWithItem initWithItem)
|
||||
{
|
||||
var hr = PInvoke.SHCreateItemFromParsingName(FileItem.Path, null, typeof(IShellItem).GUID, out var item);
|
||||
var hr = PInvoke_FilePreviewer.SHCreateItemFromParsingName(FileItem.Path, null, typeof(IShellItem).GUID, out var item);
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
|
||||
initWithItem.Initialize((IShellItem)item, STGM_READ);
|
||||
|
||||
@@ -48,21 +48,21 @@ namespace Peek.UI.Extensions
|
||||
|
||||
internal static HWND FindChildWindow(this HWND windowHandle, string className)
|
||||
{
|
||||
return PInvoke.FindWindowEx(windowHandle, HWND.Null, className, null);
|
||||
return PInvoke_PeekUI.FindWindowEx(windowHandle, HWND.Null, className, null);
|
||||
}
|
||||
|
||||
internal static Size GetMonitorSize(this HWND hwnd)
|
||||
{
|
||||
var monitor = PInvoke.MonitorFromWindow(hwnd, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);
|
||||
var monitor = PInvoke_PeekUI.MonitorFromWindow(hwnd, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFO info = default(MONITORINFO);
|
||||
info.cbSize = 40;
|
||||
PInvoke.GetMonitorInfo(monitor, ref info);
|
||||
PInvoke_PeekUI.GetMonitorInfo(monitor, ref info);
|
||||
return new Size(info.rcMonitor.Size.Width, info.rcMonitor.Size.Height);
|
||||
}
|
||||
|
||||
internal static double GetMonitorScale(this HWND hwnd)
|
||||
{
|
||||
var dpi = PInvoke.GetDpiForWindow(hwnd);
|
||||
var dpi = PInvoke_PeekUI.GetDpiForWindow(hwnd);
|
||||
var scalingFactor = dpi / 96d;
|
||||
return scalingFactor;
|
||||
}
|
||||
|
||||
@@ -28,12 +28,12 @@ namespace Peek.UI.Extensions
|
||||
|
||||
// If the window is maximized, restore to normal state before change its size
|
||||
var placement = default(WINDOWPLACEMENT);
|
||||
if (PInvoke.GetWindowPlacement(hwndToCenter, ref placement))
|
||||
if (PInvoke_PeekUI.GetWindowPlacement(hwndToCenter, ref placement))
|
||||
{
|
||||
if (placement.showCmd == SHOW_WINDOW_CMD.SW_MAXIMIZE)
|
||||
{
|
||||
placement.showCmd = SHOW_WINDOW_CMD.SW_SHOWNORMAL;
|
||||
if (!PInvoke.SetWindowPlacement(hwndToCenter, in placement))
|
||||
if (!PInvoke_PeekUI.SetWindowPlacement(hwndToCenter, in placement))
|
||||
{
|
||||
Logger.LogError($"SetWindowPlacement failed with error {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
@@ -44,12 +44,12 @@ namespace Peek.UI.Extensions
|
||||
Logger.LogError($"GetWindowPlacement failed with error {Marshal.GetLastWin32Error()}");
|
||||
}
|
||||
|
||||
var monitor = PInvoke.MonitorFromWindow(hwndDesktop, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);
|
||||
var monitor = PInvoke_PeekUI.MonitorFromWindow(hwndDesktop, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST);
|
||||
MONITORINFO info = default(MONITORINFO);
|
||||
info.cbSize = 40;
|
||||
PInvoke.GetMonitorInfo(monitor, ref info);
|
||||
var dpi = PInvoke.GetDpiForWindow(new HWND(hwndDesktop));
|
||||
PInvoke.GetWindowRect(hwndToCenter, out RECT windowRect);
|
||||
PInvoke_PeekUI.GetMonitorInfo(monitor, ref info);
|
||||
var dpi = PInvoke_PeekUI.GetDpiForWindow(new HWND((nint)hwndDesktop));
|
||||
PInvoke_PeekUI.GetWindowRect(hwndToCenter, out RECT windowRect);
|
||||
var scalingFactor = dpi / 96d;
|
||||
var w = width.HasValue ? (int)(width * scalingFactor) : windowRect.right - windowRect.left;
|
||||
var h = height.HasValue ? (int)(height * scalingFactor) : windowRect.bottom - windowRect.top;
|
||||
@@ -63,7 +63,7 @@ namespace Peek.UI.Extensions
|
||||
|
||||
private static void SetWindowPosOrThrow(HWND hWnd, HWND hWndInsertAfter, int x, int y, int cx, int cy, SET_WINDOW_POS_FLAGS uFlags)
|
||||
{
|
||||
bool result = PInvoke.SetWindowPos(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
|
||||
bool result = PInvoke_PeekUI.SetWindowPos(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
|
||||
if (!result)
|
||||
{
|
||||
Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace Peek.UI.Helpers
|
||||
object? oNull2 = null;
|
||||
|
||||
var serviceProvider = (IServiceProvider)shellWindows.FindWindowSW(ref oNull1, ref oNull2, SWC_DESKTOP, out int pHWND, SWFO_NEEDDISPATCH);
|
||||
var shellBrowser = (IShellBrowser)serviceProvider.QueryService(PInvoke.SID_STopLevelBrowser, typeof(IShellBrowser).GUID);
|
||||
var shellBrowser = (IShellBrowser)serviceProvider.QueryService(PInvoke_PeekUI.SID_STopLevelBrowser, typeof(IShellBrowser).GUID);
|
||||
|
||||
IShellItemArray? shellItemArray = GetShellItemArray(shellBrowser, onlySelectedFiles);
|
||||
return shellItemArray;
|
||||
@@ -81,7 +81,7 @@ namespace Peek.UI.Helpers
|
||||
if (webBrowserApp.HWND == foregroundWindowHandle)
|
||||
{
|
||||
var serviceProvider = (IServiceProvider)webBrowserApp;
|
||||
var shellBrowser = (IShellBrowser)serviceProvider.QueryService(PInvoke.SID_STopLevelBrowser, typeof(IShellBrowser).GUID);
|
||||
var shellBrowser = (IShellBrowser)serviceProvider.QueryService(PInvoke_PeekUI.SID_STopLevelBrowser, typeof(IShellBrowser).GUID);
|
||||
shellBrowser.GetWindow(out IntPtr shellBrowserHandle);
|
||||
|
||||
if (activeTab == shellBrowserHandle)
|
||||
@@ -122,7 +122,7 @@ namespace Peek.UI.Helpers
|
||||
GUITHREADINFO guiThreadInfo = new() { cbSize = (uint)Marshal.SizeOf<GUITHREADINFO>() };
|
||||
|
||||
// Get information for the foreground thread
|
||||
if (PInvoke.GetGUIThreadInfo(0, ref guiThreadInfo))
|
||||
if (PInvoke_PeekUI.GetGUIThreadInfo(0, ref guiThreadInfo))
|
||||
{
|
||||
return guiThreadInfo.hwndActive == hwnd && (guiThreadInfo.flags & GUITHREADINFO_FLAGS.GUI_CARETBLINKING) != 0;
|
||||
}
|
||||
|
||||
5
src/modules/peek/Peek.UI/NativeMethods.json
Normal file
5
src/modules/peek/Peek.UI/NativeMethods.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"$schema": "https://aka.ms/CsWin32.schema.json",
|
||||
"public": false,
|
||||
"className": "PInvoke_PeekUI"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user