Compare commits

..

12 commits

Author SHA1 Message Date
Clint Rutkas cae7c7c897
Update release.yml 2021-11-24 14:57:17 -08:00
Clint Rutkas fa4b64e59a
Update release.yml 2021-11-24 14:55:19 -08:00
Clint Rutkas 7234f9028d Update release.yml for Azure Pipelines 2021-11-24 14:12:29 -08:00
Clint Rutkas 036c9ed36b
Update release.yml 2021-11-24 14:10:11 -08:00
Clint Rutkas 643735fa76
Update release.yml 2021-11-24 14:08:37 -08:00
Dustin Howett 09deb8cbc8 What if we don't do package ES... 2021-11-23 17:30:03 -06:00
Dustin Howett e733edd02e Try to use the right feed, scrub 2021-11-23 16:24:57 -06:00
Clint Rutkas 0c3654ca30
Update release.yml 2021-11-23 13:51:26 -08:00
Clint Rutkas 711dc7d8a4
Create release.yml 2021-11-23 11:44:07 -08:00
Clint Rutkas 2c3fec6a30 forcing internal 2021-11-12 13:10:45 -08:00
Clint Rutkas 27e61eb70b adding in direct installer yml 2021-11-12 13:07:34 -08:00
Clint Rutkas 6e90166b69 lets move unneeded stuff out 2021-11-12 13:05:26 -08:00
123 changed files with 1518 additions and 3449 deletions

View file

@ -699,7 +699,6 @@ gdi
gdiplus
GDISCALED
generatesqlfromuserquery
GETDESKWALLPAPER
GETDISPINFO
GETDLGCODE
GETDPISCALEDSIZE
@ -763,10 +762,8 @@ hglobal
hhk
HHmmss
HHOOK
hhx
HICON
HIDEWINDOW
highlighter
HIMAGELIST
himl
hinst
@ -790,7 +787,7 @@ hmonitor
HOLDENTER
HOLDESC
homljgmgpmcbpjbnjpfijnhipfkiclkd
homepage
Homepage
HOOKPROC
hostname
hotkeycontrol
@ -2086,7 +2083,6 @@ Switchbetweenvirtualdesktops
SWP
swprintf
SWRESTORE
swscanf
SYMED
SYMOPT
SYNCMFT
@ -2338,7 +2334,7 @@ VTABLE
Vtbl
wav
WBounds
wca
Wca
wcautil
WCE
wcex

View file

@ -0,0 +1,20 @@
parameters:
configuration: 'Release'
platform: ''
additionalBuildArguments: '-m'
jobs:
- job: Build${{ parameters.platform }}${{ parameters.configuration }}
displayName: Build ${{ parameters.platform }} ${{ parameters.configuration }}
variables:
BuildConfiguration: ${{ parameters.configuration }}
BuildPlatform: ${{ parameters.platform }}
pool:
name: WinDevPool-L
timeoutInMinutes: 120
strategy:
maxParallel: 10
steps:
- template: build-powertoys-steps.yml
parameters:
additionalBuildArguments: ${{ parameters.additionalBuildArguments }}

View file

@ -138,24 +138,24 @@ build:
- 'modules\launcher\Microsoft.Launcher.dll'
- 'modules\launcher\Plugins\Calculator\Microsoft.PowerToys.Run.Plugin.Calculator.dll'
- 'modules\launcher\Plugins\Calculator\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Folder\Microsoft.Plugin.Folder.dll'
- 'modules\launcher\Plugins\Folder\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Indexer\Microsoft.Plugin.Indexer.dll'
- 'modules\launcher\Plugins\Indexer\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Program\Microsoft.Plugin.Program.dll'
- 'modules\launcher\Plugins\Program\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Registry\Microsoft.PowerToys.Run.Plugin.Registry.dll'
- 'modules\launcher\Plugins\Registry\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\WindowsSettings\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll'
- 'modules\launcher\Plugins\WindowsSettings\WindowsSettings.json'
- 'modules\launcher\Plugins\Shell\Microsoft.Plugin.Shell.dll'
- 'modules\launcher\Plugins\Shell\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Uri\Microsoft.Plugin.Uri.dll'
- 'modules\launcher\Plugins\Uri\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\WindowWalker\Microsoft.Plugin.WindowWalker.dll'
- 'modules\launcher\Plugins\WindowWalker\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\UnitConverter\Community.PowerToys.Run.Plugin.UnitConverter.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Folder\Microsoft.Plugin.Folder.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Folder\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Indexer\Microsoft.Plugin.Indexer.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Indexer\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Program\Microsoft.Plugin.Program.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Program\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\Microsoft.PowerToys.Run.Plugin.Registry.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll'
- 'modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\WindowsSettings.json'
- 'modules\launcher\Plugins\Microsoft.Plugin.Shell\Microsoft.Plugin.Shell.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Shell\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Uri\Microsoft.Plugin.Uri.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.Uri\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\Microsoft.Plugin.WindowWalker.dll'
- 'modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\ManagedTelemetry.dll'
- 'modules\launcher\Plugins\Community.UnitConverter\Community.PowerToys.Run.Plugin.UnitConverter.dll'
- 'modules\launcher\Plugins\VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.dll'
- 'modules\launcher\Plugins\Service\Microsoft.PowerToys.Run.Plugin.Service.dll'
- 'modules\launcher\Plugins\System\Microsoft.PowerToys.Run.Plugin.System.dll'
@ -171,7 +171,6 @@ build:
- 'modules\launcher\Wox.Infrastructure.dll'
- 'modules\launcher\Wox.Plugin.dll'
- 'modules\MouseUtils\FindMyMouse.dll'
- 'modules\MouseUtils\MouseHighlighter.dll'
- 'modules\PowerRename\PowerRenameExt.dll'
- 'modules\PowerRename\PowerRenameUILib.dll'
- 'modules\PowerRename\PowerRename.exe'
@ -255,7 +254,6 @@ static_analysis_options:
exclude:
- 'WiX.*/**/*.dll'
- 'Wix.*/**/*.exe'
- 'Microsoft.Windows.CppWinRT.*/**/*.exe'
moderncop_options:
files_to_scan:
- from: 'src'

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="PowerToysCDPX_Feed" value="https://github-private.pkgs.visualstudio.com/microsoft/_packaging/PowerToysCDPX_Feed/nuget/v3/index.json" />
</packageSources>
<disabledPackageSources>
<clear />
</disabledPackageSources>
</configuration>

187
.pipelines/release.yml Normal file
View file

@ -0,0 +1,187 @@
# This build should never run as CI or against a pull request.
trigger: none
pr: none
pool:
name: WinDevPool-L
demands: ImageOverride -equals WinDevVS16-latest
parameters:
- name: buildConfigurations
type: object
default:
- Release
- name: buildPlatforms
type: object
default:
- x64
name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
resources:
repositories:
- repository: self
type: git
ref: main
jobs:
- job: Build
strategy:
matrix:
${{ each config in parameters.buildConfigurations }}:
${{ each platform in parameters.buildPlatforms }}:
${{ config }}_${{ platform }}:
BuildConfiguration: ${{ config }}
BuildPlatform: ${{ platform }}
displayName: Build
cancelTimeoutInMinutes: 1
steps:
- checkout: self
clean: true
submodules: true
persistCredentials: True
# - task: PkgESSetupBuild@12
# displayName: Package ES - Setup Build
# inputs:
# disableOutputRedirect: true
- task: NuGetToolInstaller@1
displayName: Use NuGet 5.10
inputs:
versionSpec: 5.10
- task: NuGetAuthenticate@0
inputs:
nuGetServiceConnections: PowerToysCDPxFeed
# we may need to do this one by one based on the cmd files for restoring.
- task: NuGetCommand@2
displayName: NuGet restore solutions dependencies
inputs:
command: restore
restoreSolution: '**/*.sln'
selectOrConfig: config
nugetConfigPath: .pipelines/release-nuget.config
- task: CmdLine@2
displayName: Moving telem files over
inputs:
script: |
call nuget.exe restore -PackagesDirectory . packages.config || exit /b 1
move /Y "Microsoft.PowerToys.Telemetry.2.0.0\build\include\TraceLoggingDefines.h" "..\src\common\Telemetry\TraceLoggingDefines.h" || exit /b 1
move /Y "Microsoft.PowerToys.Telemetry.2.0.0\build\include\TelemetryBase.cs" "..\src\common\Telemetry\TelemetryBase.cs" || exit /b 1
# - task: TouchdownBuildTask@1
# displayName: Download Localization Files
# inputs:
# teamId: 7105
# authId: $(TouchdownAppId)
# authKey: $(TouchdownAppKey)
# resourceFilePath: >-
# src\cascadia\TerminalApp\Resources\en-US\Resources.resw
#
# src\cascadia\TerminalControl\Resources\en-US\Resources.resw
#
# src\cascadia\TerminalConnection\Resources\en-US\Resources.resw
#
# src\cascadia\TerminalSettingsModel\Resources\en-US\Resources.resw
#
# src\cascadia\TerminalSettingsEditor\Resources\en-US\Resources.resw
#
# src\cascadia\WindowsTerminalUniversal\Resources\en-US\Resources.resw
#
# src\cascadia\CascadiaPackage\Resources\en-US\Resources.resw
# appendRelativeDir: true
# localizationTarget: false
# pseudoSetting: Included
# - task: PowerShell@2
# displayName: Move Loc files one level up
# inputs:
# targetType: inline
# script: >-
# $Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw'
#
# $Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore }
# pwsh: true
- task: VSBuild@1
displayName: Build solution **\PowerToys.sln
inputs:
solution: '**\PowerToys.sln'
vsVersion: 16.0
msbuildArgs: /p:CIBuild=true /bl:$(Build.SourcesDirectory)\msbuild.binlog
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
clean: true
maximumCpuCount: true
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: binlog'
condition: failed()
continueOnError: True
inputs:
PathtoPublish: $(Build.SourcesDirectory)\msbuild.binlog
ArtifactName: binlog-$(BuildPlatform)
- task: ComponentGovernanceComponentDetection@0
displayName: Component Detection
- task: CopyFiles@2
displayName: Copy *.appx/*.msix to Artifacts
inputs: # general format for how to publish artifacts -- move to below your build/sign rules
Contents: >-
**/*.appx
**/*.msix
**/*.appxsym
!**/Microsoft.VCLibs*.appx
TargetFolder: $(Build.ArtifactStagingDirectory)/appx
OverWrite: true
flattenFolders: true
- task: PublishBuildArtifacts@1
displayName: TERMINAL LEGACY - Publish Artifact (appx)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/appx
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)
- task: PublishSymbols@2
displayName: Publish symbols path
continueOnError: True
inputs:
SearchPattern: '**/*.pdb'
IndexSources: false
SymbolServerType: TeamServices
- task: EsrpCodeSigning@1
displayName: USE AS BASE BUT TERMINAL CODE - Submit *.msixbundle to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(System.ArtifactsDirectory)
Pattern: Microsoft.WindowsTerminal*.msixbundle
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "Dynamic",
"CertTemplateName": "WINMSAPP1ST",
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
"OperationCode": "SigntoolSign",
"Parameters": {
"OpusName": "Microsoft",
"OpusInfo": "http://www.microsoft.com",
"FileDigest": "/fd \"SHA256\"",
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "Dynamic",
"CertTemplateName": "WINMSAPP1ST",
"CertSubjectName": "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US",
"OperationCode": "SigntoolVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- task: PublishBuildArtifacts@1
displayName: 'TERMINAL LEGACY - Publish Artifact: appxbundle-signed'
inputs:
PathtoPublish: $(System.ArtifactsDirectory)
ArtifactName: appxbundle-signed
...

View file

@ -262,7 +262,6 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643-4663-475E-B329-03F0C9918D48}"
ProjectSection(SolutionItems) = preProject
src\common\utils\appMutex.h = src\common\utils\appMutex.h
src\common\utils\color.h = src\common\utils\color.h
src\common\utils\com_object_factory.h = src\common\utils\com_object_factory.h
src\common\utils\elevation.h = src\common\utils\elevation.h
src\common\utils\EventLocker.h = src\common\utils\EventLocker.h
@ -372,8 +371,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "MouseUtils", "MouseUtils",
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FindMyMouse", "src\modules\MouseUtils\FindMyMouse\FindMyMouse.vcxproj", "{E94FD11C-0591-456F-899F-EFC0CA548336}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MouseHighlighter", "src\modules\MouseUtils\MouseHighlighter\MouseHighlighter.vcxproj", "{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -989,12 +986,6 @@ Global
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.ActiveCfg = Release|x64
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x64.Build.0 = Release|x64
{E94FD11C-0591-456F-899F-EFC0CA548336}.Release|x86.ActiveCfg = Release|x64
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|x64.ActiveCfg = Debug|x64
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|x64.Build.0 = Debug|x64
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Debug|x86.ActiveCfg = Debug|x64
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|x64.ActiveCfg = Release|x64
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|x64.Build.0 = Release|x64
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88}.Release|x86.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1114,7 +1105,6 @@ Global
{4642D596-723F-4BFC-894C-46811219AC4A} = {89E20BCE-EB9C-46C8-8B50-E01A82E6FDC3}
{322566EF-20DC-43A6-B9F8-616AF942579A} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
{E94FD11C-0591-456F-899F-EFC0CA548336} = {322566EF-20DC-43A6-B9F8-616AF942579A}
{782A61BE-9D85-4081-B35C-1CCC9DCC1E88} = {322566EF-20DC-43A6-B9F8-616AF942579A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}

View file

@ -1,6 +1,6 @@
# Microsoft PowerToys
![Hero image for Microsoft PowerToys](doc/images/overview/PT_hero_image.png)
<img src="./doc/images/overview/PT%20hero%20image.png"/>
[How to use PowerToys][usingPowerToys-docs-link] | [Downloads & Release notes][github-release-link] | [Contributing to PowerToys](#contributing) | [What's Happening](#whats-happening) | [Roadmap](#powertoys-roadmap)

View file

@ -4,7 +4,7 @@
|----------|----------|
| getpowertoys | ms-windows-store://pdp/?productid=XP89DCGQ3K6VLD |
| installpowertoys | https://github.com/microsoft/PowerToys/releases/latest |
| powertoys-license | https://github.com/microsoft/PowerToys/blob/main/LICENSE |
| powertoys-license | https://github.com/microsoft/PowerToys/blob/master/LICENSE |
| powertoys | https://github.com/microsoft/PowerToys |
| PowerToysAppCompat | https://github.com/microsoft/PowerToys/wiki/Application-Compatibility |
| powerToysCannotRemapKeys | https://docs.microsoft.com/windows/powertoys/keyboard-manager#keys-that-cannot-be-remapped |

View file

@ -15,7 +15,7 @@ TODO
#### [`ZoneSet.cpp`](/src/modules/fancyzones/lib/ZoneSet.cpp)
TODO
#### [`WorkArea.cpp`](/src/modules/fancyzones/lib/WorkArea.cpp)
#### [`ZoneWindow.cpp`](/src/modules/fancyzones/lib/ZoneWindow.cpp)
TODO
## FancyZones Editor

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View file

Before

Width:  |  Height:  |  Size: 447 KiB

After

Width:  |  Height:  |  Size: 447 KiB

View file

@ -2,17 +2,17 @@
---
1. `Zone` - Class which is basically wrapper around rectangle structure, representing one zone inside applied zone layout. ZoneSet is holding array of these which represent zone layout.
2. `ZoneSet` - Class implementing actual zone layout applied. What this means is that ZoneSet is responsible for actual calculation of rectangle coordinates (whether is grid or canvas layout) and moving window through them. WorkArea holds ZoneSet structure which represents currently active zone set.
3. `WorkArea` - Class representing work area, which is defined by monitor and current virtual desktop. For an example, if You have two monitors connected and two virtual desktops, You have 4 work areas available, and each of them can have separate zone layout. WorkArea is describing single work area. As mentioned before it holds active ZoneSet.
2. `ZoneSet` - Class implementing actual zone layout applied. What this means is that ZoneSet is responsible for actual calculation of rectangle coordinates (whether is grid or canvas layout) and moving window through them. ZoneWindow holds ZoneSet structure which represents currently active zone set.
3. `ZoneWindow` - Class representing work area, which is defined by monitor and current virtual desktop. For an example, if You have two monitors connected and two virtual desktops, You have 4 work areas available, and each of them can have separate zone layout. ZoneWindow is describing single work area. As mentioned before it holds active ZoneSet.
4. `FancyZones` - Top level entity and entry point for all user actions (which goes through actual module interface). Some of the main responsibilities of FancyZones class:
1. Starting FancyZones Editor (C#) with appropriate command line arguments on user request.
2. Keeping track of WorkArea per monitor (currently active work area on each connected monitor).
2. Keeping track of ZoneWindow per monitor (currently active work area on each connected monitor).
3. Keeping track of active virtual desktops. This is performed in separate thread by polling VirtualDesktopIDs registry key and parsing its content.
4. Detecting every change in work environment, such as creating / destroying / switching between virtual desktops, closing FancyZones Editor, changing display settings and handling those changes.
### Proposal for modifications of handling described in 4.4:
Currently after each of the mentioned changes in work environment we are calling EnumDisplayMonitors windows API, and passing callback function to it. EnumDisplayMonitors works asynchronous and triggers that callback for each work area available (as mentioned in previous example, for two monitors and two virtual desktops, we have this callback triggered four times). As mentioned previously, we have WorkArea class as our representation of this work area. And what we do, every time this callback is triggered we destroy previous WorkArea object for that work area and create new one, even though that it is most likely that nothing has changed (e.g. just switching back and forth between virtual desktops). This constant creation and deletion of WorkArea has caused some problems in the past and it's not ideal for some other fixes we would like to make in the multi-monitor/multi-desktop scenario.
Currently after each of the mentioned changes in work environment we are calling EnumDisplayMonitors windows API, and passing callback function to it. EnumDisplayMonitors works asynchronous and triggers that callback for each work area available (as mentioned in previous example, for two monitors and two virtual desktops, we have this callback triggered four times). As mentioned previously, we have ZoneWindow class as our representation of this work area. And what we do, every time this callback is triggered we destroy previous ZoneWindow object for that work area and create new one, even though that it is most likely that nothing has changed (e.g. just switching back and forth between virtual desktops). This constant creation and deletion of ZoneWindow has caused some problems in the past and it's not ideal for some other fixes we would like to make in the multi-monitor/multi-desktop scenario.
As mentioned in 4.3 we already have tracker of virtual desktops implemented. Idea is to use this functionality and to extend it bit more, so we can track if work area (WorkArea) is new one, or already processed and skip creating new WorkArea objects and deleting old ones every time, even if nothing changed in it. We will keep map, where virtual desktop id is the key, and values are already processed monitors (virtual desktop exists across all monitors). Once we receive callback from EnumDisplayMonitors, indicating work area (defined by virtual desktop id and monitor) we can check if its new or not, and act accordingly (create new WorkArea for it or not). Deleting virtual desktop (which is also registered in 4.3), will trigger updates in this map, and also updates in our JSON storage.
As mentioned in 4.3 we already have tracker of virtual desktops implemented. Idea is to use this functionality and to extend it bit more, so we can track if work area (ZoneWindow) is new one, or already processed and skip creating new ZoneWindow objects and deleting old ones every time, even if nothing changed in it. We will keep map, where virtual desktop id is the key, and values are already processed monitors (virtual desktop exists across all monitors). Once we receive callback from EnumDisplayMonitors, indicating work area (defined by virtual desktop id and monitor) we can check if its new or not, and act accordingly (create new ZoneWindow for it or not). Deleting virtual desktop (which is also registered in 4.3), will trigger updates in this map, and also updates in our JSON storage.

View file

@ -316,27 +316,27 @@
<Directory Id="CalculatorImagesFolder" Name="Images" />
<Directory Id="CalculatorLanguagesFolder" Name="Languages" />
</Directory>
<Directory Id="FolderPluginFolder" Name="Folder">
<Directory Id="FolderPluginFolder" Name="Microsoft.Plugin.Folder">
<Directory Id="FolderPluginImagesFolder" Name="Images" />
<Directory Id="FolderPluginLanguagesFolder" Name="Languages" />
</Directory>
<Directory Id="ProgramPluginFolder" Name="Program">
<Directory Id="ProgramPluginFolder" Name="Microsoft.Plugin.Program">
<Directory Id="ProgramImagesFolder" Name="Images" />
<Directory Id="ProgramLanguagesFolder" Name="Languages" />
</Directory>
<Directory Id="ShellPluginFolder" Name="Shell">
<Directory Id="ShellPluginFolder" Name="Microsoft.Plugin.Shell">
<Directory Id="ShellImagesFolder" Name="Images" />
<Directory Id="ShellLanguagesFolder" Name="Languages" />
</Directory>
<Directory Id="IndexerPluginFolder" Name="Indexer">
<Directory Id="IndexerPluginFolder" Name="Microsoft.Plugin.Indexer">
<Directory Id="IndexerImagesFolder" Name="Images" />
<Directory Id="IndexerLanguagesFolder" Name="Languages" />
</Directory>
<Directory Id="UriPluginFolder" Name="Uri">
<Directory Id="UriPluginFolder" Name="Microsoft.Plugin.Uri">
<Directory Id="UriImagesFolder" Name="Images" />
<Directory Id="UriLanguagesFolder" Name="Languages" />
</Directory>
<Directory Id="UnitConverterPluginFolder" Name="UnitConverter">
<Directory Id="UnitConverterPluginFolder" Name="Community.UnitConverter">
<Directory Id="UnitConverterImagesFolder" Name="Images" />
<Directory Id="UnitConverterLanguagesFolder" Name="Languages" />
</Directory>
@ -344,11 +344,11 @@
<Directory Id="VSCodeWorkspaceImagesFolder" Name="Images" />
<Directory Id="VSCodeWorkspaceLanguagesFolder" Name="Languages" />
</Directory>
<Directory Id="WindowWalkerPluginFolder" Name="WindowWalker">
<Directory Id="WindowWalkerPluginFolder" Name="Microsoft.Plugin.WindowWalker">
<Directory Id="WindowWalkerImagesFolder" Name="Images" />
<Directory Id="WindowWalkerLanguagesFolder" Name="Languages" />
</Directory>
<Directory Id="RegistryPluginFolder" Name="Registry">
<Directory Id="RegistryPluginFolder" Name="Microsoft.PowerToys.Run.Plugin.Registry">
<Directory Id="RegistryImagesFolder" Name="Images" />
<Directory Id="RegistryLanguagesFolder" Name="Languages" />
</Directory>
@ -361,7 +361,7 @@
<Directory Id="SystemPluginFolder" Name="System">
<Directory Id="SystemImagesFolder" Name="Images" />
</Directory>
<Directory Id="WindowsSettingsPluginFolder" Name="WindowsSettings">
<Directory Id="WindowsSettingsPluginFolder" Name="Microsoft.PowerToys.Run.Plugin.WindowsSettings">
<Directory Id="WindowsSettingsImagesFolder" Name="Images" />
<Directory Id="WindowsSettingsLanguagesFolder" Name="Languages" />
</Directory>
@ -657,9 +657,6 @@
<Component Id="Module_FindMyMouse" Guid="60D0E4AE-188F-4403-BF06-1465AACC1BC5" Win64="yes">
<File Source="$(var.BinX64Dir)modules\$(var.MouseUtilsProjectName)\FindMyMouse.dll" KeyPath="yes" />
</Component>
<Component Id="Module_MouseHighlighter" Guid="3BAEA39F-A73D-48D2-9616-BBED5B8C86D3" Win64="yes">
<File Source="$(var.BinX64Dir)modules\$(var.MouseUtilsProjectName)\MouseHighlighter.dll" KeyPath="yes" />
</Component>
</DirectoryRef>
<!-- Shortcut guide -->
@ -974,7 +971,6 @@
<ComponentRef Id="Module_Awake_runtime_netcoreapp30"/>
<ComponentRef Id="Module_Awake_runtime_netcoreapp21"/>
<ComponentRef Id="Module_FindMyMouse"/>
<ComponentRef Id="Module_MouseHighlighter"/>
<ComponentRef Id="SettingsV2" />
<ComponentRef Id="SettingsV2Assets" />
<ComponentRef Id="SettingsV2AssetsModules" />
@ -1063,28 +1059,28 @@
<File Id="Launcher_Calculator_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Calculator\$(var.Language)\Microsoft.PowerToys.Run.Plugin.Calculator.resources.dll" />
</Component>
<Component Id="Launcher_Folder_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)FolderPluginFolder">
<File Id="Launcher_Folder_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Folder\$(var.Language)\Microsoft.Plugin.Folder.resources.dll" />
<File Id="Launcher_Folder_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Folder\$(var.Language)\Microsoft.Plugin.Folder.resources.dll" />
</Component>
<Component Id="Launcher_Program_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)ProgramPluginFolder">
<File Id="Launcher_Program_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Program\$(var.Language)\Microsoft.Plugin.Program.resources.dll" />
<File Id="Launcher_Program_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Program\$(var.Language)\Microsoft.Plugin.Program.resources.dll" />
</Component>
<Component Id="Launcher_Shell_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)ShellPluginFolder">
<File Id="Launcher_Shell_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Shell\$(var.Language)\Microsoft.Plugin.Shell.resources.dll" />
<File Id="Launcher_Shell_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Shell\$(var.Language)\Microsoft.Plugin.Shell.resources.dll" />
</Component>
<Component Id="Launcher_Indexer_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)IndexerPluginFolder">
<File Id="Launcher_Indexer_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Indexer\$(var.Language)\Microsoft.Plugin.Indexer.resources.dll" />
<File Id="Launcher_Indexer_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Indexer\$(var.Language)\Microsoft.Plugin.Indexer.resources.dll" />
</Component>
<Component Id="Launcher_Uri_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)UriPluginFolder">
<File Id="Launcher_Uri_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Uri\$(var.Language)\Microsoft.Plugin.Uri.resources.dll" />
<File Id="Launcher_Uri_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Uri\$(var.Language)\Microsoft.Plugin.Uri.resources.dll" />
</Component>
<Component Id="Launcher_VSCodeWorkspaces_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)VSCodeWorkspacesPluginFolder">
<File Id="Launcher_VSCodeWorkspaces_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\VSCodeWorkspaces\$(var.Language)\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.resources.dll" />
</Component>
<Component Id="Launcher_WindowWalker_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)WindowWalkerPluginFolder">
<File Id="Launcher_WindowWalker_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowWalker\$(var.Language)\Microsoft.Plugin.WindowWalker.resources.dll" />
<File Id="Launcher_WindowWalker_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\$(var.Language)\Microsoft.Plugin.WindowWalker.resources.dll" />
</Component>
<Component Id="Launcher_Registry_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)RegistryPluginFolder">
<File Id="Launcher_Registry_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Registry\$(var.Language)\Microsoft.PowerToys.Run.Plugin.Registry.resources.dll" />
<File Id="Launcher_Registry_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\$(var.Language)\Microsoft.PowerToys.Run.Plugin.Registry.resources.dll" />
</Component>
<Component Id="Launcher_Service_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)ServicePluginFolder">
<File Id="Launcher_Service_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Service\$(var.Language)\Microsoft.PowerToys.Run.Plugin.Service.resources.dll" />
@ -1093,7 +1089,7 @@
<File Id="Launcher_System_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\System\$(var.Language)\Microsoft.PowerToys.Run.Plugin.System.resources.dll" />
</Component>
<Component Id="Launcher_WindowsSettings_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)WindowsSettingsPluginFolder">
<File Id="Launcher_WindowsSettings_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowsSettings\$(var.Language)\Microsoft.PowerToys.Run.Plugin.WindowsSettings.resources.dll" />
<File Id="Launcher_WindowsSettings_$(var.IdSafeLanguage)_File" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\$(var.Language)\Microsoft.PowerToys.Run.Plugin.WindowsSettings.resources.dll" />
</Component>
<!-- Uncomment after Plugin receives the localization files.
<Component Id="Launcher_WindowsTerminal_$(var.IdSafeLanguage)_Component" Directory="Resource$(var.IdSafeLanguage)WindowsTerminalFolder">
@ -1147,71 +1143,71 @@
<!-- Folder Plugin -->
<Component Id="FolderComponent" Directory="FolderPluginFolder" Guid="453D6C29-8F0D-46EC-B210-82E6AF547039">
<?foreach File in plugin.json;Microsoft.Plugin.Folder.deps.json;Microsoft.Plugin.Folder.dll;ManagedTelemetry.dll?>
<File Id="Folder_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Folder\$(var.File)" />
<File Id="Folder_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Folder\$(var.File)" />
<?endforeach?>
</Component>
<Component Id="FolderImagesComponent" Directory="FolderPluginImagesFolder" Guid="6C5226EB-E312-4768-B4D1-B1D3ACFCCBDF">
<?foreach File in copy.dark.png;copy.light.png;delete.dark.png;delete.light.png;file.dark.png;file.light.png;folder.dark.png;folder.light.png;user.dark.png;user.light.png;Warning.dark.png;Warning.light.png?>
<File Id="FolderPlugin_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Folder\Images\$(var.File)" />
<File Id="FolderPlugin_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Folder\Images\$(var.File)" />
<?endforeach?>
</Component>
<!-- Program Plugin -->
<Component Id="ProgramComponent" Directory="ProgramPluginFolder" Guid="3C5CA6E6-3D36-4F4E-B40E-38AA5E5CB799">
<?foreach File in plugin.json;Microsoft.Plugin.Program.deps.json;Microsoft.Plugin.Program.dll;ManagedTelemetry.dll?>
<File Id="Program_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Program\$(var.File)" />
<File Id="Program_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Program\$(var.File)" />
<?endforeach?>
</Component>
<Component Id="ProgramImagesComponent" Directory="ProgramImagesFolder" Guid="30D357F5-406F-47D1-BEFE-6022746469B4">
<?foreach File in app.dark.png;app.light.png;disable.light.png;disable.dark.png;folder.light.png;folder.dark.png;shell.light.png;shell.dark.png;user.light.png;user.dark.png?>
<File Id="Program_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Program\Images\$(var.File)" />
<File Id="Program_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Program\Images\$(var.File)" />
<?endforeach?>
</Component>
<!-- Shell Plugin -->
<Component Id="ShellComponent" Directory="ShellPluginFolder" Guid="6D3D7294-1804-47C9-83E5-47A8867F3801">
<?foreach File in plugin.json;Microsoft.Plugin.Shell.deps.json;Microsoft.Plugin.Shell.dll;ManagedTelemetry.dll?>
<File Id="Shell_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Shell\$(var.File)" />
<File Id="Shell_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Shell\$(var.File)" />
<?endforeach?>
</Component>
<Component Id="ShellImagesComponent" Directory="ShellImagesFolder" Guid="15B5DBAE-E7C1-4BF7-A29E-6CE76242F8F4">
<?foreach File in shell.light.png;shell.dark.png;user.light.png;user.dark.png?>
<File Id="Shell_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Shell\Images\$(var.File)" />
<File Id="Shell_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Shell\Images\$(var.File)" />
<?endforeach?>
</Component>
<!-- Indexer Plugin -->
<Component Id="IndexerComponent" Directory="IndexerPluginFolder" Guid="FEA9816A-B4F7-42CC-99AF-B05F3E7F7EBF">
<?foreach File in Microsoft.Plugin.Indexer.deps.json;Microsoft.Plugin.Indexer.dll;plugin.json;ManagedTelemetry.dll?>
<File Id="Indexer_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Indexer\$(var.File)" />
<File Id="Indexer_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Indexer\$(var.File)" />
<?endforeach?>
</Component>
<Component Id="IndexerImagesComponent" Directory="IndexerImagesFolder" Guid="DB2E8D49-D104-425B-9616-952AC8CAB676">
<?foreach File in indexer.dark.png;indexer.light.png;Warning.light.png;Warning.dark.png?>
<File Id="Indexer_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Indexer\Images\$(var.File)" />
<File Id="Indexer_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Indexer\Images\$(var.File)" />
<?endforeach?>
</Component>
<!-- UnitConverter Plugin -->
<Component Id="UnitConverterComponent" Directory="UnitConverterPluginFolder" Guid="D4F429E3-C619-49D6-9416-88A757D18E02">
<?foreach File in plugin.json;Community.PowerToys.Run.Plugin.UnitConverter.deps.json;Community.PowerToys.Run.Plugin.UnitConverter.dll?>
<File Id="UnitConverter_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\UnitConverter\$(var.File)" />
<File Id="UnitConverter_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Community.UnitConverter\$(var.File)" />
<?endforeach?>
</Component>
<Component Id="UnitConverterImagesComponent" Directory="UnitConverterImagesFolder" Guid="16ABD217-0898-47B2-89D9-AF1ABF00F543">
<File Id="UnitConverterLight" Source="$(var.BinX64Dir)modules\launcher\Plugins\UnitConverter\Images\unitconverter.light.png" />
<File Id="UnitConverterDark" Source="$(var.BinX64Dir)modules\launcher\Plugins\UnitConverter\Images\unitconverter.dark.png" />
<File Id="UnitConverterLight" Source="$(var.BinX64Dir)modules\launcher\Plugins\Community.UnitConverter\Images\unitconverter.light.png" />
<File Id="UnitConverterDark" Source="$(var.BinX64Dir)modules\launcher\Plugins\Community.UnitConverter\Images\unitconverter.dark.png" />
</Component>
<!-- Uri Plugin -->
<Component Id="UriComponent" Directory="UriPluginFolder" Guid="C7DC8F88-554C-4375-9510-9435399B5D3D">
<?foreach File in plugin.json;Microsoft.Plugin.Uri.deps.json;Microsoft.Plugin.Uri.dll;ManagedTelemetry.dll?>
<File Id="Uri_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Uri\$(var.File)" />
<File Id="Uri_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Uri\$(var.File)" />
<?endforeach?>
</Component>
<Component Id="UriImagesComponent" Directory="UriImagesFolder" Guid="8C9C1634-28C8-45C4-A8EA-8D4C9B4810D0">
<File Id="UriDarkIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Uri\Images\Uri.dark.png" />
<File Id="UriLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Uri\Images\Uri.light.png" />
<File Id="UriDarkIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Uri\Images\Uri.dark.png" />
<File Id="UriLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.Uri\Images\Uri.light.png" />
</Component>
<!-- VSCodeWorkspaces Plugin -->
@ -1231,23 +1227,23 @@
<!-- WindowWalker Plugin -->
<Component Id="WindowWalkerComponent" Directory="WindowWalkerPluginFolder" Guid="EB1391C9-B701-421F-80FC-ABB2FEDFAD19">
<?foreach File in plugin.json;Microsoft.Plugin.WindowWalker.deps.json;Microsoft.Plugin.WindowWalker.dll;ManagedTelemetry.dll?>
<File Id="WindowWalker_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowWalker\$(var.File)" />
<File Id="WindowWalker_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\$(var.File)" />
<?endforeach?>
</Component>
<Component Id="WindowWalkerImagesComponent" Directory="WindowWalkerImagesFolder" Guid="3944A7F5-77F4-4979-9911-EDE709B2F509">
<File Id="WindowWalkerDarkIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowWalker\Images\windowwalker.dark.png" />
<File Id="WindowWalkerLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowWalker\Images\windowwalker.light.png" />
<File Id="WindowWalkerDarkIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\Images\windowwalker.dark.png" />
<File Id="WindowWalkerLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\Images\windowwalker.light.png" />
</Component>
<!-- Registry Plugin -->
<Component Id="RegistryComponent" Directory="RegistryPluginFolder" Guid="186FDFDC-12F1-4221-BEF6-DE6763F54B18">
<?foreach File in plugin.json;Microsoft.PowerToys.Run.Plugin.Registry.deps.json;Microsoft.PowerToys.Run.Plugin.Registry.dll;ManagedTelemetry.dll?>
<File Id="Registry_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Registry\$(var.File)" />
<File Id="Registry_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\$(var.File)" />
<?endforeach?>
</Component>
<Component Id="RegistryImagesComponent" Directory="RegistryImagesFolder" Guid="2E2C91A2-9F53-40C6-BBE9-E6FD6D6E94EB">
<File Id="RegistryDarkIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Registry\Images\reg.dark.png" />
<File Id="RegistryLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Registry\Images\reg.light.png" />
<File Id="RegistryDarkIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\Images\reg.dark.png" />
<File Id="RegistryLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\Images\reg.light.png" />
</Component>
<!-- Service Plugin -->
@ -1285,12 +1281,12 @@
<!-- WindowsSettings Plugin -->
<Component Id="WindowsSettingsComponent" Directory="WindowsSettingsPluginFolder" Guid="ACEC2B6D-8E95-43BF-A1E4-137E95F07C96">
<?foreach File in plugin.json;Microsoft.PowerToys.Run.Plugin.WindowsSettings.deps.json;Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll;ManagedTelemetry.dll?>
<File Id="WindowsSettings_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowsSettings\$(var.File)" />
<File Id="WindowsSettings_$(var.File)" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\$(var.File)" />
<?endforeach?>
</Component>
<Component Id="WindowsSettingsImagesComponent" Directory="WindowsSettingsImagesFolder" Guid="E1CE33A7-6318-4FA6-A46B-9302A00BD6AA">
<File Id="WindowsSettingsDarkIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowsSettings\Images\WindowsSettings.dark.png" />
<File Id="WindowsSettingsLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\WindowsSettings\Images\WindowsSettings.light.png" />
<File Id="WindowsSettingsDarkIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Images\WindowsSettings.dark.png" />
<File Id="WindowsSettingsLightIcon" Source="$(var.BinX64Dir)modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Images\WindowsSettings.light.png" />
</Component>
<!-- WindowsTerminal Plugin -->

View file

@ -26,7 +26,6 @@ struct LogSettings
inline const static std::string keyboardManagerLoggerName = "keyboard-manager";
inline const static std::wstring keyboardManagerLogPath = L"Logs\\keyboard-manager-log.txt";
inline const static std::string findMyMouseLoggerName = "find-my-mouse";
inline const static std::string mouseHighlighterLoggerName = "mouse-highlighter";
inline const static std::string powerRenameLoggerName = "powerrename";
inline const static int retention = 30;
std::wstring logLevel;

View file

@ -9,7 +9,10 @@
#include "winapi_error.h"
#include "../logger/logger.h"
static IMAGEHLP_SYMBOL64* pSymbol = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH * sizeof(TCHAR));
static IMAGEHLP_LINE64 line;
static BOOLEAN processingException = FALSE;
static CHAR modulePath[MAX_PATH];
static inline const char* exceptionDescription(const DWORD& code)
{
@ -61,15 +64,15 @@ static inline const char* exceptionDescription(const DWORD& code)
}
/* Returns the index of the last backslash in the file path */
inline int GetFilenameStart(wchar_t* path)
inline int GetFilenameStart(CHAR* path)
{
int pos = 0;
int found = 0;
if (path != NULL)
{
while (path[pos] != L'\0' && pos < MAX_PATH)
while (path[pos] != '\0' && pos < MAX_PATH)
{
if (path[pos] == L'\\')
if (path[pos] == '\\')
{
found = pos + 1;
}
@ -80,73 +83,22 @@ inline int GetFilenameStart(wchar_t* path)
return found;
}
inline std::wstring GetModuleName(HANDLE process, const STACKFRAME64& stack)
{
static wchar_t modulePath[MAX_PATH]{};
const size_t size = sizeof(modulePath);
memset(&modulePath[0], '\0', size);
DWORD64 moduleBase = SymGetModuleBase64(process, stack.AddrPC.Offset);
if (!moduleBase)
{
Logger::error(L"Failed to get a module. {}", get_last_error_or_default(GetLastError()));
return std::wstring();
}
if (!GetModuleFileNameW((HINSTANCE)moduleBase, modulePath, MAX_PATH))
{
Logger::error(L"Failed to get a module path. {}", get_last_error_or_default(GetLastError()));
return std::wstring();
}
const int start = GetFilenameStart(modulePath);
return std::wstring(modulePath, start);
}
inline std::wstring GetName(HANDLE process, const STACKFRAME64& stack)
{
static IMAGEHLP_SYMBOL64* pSymbol = (IMAGEHLP_SYMBOL64*)malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH * sizeof(TCHAR));
if (!pSymbol)
{
return std::wstring();
}
memset(pSymbol, '\0', sizeof(*pSymbol) + MAX_PATH);
pSymbol->MaxNameLength = MAX_PATH;
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
DWORD64 dw64Displacement = 0;
if (!SymGetSymFromAddr64(process, stack.AddrPC.Offset, &dw64Displacement, pSymbol))
{
Logger::error(L"Failed to get a symbol. {}", get_last_error_or_default(GetLastError()));
return std::wstring();
}
std::string str = pSymbol->Name;
return std::wstring(str.begin(), str.end());
}
inline std::wstring GetLine(HANDLE process, const STACKFRAME64& stack)
{
static IMAGEHLP_LINE64 line{};
memset(&line, '\0', sizeof(IMAGEHLP_LINE64));
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
line.LineNumber = 0;
DWORD dwDisplacement = 0;
if (!SymGetLineFromAddr64(process, stack.AddrPC.Offset, &dwDisplacement, &line))
{
return std::wstring();
}
std::string fileName(line.FileName);
return L"(" + std::wstring(fileName.begin(), fileName.end()) + L":" + std::to_wstring(line.LineNumber) + L")";
}
inline void LogStackTrace()
{
BOOL result;
HANDLE thread;
HANDLE process;
CONTEXT context;
STACKFRAME64 stack;
ULONG frame;
DWORD64 dw64Displacement;
DWORD dwDisplacement;
memset(&stack, 0, sizeof(STACKFRAME64));
memset(pSymbol, '\0', sizeof(*pSymbol) + MAX_PATH);
memset(&modulePath[0], '\0', sizeof(modulePath));
line.LineNumber = 0;
try
{
RtlCaptureContext(&context);
@ -157,11 +109,9 @@ inline void LogStackTrace()
return;
}
STACKFRAME64 stack;
memset(&stack, 0, sizeof(STACKFRAME64));
HANDLE process = GetCurrentProcess();
HANDLE thread = GetCurrentThread();
process = GetCurrentProcess();
thread = GetCurrentThread();
dw64Displacement = 0;
stack.AddrPC.Offset = context.Rip;
stack.AddrPC.Mode = AddrModeFlat;
stack.AddrStack.Offset = context.Rsp;
@ -169,9 +119,8 @@ inline void LogStackTrace()
stack.AddrFrame.Offset = context.Rbp;
stack.AddrFrame.Mode = AddrModeFlat;
BOOL result = false;
std::wstringstream ss;
for (;;)
std::stringstream ss;
for (frame = 0;; frame++)
{
result = StackWalk64(
IMAGE_FILE_MACHINE_AMD64,
@ -189,10 +138,34 @@ inline void LogStackTrace()
break;
}
ss << GetModuleName(process, stack) << "!" << GetName(process, stack) << GetLine(process, stack) << std::endl;
pSymbol->MaxNameLength = MAX_PATH;
pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
if (!SymGetSymFromAddr64(process, stack.AddrPC.Offset, &dw64Displacement, pSymbol))
{
Logger::error(L"Failed to get a symbol. {}", get_last_error_or_default(GetLastError()));
}
line.LineNumber = 0;
SymGetLineFromAddr64(process, stack.AddrPC.Offset, &dwDisplacement, &line);
DWORD64 moduleBase = SymGetModuleBase64(process, stack.AddrPC.Offset);
if (moduleBase)
{
if (!GetModuleFileNameA((HINSTANCE)moduleBase, modulePath, MAX_PATH))
{
Logger::error(L"Failed to get a module path. {}", get_last_error_or_default(GetLastError()));
}
}
else
{
Logger::error(L"Failed to get a module. {}", get_last_error_or_default(GetLastError()));
}
ss << std::string(modulePath).substr(GetFilenameStart(modulePath)) << "!" << pSymbol->Name << "(" << line.FileName << ":" << line.LineNumber << std::endl;
}
Logger::error(L"STACK TRACE\r\n{}", ss.str());
Logger::error("STACK TRACE\r\n{}", ss.str());
Logger::flush();
}
@ -245,6 +218,7 @@ inline void InitSymbols()
{
// Preload symbols so they will be available in case of out-of-memory exception
SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME);
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
HANDLE process = GetCurrentProcess();
if (!SymInitialize(process, NULL, TRUE))
{

View file

@ -1,21 +0,0 @@
#pragma once
// helper function to get the RGB from a #FFFFFF string.
inline bool checkValidRGB(std::wstring_view hex, uint8_t* R, uint8_t* G, uint8_t* B)
{
if (hex.length() != 7)
return false;
hex = hex.substr(1, 6); // remove #
for (auto& c : hex)
{
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')))
{
return false;
}
}
if (swscanf_s(hex.data(), L"%2hhx%2hhx%2hhx", R, G, B) != 3)
{
return false;
}
return true;
}

View file

@ -8,7 +8,6 @@
#include <vector>
#include <optional>
#include <cassert>
#include <sstream>
#include "../logger/logger.h"
#include "../utils/winapi_error.h"

View file

@ -19,6 +19,8 @@ namespace ABI
}
#endif
bool m_doNotActivateOnGameMode = true;
#pragma region Super_Sonar_Base_Code
template<typename D>
@ -56,13 +58,11 @@ protected:
// At actual check, time a fifth of the current double click setting might be used instead to take into account users who might have low values.
static const int MIN_DOUBLE_CLICK_TIME = 100;
bool m_destroyed = false;
bool m_doNotActivateOnGameMode = true;
int m_sonarRadius = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_RADIUS;
int m_sonarZoomFactor = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM;
DWORD m_fadeDuration = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS;
int m_finalAlphaNumerator = FIND_MY_MOUSE_DEFAULT_OVERLAY_OPACITY;
static constexpr int FinalAlphaDenominator = 100;
static constexpr int SonarRadius = 100;
static constexpr int SonarZoomFactor = 9;
static constexpr DWORD FadeDuration = 500;
static constexpr int FinalAlphaNumerator = 1;
static constexpr int FinalAlphaDenominator = 2;
winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
private:
@ -141,7 +141,7 @@ bool SuperSonar<D>::Initialize(HINSTANCE hinst)
m_hwndOwner = CreateWindow(L"static", nullptr, WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, hinst, nullptr);
DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_TOOLWINDOW | Shim()->GetExtendedStyle();
DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | Shim()->GetExtendedStyle();
return CreateWindowExW(exStyle, className, windowTitle, WS_POPUP, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, m_hwndOwner, nullptr, hinst, this) != nullptr;
}
@ -150,7 +150,6 @@ void SuperSonar<D>::Terminate()
{
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
m_destroyed = true;
DestroyWindow(m_hwndOwner);
});
if (!enqueueSucceeded)
@ -458,7 +457,7 @@ void SuperSonar<D>::UpdateMouseSnooping()
struct CompositionSpotlight : SuperSonar<CompositionSpotlight>
{
static constexpr UINT WM_OPACITY_ANIMATION_COMPLETED = WM_APP;
float m_sonarRadiusFloat = static_cast<float>(m_sonarRadius);
static constexpr float SonarRadiusFloat = static_cast<float>(SonarRadius);
DWORD GetExtendedStyle()
{
@ -490,7 +489,7 @@ struct CompositionSpotlight : SuperSonar<CompositionSpotlight>
m_batch.Completed([hwnd = m_hwnd](auto&&, auto&&) {
PostMessage(hwnd, WM_OPACITY_ANIMATION_COMPLETED, 0, 0);
});
m_root.Opacity(visible ? static_cast<float>(m_finalAlphaNumerator) / FinalAlphaDenominator : 0.0f);
m_root.Opacity(visible ? static_cast<float>(FinalAlphaNumerator) / FinalAlphaDenominator : 0.0f);
if (visible)
{
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
@ -532,38 +531,38 @@ private:
layer.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
m_root.Children().InsertAtTop(layer);
m_backdrop = m_compositor.CreateSpriteVisual();
m_backdrop.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
m_backdrop.Brush(m_compositor.CreateColorBrush(m_backgroundColor));
layer.Children().InsertAtTop(m_backdrop);
auto backdrop = m_compositor.CreateSpriteVisual();
backdrop.RelativeSizeAdjustment({ 1.0f, 1.0f }); // fill the parent
backdrop.Brush(m_compositor.CreateColorBrush({ 255, 0, 0, 0 }));
layer.Children().InsertAtTop(backdrop);
m_circleGeometry = m_compositor.CreateEllipseGeometry(); // radius set via expression animation
m_circleShape = m_compositor.CreateSpriteShape(m_circleGeometry);
m_circleShape.FillBrush(m_compositor.CreateColorBrush(m_spotlightColor));
m_circleShape.Offset({ m_sonarRadiusFloat * m_sonarZoomFactor, m_sonarRadiusFloat * m_sonarZoomFactor });
auto circleShape = m_compositor.CreateSpriteShape(m_circleGeometry);
circleShape.FillBrush(m_compositor.CreateColorBrush({ 255, 255, 255, 255 }));
circleShape.Offset({ SonarRadiusFloat * SonarZoomFactor, SonarRadiusFloat * SonarZoomFactor });
m_spotlight = m_compositor.CreateShapeVisual();
m_spotlight.Size({ m_sonarRadiusFloat * 2 * m_sonarZoomFactor, m_sonarRadiusFloat * 2 * m_sonarZoomFactor });
m_spotlight.Size({ SonarRadiusFloat * 2 * SonarZoomFactor, SonarRadiusFloat * 2 * SonarZoomFactor });
m_spotlight.AnchorPoint({ 0.5f, 0.5f });
m_spotlight.Shapes().Append(m_circleShape);
m_spotlight.Shapes().Append(circleShape);
layer.Children().InsertAtTop(m_spotlight);
// Implicitly animate the alpha.
m_animation = m_compositor.CreateScalarKeyFrameAnimation();
m_animation.Target(L"Opacity");
m_animation.InsertExpressionKeyFrame(1.0f, L"this.FinalValue");
m_animation.Duration(std::chrono::milliseconds{ m_fadeDuration });
auto animation = m_compositor.CreateScalarKeyFrameAnimation();
animation.Target(L"Opacity");
animation.InsertExpressionKeyFrame(1.0f, L"this.FinalValue");
animation.Duration(std::chrono::milliseconds{ FadeDuration });
auto collection = m_compositor.CreateImplicitAnimationCollection();
collection.Insert(L"Opacity", m_animation);
collection.Insert(L"Opacity", animation);
m_root.ImplicitAnimations(collection);
// Radius of spotlight shrinks as opacity increases.
// At opacity zero, it is m_sonarRadius * SonarZoomFactor.
// At maximum opacity, it is m_sonarRadius.
// At opacity zero, it is SonarRadius * SonarZoomFactor.
// At maximum opacity, it is SonarRadius.
auto radiusExpression = m_compositor.CreateExpressionAnimation();
radiusExpression.SetReferenceParameter(L"Root", m_root);
wchar_t expressionText[256];
winrt::check_hresult(StringCchPrintfW(expressionText, ARRAYSIZE(expressionText), L"Lerp(Vector2(%d, %d), Vector2(%d, %d), Root.Opacity * %d / %d)", m_sonarRadius * m_sonarZoomFactor, m_sonarRadius * m_sonarZoomFactor, m_sonarRadius, m_sonarRadius, FinalAlphaDenominator, m_finalAlphaNumerator));
winrt::check_hresult(StringCchPrintfW(expressionText, ARRAYSIZE(expressionText), L"Lerp(Vector2(%d, %d), Vector2(%d, %d), Root.Opacity * %d / %d)", SonarRadius * SonarZoomFactor, SonarRadius * SonarZoomFactor, SonarRadius, SonarRadius, FinalAlphaDenominator, FinalAlphaNumerator));
radiusExpression.Expression(expressionText);
m_circleGeometry.StartAnimation(L"Radius", radiusExpression);
@ -582,62 +581,6 @@ private:
}
}
public:
void ApplySettings(const FindMyMouseSettings& settings, bool applyToRuntimeObjects) {
if (!applyToRuntimeObjects)
{
// Runtime objects not created yet. Just update fields.
m_sonarRadius = settings.spotlightRadius;
m_sonarRadiusFloat = static_cast<float>(m_sonarRadius);
m_backgroundColor = settings.backgroundColor;
m_spotlightColor = settings.spotlightColor;
m_doNotActivateOnGameMode = settings.doNotActivateOnGameMode;
m_fadeDuration = settings.animationDurationMs > 0 ? settings.animationDurationMs : 1;
m_finalAlphaNumerator = settings.overlayOpacity;
m_sonarZoomFactor = settings.spotlightInitialZoom;
}
else
{
// Runtime objects already created. Should update in the owner thread.
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
FindMyMouseSettings localSettings = settings;
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
if (!m_destroyed)
{
// Runtime objects not created yet. Just update fields.
m_sonarRadius = localSettings.spotlightRadius;
m_sonarRadiusFloat = static_cast<float>(m_sonarRadius);
m_backgroundColor = localSettings.backgroundColor;
m_spotlightColor = localSettings.spotlightColor;
m_doNotActivateOnGameMode = localSettings.doNotActivateOnGameMode;
m_fadeDuration = localSettings.animationDurationMs > 0 ? localSettings.animationDurationMs : 1;
m_finalAlphaNumerator = localSettings.overlayOpacity;
m_sonarZoomFactor = localSettings.spotlightInitialZoom;
// Apply new settings to runtime composition objects.
m_backdrop.Brush().as<winrt::CompositionColorBrush>().Color(m_backgroundColor);
m_circleShape.FillBrush().as<winrt::CompositionColorBrush>().Color(m_spotlightColor);
m_circleShape.Offset({ m_sonarRadiusFloat * m_sonarZoomFactor, m_sonarRadiusFloat * m_sonarZoomFactor });
m_spotlight.Size({ m_sonarRadiusFloat * 2 * m_sonarZoomFactor, m_sonarRadiusFloat * 2 * m_sonarZoomFactor });
m_animation.Duration(std::chrono::milliseconds{ m_fadeDuration });
m_circleGeometry.StopAnimation(L"Radius");
// Update animation
auto radiusExpression = m_compositor.CreateExpressionAnimation();
radiusExpression.SetReferenceParameter(L"Root", m_root);
wchar_t expressionText[256];
winrt::check_hresult(StringCchPrintfW(expressionText, ARRAYSIZE(expressionText), L"Lerp(Vector2(%d, %d), Vector2(%d, %d), Root.Opacity * %d / %d)", m_sonarRadius * m_sonarZoomFactor, m_sonarRadius * m_sonarZoomFactor, m_sonarRadius, m_sonarRadius, FinalAlphaDenominator, m_finalAlphaNumerator));
radiusExpression.Expression(expressionText);
m_circleGeometry.StartAnimation(L"Radius", radiusExpression);
}
});
if (!enqueueSucceeded)
{
Logger::error("Couldn't enqueue message to update the sonar settings.");
}
}
}
private:
winrt::Compositor m_compositor{ nullptr };
winrt::Desktop::DesktopWindowTarget m_target{ nullptr };
@ -645,11 +588,6 @@ private:
winrt::CompositionEllipseGeometry m_circleGeometry{ nullptr };
winrt::ShapeVisual m_spotlight{ nullptr };
winrt::CompositionCommitBatch m_batch{ nullptr };
winrt::SpriteVisual m_backdrop{ nullptr };
winrt::CompositionSpriteShape m_circleShape{ nullptr };
winrt::Windows::UI::Color m_backgroundColor = FIND_MY_MOUSE_DEFAULT_BACKGROUND_COLOR;
winrt::Windows::UI::Color m_spotlightColor = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_COLOR;
winrt::ScalarKeyFrameAnimation m_animation{ nullptr };
};
template<typename D>
@ -693,7 +631,7 @@ struct GdiSonar : SuperSonar<D>
void OnFadeTimer()
{
auto now = GetTickCount();
auto step = (int)((now - m_fadeStart) * MaxAlpha / this->m_fadeDuration);
auto step = (int)((now - m_fadeStart) * MaxAlpha / this->FadeDuration);
this->Shim()->InvalidateSonar();
if (m_alpha < m_alphaTarget)
@ -728,13 +666,13 @@ protected:
int CurrentSonarRadius()
{
int range = MaxAlpha - m_alpha;
int radius = this->m_sonarRadius + this->m_sonarRadius * range * (this->m_sonarZoomFactor - 1) / MaxAlpha;
int radius = this->SonarRadius + this->SonarRadius * range * (this->SonarZoomFactor - 1) / MaxAlpha;
return radius;
}
private:
static constexpr DWORD FadeFramePeriod = 10;
int MaxAlpha = SuperSonar<D>::m_finalAlphaNumerator * 255 / SuperSonar<D>::FinalAlphaDenominator;
static constexpr int MaxAlpha = SuperSonar<D>::FinalAlphaNumerator * 255 / SuperSonar<D>::FinalAlphaDenominator;
static constexpr DWORD TIMER_ID_FADE = 101;
private:
@ -854,14 +792,6 @@ struct GdiCrosshairs : GdiSonar<GdiCrosshairs>
#pragma region Super_Sonar_API
CompositionSpotlight* m_sonar = nullptr;
void FindMyMouseApplySettings(const FindMyMouseSettings& settings)
{
if (m_sonar != nullptr)
{
Logger::info("Applying settings.");
m_sonar->ApplySettings(settings, true);
}
}
void FindMyMouseDisable()
{
@ -877,8 +807,13 @@ bool FindMyMouseIsEnabled()
return (m_sonar != nullptr);
}
void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate)
{
m_doNotActivateOnGameMode = doNotActivate;
}
// Based on SuperSonar's original wWinMain.
int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings)
int FindMyMouseMain(HINSTANCE hinst)
{
Logger::info("Starting a sonar instance.");
if (m_sonar != nullptr)
@ -888,7 +823,6 @@ int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings)
}
CompositionSpotlight sonar;
sonar.ApplySettings(settings, false);
if (!sonar.Initialize(hinst))
{
Logger::error("Couldn't initialize a sonar instance.");

View file

@ -1,26 +1,6 @@
#pragma once
#include "pch.h"
constexpr bool FIND_MY_MOUSE_DEFAULT_DO_NOT_ACTIVATE_ON_GAME_MODE = true;
const winrt::Windows::UI::Color FIND_MY_MOUSE_DEFAULT_BACKGROUND_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(255, 0, 0, 0);
const winrt::Windows::UI::Color FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(255, 255, 255, 255);
constexpr int FIND_MY_MOUSE_DEFAULT_OVERLAY_OPACITY = 50;
constexpr int FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_RADIUS = 100;
constexpr int FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS = 500;
constexpr int FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM = 9;
struct FindMyMouseSettings
{
bool doNotActivateOnGameMode = FIND_MY_MOUSE_DEFAULT_DO_NOT_ACTIVATE_ON_GAME_MODE;
winrt::Windows::UI::Color backgroundColor = FIND_MY_MOUSE_DEFAULT_BACKGROUND_COLOR;
winrt::Windows::UI::Color spotlightColor = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_COLOR;
int overlayOpacity = FIND_MY_MOUSE_DEFAULT_OVERLAY_OPACITY;
int spotlightRadius = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_RADIUS;
int animationDurationMs = FIND_MY_MOUSE_DEFAULT_ANIMATION_DURATION_MS;
int spotlightInitialZoom = FIND_MY_MOUSE_DEFAULT_SPOTLIGHT_INITIAL_ZOOM;
};
int FindMyMouseMain(HINSTANCE hinst, const FindMyMouseSettings& settings);
int FindMyMouseMain(HINSTANCE hinst);
void FindMyMouseDisable();
bool FindMyMouseIsEnabled();
void FindMyMouseApplySettings(const FindMyMouseSettings& settings);
void FindMyMouseSetDoNotActivateOnGameMode(bool doNotActivate);

View file

@ -5,19 +5,13 @@
#include "FindMyMouse.h"
#include <thread>
#include <common/utils/logger_helper.h>
#include <common/utils/color.h>
namespace
{
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
const wchar_t JSON_KEY_VALUE[] = L"value";
const wchar_t JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE[] = L"do_not_activate_on_game_mode";
const wchar_t JSON_KEY_BACKGROUND_COLOR[] = L"background_color";
const wchar_t JSON_KEY_SPOTLIGHT_COLOR[] = L"spotlight_color";
const wchar_t JSON_KEY_OVERLAY_OPACITY[] = L"overlay_opacity";
const wchar_t JSON_KEY_SPOTLIGHT_RADIUS[] = L"spotlight_radius";
const wchar_t JSON_KEY_ANIMATION_DURATION_MS[] = L"animation_duration_ms";
const wchar_t JSON_KEY_SPOTLIGHT_INITIAL_ZOOM[] = L"spotlight_initial_zoom";
}
extern "C" IMAGE_DOS_HEADER __ImageBase;
@ -54,9 +48,6 @@ private:
// The PowerToy state.
bool m_enabled = false;
// Find My Mouse specific settings
FindMyMouseSettings m_findMyMouseSettings;
// Load initial settings from the persisted values.
void init_settings();
@ -118,7 +109,7 @@ public:
parse_settings(values);
FindMyMouseApplySettings(m_findMyMouseSettings);
values.save_to_settings_file();
}
catch (std::exception&)
{
@ -131,7 +122,7 @@ public:
{
m_enabled = true;
Trace::EnableFindMyMouse(true);
std::thread([=]() { FindMyMouseMain(m_hModule, m_findMyMouseSettings); }).detach();
std::thread([]() { FindMyMouseMain(m_hModule); }).detach();
}
// Disable the powertoy
@ -167,103 +158,25 @@ void FindMyMouse::init_settings()
void FindMyMouse::parse_settings(PowerToysSettings::PowerToyValues& settings)
{
FindMyMouseSetDoNotActivateOnGameMode(true);
auto settingsObject = settings.get_raw_json();
FindMyMouseSettings findMyMouseSettings;
if (settingsObject.GetView().Size())
{
try
{
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_DO_NOT_ACTIVATE_ON_GAME_MODE);
findMyMouseSettings.doNotActivateOnGameMode = (bool)jsonPropertiesObject.GetNamedBoolean(JSON_KEY_VALUE);
FindMyMouseSetDoNotActivateOnGameMode((bool)jsonPropertiesObject.GetNamedBoolean(JSON_KEY_VALUE));
}
catch (...)
{
Logger::warn("Failed to get 'do not activate on game mode' setting");
}
try
{
// Parse background color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_BACKGROUND_COLOR);
auto backgroundColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
uint8_t r, g, b;
if (!checkValidRGB(backgroundColor, &r, &g, &b))
{
Logger::error("Background color RGB value is invalid. Will use default value");
}
else
{
findMyMouseSettings.backgroundColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
}
}
catch (...)
{
Logger::warn("Failed to initialize background color from settings. Will use default value");
}
try
{
// Parse spotlight color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SPOTLIGHT_COLOR);
auto spotlightColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
uint8_t r, g, b;
if (!checkValidRGB(spotlightColor, &r, &g, &b))
{
Logger::error("Spotlight color RGB value is invalid. Will use default value");
}
else
{
findMyMouseSettings.spotlightColor = winrt::Windows::UI::ColorHelper::FromArgb(255, r, g, b);
}
}
catch (...)
{
Logger::warn("Failed to initialize spotlight color from settings. Will use default value");
}
try
{
// Parse Overlay Opacity
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_OVERLAY_OPACITY);
findMyMouseSettings.overlayOpacity = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Overlay Opacity from settings. Will use default value");
}
try
{
// Parse Spotlight Radius
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SPOTLIGHT_RADIUS);
findMyMouseSettings.spotlightRadius = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Spotlight Radius from settings. Will use default value");
}
try
{
// Parse Animation Duration
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ANIMATION_DURATION_MS);
findMyMouseSettings.animationDurationMs = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Animation Duration from settings. Will use default value");
}
try
{
// Parse Spotlight Initial Zoom
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SPOTLIGHT_INITIAL_ZOOM);
findMyMouseSettings.spotlightInitialZoom = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Spotlight Initial Zoom from settings. Will use default value");
}
}
else
{
Logger::info("Find My Mouse settings are empty");
}
m_findMyMouseSettings = findMyMouseSettings;
}

View file

@ -1,5 +0,0 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 .\ resource.base.h resource.h MouseHighlighter.base.rc MouseHighlighter.rc" />
</Target>
</Project>

View file

@ -1,40 +0,0 @@
#include <windows.h>
#include "resource.h"
#include "../../../../common/version/version.h"
#define APSTUDIO_READONLY_SYMBOLS
#include "winres.h"
#undef APSTUDIO_READONLY_SYMBOLS
1 VERSIONINFO
FILEVERSION FILE_VERSION
PRODUCTVERSION PRODUCT_VERSION
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_DLL
FILESUBTYPE VFT2_UNKNOWN
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0" // 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

View file

@ -1,443 +0,0 @@
// MouseHighlighter.cpp : Defines the entry point for the application.
//
#include "pch.h"
#include "MouseHighlighter.h"
#include "trace.h"
#ifdef COMPOSITION
namespace winrt
{
using namespace winrt::Windows::System;
using namespace winrt::Windows::UI::Composition;
}
namespace ABI
{
using namespace ABI::Windows::System;
using namespace ABI::Windows::UI::Composition::Desktop;
}
#endif
struct Highlighter
{
bool MyRegisterClass(HINSTANCE hInstance);
static Highlighter* instance;
void Terminate();
void SwitchActivationMode();
void ApplySettings(MouseHighlighterSettings settings);
private:
enum class MouseButton
{
Left,
Right
};
void DestroyHighlighter();
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) noexcept;
void StartDrawing();
void StopDrawing();
bool CreateHighlighter();
void AddDrawingPoint(MouseButton button);
void UpdateDrawingPointPosition(MouseButton button);
void StartDrawingPointFading(MouseButton button);
void ClearDrawing();
HHOOK m_mouseHook = NULL;
static LRESULT CALLBACK MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) noexcept;
static constexpr auto m_className = L"MouseHighlighter";
static constexpr auto m_windowTitle = L"MouseHighlighter";
HWND m_hwndOwner = NULL;
HWND m_hwnd = NULL;
HINSTANCE m_hinstance = NULL;
static constexpr DWORD WM_SWITCH_ACTIVATION_MODE = WM_APP;
winrt::DispatcherQueueController m_dispatcherQueueController{ nullptr };
winrt::Compositor m_compositor{ nullptr };
winrt::Desktop::DesktopWindowTarget m_target{ nullptr };
winrt::ContainerVisual m_root{ nullptr };
winrt::LayerVisual m_layer{ nullptr };
winrt::ShapeVisual m_shape{ nullptr };
winrt::CompositionSpriteShape m_leftPointer{ nullptr };
winrt::CompositionSpriteShape m_rightPointer{ nullptr };
bool m_leftButtonPressed = false;
bool m_rightButtonPressed = false;
bool m_visible = false;
// Possible configurable settings
float m_radius = MOUSE_HIGHLIGHTER_DEFAULT_RADIUS;
int m_fadeDelay_ms = MOUSE_HIGHLIGHTER_DEFAULT_DELAY_MS;
int m_fadeDuration_ms = MOUSE_HIGHLIGHTER_DEFAULT_DURATION_MS;
winrt::Windows::UI::Color m_leftClickColor = MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR;
winrt::Windows::UI::Color m_rightClickColor = MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR;
};
Highlighter* Highlighter::instance = nullptr;
bool Highlighter::CreateHighlighter()
{
try
{
// We need a dispatcher queue.
DispatcherQueueOptions options =
{
sizeof(options),
DQTYPE_THREAD_CURRENT,
DQTAT_COM_ASTA,
};
ABI::IDispatcherQueueController* controller;
winrt::check_hresult(CreateDispatcherQueueController(options, &controller));
*winrt::put_abi(m_dispatcherQueueController) = controller;
// Create the compositor for our window.
m_compositor = winrt::Compositor();
ABI::IDesktopWindowTarget* target;
winrt::check_hresult(m_compositor.as<ABI::ICompositorDesktopInterop>()->CreateDesktopWindowTarget(m_hwnd, false, &target));
*winrt::put_abi(m_target) = target;
// Create visual root
m_root = m_compositor.CreateContainerVisual();
m_root.RelativeSizeAdjustment({ 1.0f, 1.0f });
m_target.Root(m_root);
// Create the shapes container visual and add it to root.
m_shape = m_compositor.CreateShapeVisual();
m_shape.RelativeSizeAdjustment({ 1.0f, 1.0f });
m_root.Children().InsertAtTop(m_shape);
return true;
} catch (...)
{
return false;
}
}
void Highlighter::AddDrawingPoint(MouseButton button)
{
POINT pt;
// Applies DPIs.
GetCursorPos(&pt);
// Converts to client area of the Windows.
ScreenToClient(m_hwnd, &pt);
// Create circle and add it.
auto circleGeometry = m_compositor.CreateEllipseGeometry();
circleGeometry.Radius({ m_radius, m_radius });
auto circleShape = m_compositor.CreateSpriteShape(circleGeometry);
circleShape.Offset({ (float)pt.x, (float)pt.y });
if (button == MouseButton::Left)
{
circleShape.FillBrush(m_compositor.CreateColorBrush(m_leftClickColor));
m_leftPointer = circleShape;
}
else
{
//right
circleShape.FillBrush(m_compositor.CreateColorBrush(m_rightClickColor));
m_rightPointer = circleShape;
}
m_shape.Shapes().Append(circleShape);
// TODO: We're leaking shapes for long drawing sessions.
// Perhaps add a task to the Dispatcher every X circles to clean up.
// Get back on top in case other Window is now the topmost.
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), 0);
}
void Highlighter::UpdateDrawingPointPosition(MouseButton button)
{
POINT pt;
// Applies DPIs.
GetCursorPos(&pt);
// Converts to client area of the Windows.
ScreenToClient(m_hwnd, &pt);
if (button == MouseButton::Left)
{
m_leftPointer.Offset({ (float)pt.x, (float)pt.y });
}
else
{
//right
m_rightPointer.Offset({ (float)pt.x, (float)pt.y });
}
}
void Highlighter::StartDrawingPointFading(MouseButton button)
{
winrt::Windows::UI::Composition::CompositionSpriteShape circleShape{ nullptr };
if (button == MouseButton::Left)
{
circleShape = m_leftPointer;
}
else
{
//right
circleShape = m_rightPointer;
}
auto brushColor = circleShape.FillBrush().as<winrt::Windows::UI::Composition::CompositionColorBrush>().Color();
// Animate opacity to simulate a fade away effect.
auto animation = m_compositor.CreateColorKeyFrameAnimation();
animation.InsertKeyFrame(1, winrt::Windows::UI::ColorHelper::FromArgb(0, brushColor.R, brushColor.G, brushColor.B));
using timeSpan = std::chrono::duration<int, std::ratio<1, 1000>>;
std::chrono::milliseconds duration(m_fadeDuration_ms);
std::chrono::milliseconds delay(m_fadeDelay_ms);
animation.Duration(timeSpan(duration));
animation.DelayTime(timeSpan(delay));
circleShape.FillBrush().StartAnimation(L"Color", animation);
}
void Highlighter::ClearDrawing()
{
m_shape.Shapes().Clear();
}
LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lParam) noexcept
{
if (nCode >= 0)
{
MSLLHOOKSTRUCT* hookData = (MSLLHOOKSTRUCT*)lParam;
switch (wParam)
{
case WM_LBUTTONDOWN:
instance->AddDrawingPoint(MouseButton::Left);
instance->m_leftButtonPressed = true;
break;
case WM_RBUTTONDOWN:
instance->AddDrawingPoint(MouseButton::Right);
instance->m_rightButtonPressed = true;
break;
case WM_MOUSEMOVE:
if (instance->m_leftButtonPressed)
{
instance->UpdateDrawingPointPosition(MouseButton::Left);
}
if (instance->m_rightButtonPressed)
{
instance->UpdateDrawingPointPosition(MouseButton::Right);
}
break;
case WM_LBUTTONUP:
if (instance->m_leftButtonPressed)
{
instance->StartDrawingPointFading(MouseButton::Left);
instance->m_leftButtonPressed = false;
}
break;
case WM_RBUTTONUP:
if (instance->m_rightButtonPressed)
{
instance->StartDrawingPointFading(MouseButton::Right);
instance->m_rightButtonPressed = false;
}
break;
default:
break;
}
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
void Highlighter::StartDrawing()
{
Logger::info("Starting draw mode.");
Trace::StartHighlightingSession();
m_visible = true;
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN), GetSystemMetrics(SM_YVIRTUALSCREEN),
GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN), 0);
ClearDrawing();
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, m_hinstance, 0);
}
void Highlighter::StopDrawing()
{
Logger::info("Stopping draw mode.");
m_visible = false;
m_leftButtonPressed = false;
m_rightButtonPressed = false;
m_leftPointer = nullptr;
m_rightPointer = nullptr;
ShowWindow(m_hwnd, SW_HIDE);
UnhookWindowsHookEx(m_mouseHook);
ClearDrawing();
m_mouseHook = NULL;
}
void Highlighter::SwitchActivationMode()
{
PostMessage(m_hwnd, WM_SWITCH_ACTIVATION_MODE, 0, 0);
}
void Highlighter::ApplySettings(MouseHighlighterSettings settings) {
m_radius = (float)settings.radius;
m_fadeDelay_ms = settings.fadeDelayMs;
m_fadeDuration_ms = settings.fadeDurationMs;
m_leftClickColor = settings.leftButtonColor;
m_rightClickColor = settings.rightButtonColor;
}
void Highlighter::DestroyHighlighter()
{
StopDrawing();
PostQuitMessage(0);
}
LRESULT CALLBACK Highlighter::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) noexcept
{
switch (message)
{
case WM_NCCREATE:
instance->m_hwnd = hWnd;
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_CREATE:
return instance->CreateHighlighter() ? 0 : -1;
case WM_NCHITTEST:
return HTTRANSPARENT;
case WM_SWITCH_ACTIVATION_MODE:
if (instance->m_visible)
{
instance->StopDrawing();
}
else
{
instance->StartDrawing();
}
break;
case WM_DESTROY:
instance->DestroyHighlighter();
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
bool Highlighter::MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASS wc{};
m_hinstance = hInstance;
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
if (!GetClassInfoW(hInstance, m_className, &wc))
{
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.lpszClassName = m_className;
if (!RegisterClassW(&wc))
{
return false;
}
}
m_hwndOwner = CreateWindow(L"static", nullptr, WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, hInstance, nullptr);
DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOREDIRECTIONBITMAP | WS_EX_TOOLWINDOW;
return CreateWindowExW(exStyle, m_className, m_windowTitle, WS_POPUP,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, m_hwndOwner, nullptr, hInstance, nullptr) != nullptr;
}
void Highlighter::Terminate()
{
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
DestroyWindow(m_hwndOwner);
});
if (!enqueueSucceeded)
{
Logger::error("Couldn't enqueue message to destroy the window.");
}
}
#pragma region MouseHighlighter_API
void MouseHighlighterApplySettings(MouseHighlighterSettings settings)
{
if (Highlighter::instance != nullptr)
{
Logger::info("Applying settings.");
Highlighter::instance->ApplySettings(settings);
}
}
void MouseHighlighterSwitch()
{
if (Highlighter::instance != nullptr)
{
Logger::info("Switching activation mode.");
Highlighter::instance->SwitchActivationMode();
}
}
void MouseHighlighterDisable()
{
if (Highlighter::instance != nullptr)
{
Logger::info("Terminating the highlighter instance.");
Highlighter::instance->Terminate();
}
}
bool MouseHighlighterIsEnabled()
{
return (Highlighter::instance != nullptr);
}
int MouseHighlighterMain(HINSTANCE hInstance, MouseHighlighterSettings settings)
{
Logger::info("Starting a highlighter instance.");
if (Highlighter::instance != nullptr)
{
Logger::error("A highlighter instance was still working when trying to start a new one.");
return 0;
}
// Perform application initialization:
Highlighter highlighter;
Highlighter::instance = &highlighter;
highlighter.ApplySettings(settings);
if (!highlighter.MyRegisterClass(hInstance))
{
Logger::error("Couldn't initialize a highlighter instance.");
Highlighter::instance = nullptr;
return FALSE;
}
Logger::info("Initialized the highlighter instance.");
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Logger::info("Mouse highlighter message loop ended.");
Highlighter::instance = nullptr;
return (int)msg.wParam;
}
#pragma endregion MouseHighlighter_API

View file

@ -1,24 +0,0 @@
#pragma once
#include "pch.h"
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_OPACITY = 160;
const winrt::Windows::UI::Color MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(MOUSE_HIGHLIGHTER_DEFAULT_OPACITY, 255, 255, 0);
const winrt::Windows::UI::Color MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR = winrt::Windows::UI::ColorHelper::FromArgb(MOUSE_HIGHLIGHTER_DEFAULT_OPACITY, 0, 0, 255);
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_RADIUS = 20;
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_DELAY_MS = 500;
constexpr int MOUSE_HIGHLIGHTER_DEFAULT_DURATION_MS = 250;
struct MouseHighlighterSettings
{
winrt::Windows::UI::Color leftButtonColor = MOUSE_HIGHLIGHTER_DEFAULT_LEFT_BUTTON_COLOR;
winrt::Windows::UI::Color rightButtonColor = MOUSE_HIGHLIGHTER_DEFAULT_RIGHT_BUTTON_COLOR;
int radius = MOUSE_HIGHLIGHTER_DEFAULT_RADIUS;
int fadeDelayMs = MOUSE_HIGHLIGHTER_DEFAULT_DELAY_MS;
int fadeDurationMs = MOUSE_HIGHLIGHTER_DEFAULT_DURATION_MS;
};
int MouseHighlighterMain(HINSTANCE hinst, MouseHighlighterSettings settings);
void MouseHighlighterDisable();
bool MouseHighlighterIsEnabled();
void MouseHighlighterSwitch();
void MouseHighlighterApplySettings(MouseHighlighterSettings settings);

View file

@ -1,145 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{782a61be-9d85-4081-b35c-1ccc9dcc1e88}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>MouseHighlighter</RootNamespace>
<WindowsTargetPlatformVersion>10.0.18362.0</WindowsTargetPlatformVersion>
<ProjectName>MouseHighlighter</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)$(Platform)\$(Configuration)\modules\MouseUtils\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;_USRDLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<LanguageStandard>stdcpplatest</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(SolutionDir)src\;$(SolutionDir)src\modules;$(SolutionDir)src\common\Telemetry;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(CIBuild)'!='true'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PrecompiledHeaderFile>pch.h</PrecompiledHeaderFile>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="MouseHighlighter.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="trace.h" />
<ClInclude Include="Generated Files\resource.h" />
<None Include="resource.base.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="MouseHighlighter.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(CIBuild)'!='true'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="trace.cpp" />
<None Include="MouseHighlighter.base.rc" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Generated Files\MouseHighlighter.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\common\SettingsAPI\SetttingsAPI.vcxproj">
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="..\..\..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionTargets">
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>

View file

@ -1,62 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="trace.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="dllmain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MouseHighlighter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="trace.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Generated Files\resource.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="MouseHighlighter.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
<None Include="MouseHighlighter.base.rc">
<Filter>Resource Files</Filter>
</None>
<None Include="resource.base.h">
<Filter>Resource Files</Filter>
</None>
</ItemGroup>
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{b012a2c8-5ccb-47fc-9429-4ebf877928e2}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{c8345550-9836-40a0-b473-0f4bf6129568}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{7934ee5b-8427-486d-9324-73b6bcf60eed}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
<Filter Include="Generated Files">
<UniqueIdentifier>{e1083d6b-b856-42a6-bd1f-1710e96170ba}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Generated Files\MouseHighlighter.rc">
<Filter>Generated Files</Filter>
</ResourceCompile>
</ItemGroup>
</Project>

View file

@ -1,304 +0,0 @@
#include "pch.h"
#include <interface/powertoy_module_interface.h>
#include <common/SettingsAPI/settings_objects.h>
#include "trace.h"
#include "MouseHighlighter.h"
#include "common/utils/color.h"
namespace
{
const wchar_t JSON_KEY_PROPERTIES[] = L"properties";
const wchar_t JSON_KEY_VALUE[] = L"value";
const wchar_t JSON_KEY_ACTIVATION_SHORTCUT[] = L"activation_shortcut";
const wchar_t JSON_KEY_LEFT_BUTTON_CLICK_COLOR[] = L"left_button_click_color";
const wchar_t JSON_KEY_RIGHT_BUTTON_CLICK_COLOR[] = L"right_button_click_color";
const wchar_t JSON_KEY_HIGHLIGHT_OPACITY[] = L"highlight_opacity";
const wchar_t JSON_KEY_HIGHLIGHT_RADIUS[] = L"highlight_radius";
const wchar_t JSON_KEY_HIGHLIGHT_FADE_DELAY_MS[] = L"highlight_fade_delay_ms";
const wchar_t JSON_KEY_HIGHLIGHT_FADE_DURATION_MS[] = L"highlight_fade_duration_ms";
}
extern "C" IMAGE_DOS_HEADER __ImageBase;
HMODULE m_hModule;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
m_hModule = hModule;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Trace::RegisterProvider();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
Trace::UnregisterProvider();
break;
}
return TRUE;
}
// The PowerToy name that will be shown in the settings.
const static wchar_t* MODULE_NAME = L"MouseHighlighter";
// Add a description that will we shown in the module settings page.
const static wchar_t* MODULE_DESC = L"<no description>";
// Implement the PowerToy Module Interface and all the required methods.
class MouseHighlighter : public PowertoyModuleIface
{
private:
// The PowerToy state.
bool m_enabled = false;
// Hotkey to invoke the module
HotkeyEx m_hotkey;
// Mouse Highlighter specific settings
MouseHighlighterSettings m_highlightSettings;
public:
// Constructor
MouseHighlighter()
{
LoggerHelpers::init_logger(MODULE_NAME, L"ModuleInterface", LogSettings::mouseHighlighterLoggerName);
init_settings();
};
// Destroy the powertoy and free memory
virtual void destroy() override
{
delete this;
}
// Return the localized display name of the powertoy
virtual const wchar_t* get_name() override
{
return MODULE_NAME;
}
// Return the non localized key of the powertoy, this will be cached by the runner
virtual const wchar_t* get_key() override
{
return MODULE_NAME;
}
// Return JSON with the configuration options.
virtual bool get_config(wchar_t* buffer, int* buffer_size) override
{
HINSTANCE hinstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
PowerToysSettings::Settings settings(hinstance, get_name());
return settings.serialize_to_buffer(buffer, buffer_size);
}
// Signal from the Settings editor to call a custom action.
// This can be used to spawn more complex editors.
virtual void call_custom_action(const wchar_t* action) override
{
}
// Called by the runner to pass the updated settings values as a serialized JSON.
virtual void set_config(const wchar_t* config) override
{
try
{
// Parse the input JSON string.
PowerToysSettings::PowerToyValues values =
PowerToysSettings::PowerToyValues::from_json_string(config, get_key());
parse_settings(values);
MouseHighlighterApplySettings(m_highlightSettings);
}
catch (std::exception&)
{
Logger::error("Invalid json when trying to parse Mouse Highlighter settings json.");
}
}
// Enable the powertoy
virtual void enable()
{
m_enabled = true;
Trace::EnableMouseHighlighter(true);
std::thread([=]() { MouseHighlighterMain(m_hModule, m_highlightSettings); }).detach();
}
// Disable the powertoy
virtual void disable()
{
m_enabled = false;
Trace::EnableMouseHighlighter(false);
MouseHighlighterDisable();
}
// Returns if the powertoys is enabled
virtual bool is_enabled() override
{
return m_enabled;
}
virtual std::optional<HotkeyEx> GetHotkeyEx() override
{
return m_hotkey;
}
virtual void OnHotkeyEx() override
{
MouseHighlighterSwitch();
}
// Load the settings file.
void init_settings()
{
try
{
// Load and parse the settings file for this PowerToy.
PowerToysSettings::PowerToyValues settings =
PowerToysSettings::PowerToyValues::load_from_settings_file(MouseHighlighter::get_key());
parse_settings(settings);
}
catch (std::exception&)
{
Logger::error("Invalid json when trying to load the Mouse Highlighter settings json from file.");
}
}
void parse_settings(PowerToysSettings::PowerToyValues& settings)
{
// TODO: refactor to use common/utils/json.h instead
auto settingsObject = settings.get_raw_json();
MouseHighlighterSettings highlightSettings;
if (settingsObject.GetView().Size())
{
try
{
// Parse HotKey
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_ACTIVATION_SHORTCUT);
auto hotkey = PowerToysSettings::HotkeyObject::from_json(jsonPropertiesObject);
m_hotkey = HotkeyEx();
if (hotkey.win_pressed())
{
m_hotkey.modifiersMask |= MOD_WIN;
}
if (hotkey.ctrl_pressed())
{
m_hotkey.modifiersMask |= MOD_CONTROL;
}
if (hotkey.shift_pressed())
{
m_hotkey.modifiersMask |= MOD_SHIFT;
}
if (hotkey.alt_pressed())
{
m_hotkey.modifiersMask |= MOD_ALT;
}
m_hotkey.vkCode = hotkey.get_code();
}
catch (...)
{
Logger::warn("Failed to initialize Mouse Highlighter activation shortcut");
}
uint8_t opacity = MOUSE_HIGHLIGHTER_DEFAULT_OPACITY;
try
{
// Parse Opacity
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_OPACITY);
opacity = (uint8_t)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Opacity from settings. Will use default value");
}
try
{
// Parse left button click color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_LEFT_BUTTON_CLICK_COLOR);
auto leftColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
uint8_t r, g, b;
if (!checkValidRGB(leftColor,&r,&g,&b))
{
Logger::error("Left click color RGB value is invalid. Will use default value");
}
else
{
highlightSettings.leftButtonColor = winrt::Windows::UI::ColorHelper::FromArgb(opacity, r, g, b);
}
}
catch (...)
{
Logger::warn("Failed to initialize left click color from settings. Will use default value");
}
try
{
// Parse right button click color
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_RIGHT_BUTTON_CLICK_COLOR);
auto rightColor = (std::wstring)jsonPropertiesObject.GetNamedString(JSON_KEY_VALUE);
uint8_t r, g, b;
if (!checkValidRGB(rightColor, &r, &g, &b))
{
Logger::error("Right click color RGB value is invalid. Will use default value");
}
else
{
highlightSettings.rightButtonColor = winrt::Windows::UI::ColorHelper::FromArgb(opacity, r, g, b);
}
}
catch (...)
{
Logger::warn("Failed to initialize right click color from settings. Will use default value");
}
try
{
// Parse Radius
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_RADIUS);
highlightSettings.radius = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Radius from settings. Will use default value");
}
try
{
// Parse Fade Delay
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_FADE_DELAY_MS);
highlightSettings.fadeDelayMs = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Fade Delay from settings. Will use default value");
}
try
{
// Parse Fade Duration
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_HIGHLIGHT_FADE_DURATION_MS);
highlightSettings.fadeDurationMs = (UINT)jsonPropertiesObject.GetNamedNumber(JSON_KEY_VALUE);
}
catch (...)
{
Logger::warn("Failed to initialize Fade Duration from settings. Will use default value");
}
}
else
{
Logger::info("Mouse Highlighter settings are empty");
}
if (!m_hotkey.modifiersMask)
{
Logger::info("Mouse Highlighter is going to use default shortcut");
m_hotkey.modifiersMask = MOD_SHIFT | MOD_WIN;
m_hotkey.vkCode = 0x48; // H key
}
m_highlightSettings = highlightSettings;
}
};
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
{
return new MouseHighlighter();
}

View file

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
</packages>

View file

@ -1 +0,0 @@
#include "pch.h"

View file

@ -1,22 +0,0 @@
#pragma once
#define COMPOSITION
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <strsafe.h>
#include <hIdUsage.h>
#include <thread>
#ifdef COMPOSITION
#include <windows.ui.composition.interop.h>
#include <DispatcherQueue.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.UI.Composition.Desktop.h>
#include <winrt/Windows.Foundation.Collections.h>
#endif
#include <ProjectTelemetry.h>
#include <common/SettingsAPI/settings_helpers.h>
#include <common/logger/logger.h>
#include <common/utils/logger_helper.h>

View file

@ -1,14 +0,0 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by MouseHighlighter.rc
//////////////////////////////
// Non-localizable
#define FILE_DESCRIPTION "PowerToys MouseHighlighter"
#define INTERNAL_NAME "MouseHighlighter"
#define ORIGINAL_FILENAME "MouseHighlighter.dll"
#define IDS_KEYBOARDMANAGER_ICON 1001
// Non-localizable
//////////////////////////////

View file

@ -1,40 +0,0 @@
#include "pch.h"
#include "trace.h"
TRACELOGGING_DEFINE_PROVIDER(
g_hProvider,
"Microsoft.PowerToys",
// {38e8889b-9731-53f5-e901-e8a7c1753074}
(0x38e8889b, 0x9731, 0x53f5, 0xe9, 0x01, 0xe8, 0xa7, 0xc1, 0x75, 0x30, 0x74),
TraceLoggingOptionProjectTelemetry());
void Trace::RegisterProvider() noexcept
{
TraceLoggingRegister(g_hProvider);
}
void Trace::UnregisterProvider() noexcept
{
TraceLoggingUnregister(g_hProvider);
}
// Log if the user has MouseHighlighter enabled or disabled
void Trace::EnableMouseHighlighter(const bool enabled) noexcept
{
TraceLoggingWrite(
g_hProvider,
"MouseHighlighter_EnableMouseHighlighter",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingBoolean(enabled, "Enabled"));
}
// Log that the user activated the module by starting a highlighting session
void Trace::StartHighlightingSession() noexcept
{
TraceLoggingWrite(
g_hProvider,
"MouseHighlighter_StartHighlightingSession",
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
}

View file

@ -1,14 +0,0 @@
#pragma once
class Trace
{
public:
static void RegisterProvider() noexcept;
static void UnregisterProvider() noexcept;
// Log if the user has MouseHighlighter enabled or disabled
static void EnableMouseHighlighter(const bool enabled) noexcept;
// Log that the user activated the module by starting a highlighting session
static void StartHighlightingSession() noexcept;
};

View file

@ -177,7 +177,7 @@ namespace Awake.Core
// No keep-awake menu item.
CheckButtonToolStripMenuItem? passiveMenuItem = new CheckButtonToolStripMenuItem
{
Text = "Off (Keep using the selected power plan)",
Text = "Off (Passive)",
};
passiveMenuItem.Checked = mode == AwakeMode.PASSIVE;

View file

@ -291,7 +291,7 @@ namespace ColorPicker.Controls
var newValue = (sender as TextBox).Text;
// support hex with 3 and 6 characters
var reg = new Regex("^#([0-9A-Fa-f]{3}){1,2}$");
var reg = new Regex("^#([0-9A-F]{3}){1,2}$");
if (!reg.IsMatch(newValue))
{

View file

@ -44,14 +44,6 @@ namespace ColorPicker.Helpers
return (cyan, magenta, yellow, blackKey);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a float color styling(0.1f, 0.1f, 0.1f)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The int / 255d for each value to get value between 0 and 1</returns>
internal static (double red, double green, double blue) ConvertToDouble(Color color)
=> (color.R / 255d, color.G / 255d, color.B / 255d);
/// <summary>
/// Convert a given <see cref="Color"/> to a HSB color (hue, saturation, brightness)
/// </summary>

View file

@ -46,8 +46,6 @@ namespace ColorPicker.Helpers
ColorRepresentationType.RGB => ColorToRGB(color),
ColorRepresentationType.CIELAB => ColorToCIELAB(color),
ColorRepresentationType.CIEXYZ => ColorToCIEXYZ(color),
ColorRepresentationType.VEC4 => ColorToFloat(color),
ColorRepresentationType.DecimalValue => ColorToDecimal(color),
// Fall-back value, when "_userSettings.CopiedColorRepresentation.Value" is incorrect
_ => ColorToHex(color),
@ -101,29 +99,6 @@ namespace ColorPicker.Helpers
+ $", {brightness.ToString(CultureInfo.InvariantCulture)}%)";
}
/// <summary>
/// Return a <see cref="string"/> representation float color styling(0.1f, 0.1f, 0.1f)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>a string value (0.1f, 0.1f, 0.1f)</returns>
private static string ColorToFloat(Color color)
{
var (red, green, blue) = ColorHelper.ConvertToDouble(color);
var precision = 2;
return $"({Math.Round(red, precision).ToString("0.##", CultureInfo.InvariantCulture)}f, {Math.Round(green, precision).ToString("0.##", CultureInfo.InvariantCulture)}f, {Math.Round(blue, precision).ToString("0.##", CultureInfo.InvariantCulture)}f, 1f)";
}
/// <summary>
/// Return a <see cref="string"/> representation decimal color value
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>a string value number</returns>
private static string ColorToDecimal(Color color)
{
return $"{color.R + (color.G * 256) + (color.B * 65536)}";
}
/// <summary>
/// Return a <see cref="string"/> representation of a HSI color
/// </summary>

View file

@ -216,18 +216,6 @@ namespace ColorPicker.ViewModels
FormatName = ColorRepresentationType.CIEXYZ.ToString(),
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.CIEXYZ); },
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = ColorRepresentationType.VEC4.ToString(),
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.VEC4); },
});
_allColorRepresentations.Add(
new ColorFormatModel()
{
FormatName = "Decimal",
Convert = (Color color) => { return ColorRepresentationHelper.GetStringRepresentationFromMediaColor(color, ColorRepresentationType.DecimalValue); },
});
_userSettings.VisibleColorFormats.CollectionChanged += VisibleColorFormats_CollectionChanged;

View file

@ -24,8 +24,6 @@ namespace Microsoft.ColorPicker.UnitTests
[DataRow(ColorRepresentationType.RGB, "rgb(0, 0, 0)")]
[DataRow(ColorRepresentationType.CIELAB, "CIELab(0, 0, 0)")]
[DataRow(ColorRepresentationType.CIEXYZ, "xyz(0, 0, 0)")]
[DataRow(ColorRepresentationType.VEC4, "(0f, 0f, 0f, 1f)")]
[DataRow(ColorRepresentationType.DecimalValue, "0")]
public void GetStringRepresentationTest(ColorRepresentationType type, string expected)
{

View file

@ -25,8 +25,9 @@ const std::wstring instanceMutexName = L"Local\\PowerToys_FancyZones_InstanceMut
int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ PWSTR lpCmdLine, _In_ int nCmdShow)
{
winrt::init_apartment();
InitUnhandledExceptionHandler_x64();
LoggerHelpers::init_logger(moduleName, internalPath, LogSettings::fancyZonesLoggerName);
InitUnhandledExceptionHandler_x64();
auto mutex = CreateMutex(nullptr, true, instanceMutexName.c_str());
if (mutex == nullptr)

View file

@ -61,7 +61,7 @@
<ClInclude Include="ZoneColors.h" />
<ClInclude Include="ZoneSet.h" />
<ClInclude Include="WorkArea.h" />
<ClInclude Include="ZonesOverlay.h" />
<ClInclude Include="ZoneWindowDrawing.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="FancyZones.cpp" />
@ -84,7 +84,7 @@
<ClCompile Include="Zone.cpp" />
<ClCompile Include="ZoneSet.cpp" />
<ClCompile Include="WorkArea.cpp" />
<ClCompile Include="ZonesOverlay.cpp" />
<ClCompile Include="ZoneWindowDrawing.cpp" />
</ItemGroup>
<ItemGroup>
<None Include="fancyzones.base.rc" />

View file

@ -75,7 +75,7 @@
<ClInclude Include="KeyState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZonesOverlay.h">
<ClInclude Include="ZoneWindowDrawing.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MonitorUtils.h">
@ -140,7 +140,7 @@
<ClCompile Include="FancyZonesDataTypes.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZonesOverlay.cpp">
<ClCompile Include="ZoneWindowDrawing.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="OnThreadExecutor.cpp">

View file

@ -101,12 +101,12 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
{
for (auto [keyMonitor, workArea] : workAreaMap)
{
// Skip calling ShowZonesOverlay for iter->second (m_draggedWindowWorkArea) since it
// Skip calling ShowZoneWindow for iter->second (m_draggedWindowWorkArea) since it
// was already called in MoveSizeEnter
const bool moveSizeEnterCalled = workArea == m_draggedWindowWorkArea;
if (workArea && !moveSizeEnterCalled)
{
workArea->ShowZonesOverlay();
workArea->ShowZoneWindow();
}
}
}
@ -119,7 +119,7 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
{
if (workArea)
{
workArea->HideZonesOverlay();
workArea->HideZoneWindow();
}
}
}
@ -159,7 +159,7 @@ void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen,
{
if (workArea)
{
workArea->HideZonesOverlay();
workArea->HideZoneWindow();
}
}
}
@ -174,7 +174,7 @@ void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen,
m_draggedWindowWorkArea->ClearSelectedZones();
if (!m_settings->GetSettings()->showZonesOnAllMonitors)
{
m_draggedWindowWorkArea->HideZonesOverlay();
m_draggedWindowWorkArea->HideZoneWindow();
}
m_draggedWindowWorkArea = iter->second;
@ -279,7 +279,7 @@ void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const st
{
if (workArea)
{
workArea->HideZonesOverlay();
workArea->HideZoneWindow();
}
}
}

View file

@ -6,7 +6,7 @@
#include "FancyZonesData.h"
#include "FancyZonesDataTypes.h"
#include "ZonesOverlay.h"
#include "ZoneWindowDrawing.h"
#include "trace.h"
#include "util.h"
#include "on_thread_executor.h"
@ -21,7 +21,7 @@
// Non-Localizable strings
namespace NonLocalizable
{
const wchar_t ToolWindowClassName[] = L"FancyZones_ZonesOverlay";
const wchar_t ToolWindowClassName[] = L"SuperFancyZones_ZoneWindow";
}
using namespace FancyZonesUtils;
@ -57,13 +57,13 @@ namespace
public:
HWND NewZonesOverlayWindow(Rect position, HINSTANCE hinstance, WorkArea* owner)
HWND NewZoneWindow(Rect position, HINSTANCE hinstance, WorkArea* owner)
{
HWND windowFromPool = ExtractWindow();
if (windowFromPool == NULL)
{
HWND window = CreateWindowExW(WS_EX_TOOLWINDOW, NonLocalizable::ToolWindowClassName, L"", WS_POPUP, position.left(), position.top(), position.width(), position.height(), nullptr, nullptr, hinstance, owner);
Logger::info("Creating new ZonesOverlay window, hWnd = {}", (void*)window);
Logger::info("Creating new zone window, hWnd = {}", (void*)window);
MakeWindowTransparent(window);
// According to ShowWindow docs, we must call it with SW_SHOWNORMAL the first time
@ -73,17 +73,17 @@ namespace
}
else
{
Logger::info("Reusing ZonesOverlay window from pool, hWnd = {}", (void*)windowFromPool);
Logger::info("Reusing zone window from pool, hWnd = {}", (void*)windowFromPool);
SetWindowLongPtrW(windowFromPool, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(owner));
MoveWindow(windowFromPool, position.left(), position.top(), position.width(), position.height(), TRUE);
return windowFromPool;
}
}
void FreeZonesOverlayWindow(HWND window)
void FreeZoneWindow(HWND window)
{
_TRACER_;
Logger::info("Freeing ZonesOverlay window into pool, hWnd = {}", (void*)window);
Logger::info("Freeing zone window, hWnd = {}", (void*)window);
SetWindowLongPtrW(window, GWLP_USERDATA, 0);
ShowWindow(window, SW_HIDE);
@ -133,9 +133,9 @@ public:
IFACEMETHODIMP_(ZoneIndexSet)
GetWindowZoneIndexes(HWND window) const noexcept;
IFACEMETHODIMP_(void)
ShowZonesOverlay() noexcept;
ShowZoneWindow() noexcept;
IFACEMETHODIMP_(void)
HideZonesOverlay() noexcept;
HideZoneWindow() noexcept;
IFACEMETHODIMP_(void)
UpdateActiveZoneSet() noexcept;
IFACEMETHODIMP_(void)
@ -169,7 +169,7 @@ private:
ZoneIndexSet m_highlightZone;
WPARAM m_keyLast{};
size_t m_keyCycle{};
std::unique_ptr<ZonesOverlay> m_zonesOverlay;
std::unique_ptr<ZoneWindowDrawing> m_zoneWindowDrawing;
ZoneColors m_zoneColors;
OverlappingZonesAlgorithm m_overlappingAlgorithm;
};
@ -187,7 +187,7 @@ WorkArea::WorkArea(HINSTANCE hinstance)
WorkArea::~WorkArea()
{
windowPool.FreeZonesOverlayWindow(m_window);
windowPool.FreeZoneWindow(m_window);
}
bool WorkArea::Init(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataTypes::DeviceIdData& uniqueId, const FancyZonesDataTypes::DeviceIdData& parentUniqueId, const ZoneColors& zoneColors, OverlappingZonesAlgorithm overlappingAlgorithm)
@ -215,14 +215,14 @@ bool WorkArea::Init(HINSTANCE hinstance, HMONITOR monitor, const FancyZonesDataT
m_uniqueId = uniqueId;
InitializeZoneSets(parentUniqueId);
m_window = windowPool.NewZonesOverlayWindow(workAreaRect, hinstance, this);
m_window = windowPool.NewZoneWindow(workAreaRect, hinstance, this);
if (!m_window)
{
return false;
}
m_zonesOverlay = std::make_unique<ZonesOverlay>(m_window);
m_zoneWindowDrawing = std::make_unique<ZoneWindowDrawing>(m_window);
return true;
}
@ -232,7 +232,7 @@ IFACEMETHODIMP WorkArea::MoveSizeEnter(HWND window) noexcept
m_windowMoveSize = window;
m_highlightZone = {};
m_initialHighlightZone = {};
ShowZonesOverlay();
ShowZoneWindow();
Trace::WorkArea::MoveOrResizeStarted(m_zoneSet);
return S_OK;
}
@ -275,7 +275,7 @@ IFACEMETHODIMP WorkArea::MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled,
if (redraw)
{
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
}
return S_OK;
@ -301,7 +301,7 @@ IFACEMETHODIMP WorkArea::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcep
}
Trace::WorkArea::MoveOrResizeEnd(m_zoneSet);
HideZonesOverlay();
HideZoneWindow();
m_windowMoveSize = nullptr;
return S_OK;
}
@ -400,22 +400,22 @@ WorkArea::GetWindowZoneIndexes(HWND window) const noexcept
}
IFACEMETHODIMP_(void)
WorkArea::ShowZonesOverlay() noexcept
WorkArea::ShowZoneWindow() noexcept
{
if (m_window)
{
SetAsTopmostWindow();
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zonesOverlay->Show();
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zoneWindowDrawing->Show();
}
}
IFACEMETHODIMP_(void)
WorkArea::HideZonesOverlay() noexcept
WorkArea::HideZoneWindow() noexcept
{
if (m_window)
{
m_zonesOverlay->Hide();
m_zoneWindowDrawing->Hide();
m_keyLast = 0;
m_windowMoveSize = nullptr;
m_highlightZone = {};
@ -429,7 +429,7 @@ WorkArea::UpdateActiveZoneSet() noexcept
if (m_window)
{
m_highlightZone.clear();
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
}
}
@ -448,7 +448,7 @@ WorkArea::ClearSelectedZones() noexcept
if (m_highlightZone.size())
{
m_highlightZone.clear();
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
}
}
@ -458,8 +458,8 @@ WorkArea::FlashZones() noexcept
if (m_window)
{
SetAsTopmostWindow();
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), {}, m_zoneColors);
m_zonesOverlay->Flash();
m_zoneWindowDrawing->DrawActiveZoneSet(m_zoneSet->GetZones(), {}, m_zoneColors);
m_zoneWindowDrawing->Flash();
}
}

View file

@ -108,14 +108,8 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IWorkArea :
* @returns Zone index of the window
*/
IFACEMETHOD_(ZoneIndexSet, GetWindowZoneIndexes)(HWND window) const = 0;
/**
* Show a drawing of the zones in the work area.
*/
IFACEMETHOD_(void, ShowZonesOverlay)() = 0;
/**
* Hide the drawing of the zones in the work area.
*/
IFACEMETHOD_(void, HideZonesOverlay)() = 0;
IFACEMETHOD_(void, ShowZoneWindow)() = 0;
IFACEMETHOD_(void, HideZoneWindow)() = 0;
/**
* Update currently active zone layout for this work area.
*/

View file

@ -594,17 +594,19 @@ ZoneSet::CycleTabs(HWND window, bool reverse) noexcept
for (;;)
{
auto next = GetNextTab(indexSet, window, reverse);
if (next == NULL)
{
break;
}
// Determine whether the window still exists
if (!IsWindow(next))
auto success = SetForegroundWindow(next);
if (!success && GetLastError() == ERROR_INVALID_WINDOW_HANDLE)
{
// Dismiss the encountered window since it was probably closed
DismissWindow(next);
continue;
}
SwitchToWindow(next);
break;
}
}

View file

@ -1,5 +1,5 @@
#include "pch.h"
#include "ZonesOverlay.h"
#include "ZoneWindowDrawing.h"
#include <algorithm>
#include <map>
@ -7,6 +7,7 @@
#include <vector>
#include <common/logger/call_tracer.h>
#include <common/logger/logger.h>
namespace
{
@ -19,7 +20,7 @@ namespace NonLocalizable
const wchar_t SegoeUiFont[] = L"Segoe ui";
}
float ZonesOverlay::GetAnimationAlpha()
float ZoneWindowDrawing::GetAnimationAlpha()
{
// Lock is held by the caller
@ -40,7 +41,7 @@ float ZonesOverlay::GetAnimationAlpha()
return std::clamp(millis / FadeInDurationMillis, 0.001f, 1.f);
}
ID2D1Factory* ZonesOverlay::GetD2DFactory()
ID2D1Factory* ZoneWindowDrawing::GetD2DFactory()
{
static auto pD2DFactory = [] {
ID2D1Factory* res = nullptr;
@ -50,7 +51,7 @@ ID2D1Factory* ZonesOverlay::GetD2DFactory()
return pD2DFactory;
}
IDWriteFactory* ZonesOverlay::GetWriteFactory()
IDWriteFactory* ZoneWindowDrawing::GetWriteFactory()
{
static auto pDWriteFactory = [] {
IUnknown* res = nullptr;
@ -60,7 +61,7 @@ IDWriteFactory* ZonesOverlay::GetWriteFactory()
return pDWriteFactory;
}
D2D1_COLOR_F ZonesOverlay::ConvertColor(COLORREF color)
D2D1_COLOR_F ZoneWindowDrawing::ConvertColor(COLORREF color)
{
return D2D1::ColorF(GetRValue(color) / 255.f,
GetGValue(color) / 255.f,
@ -68,12 +69,12 @@ D2D1_COLOR_F ZonesOverlay::ConvertColor(COLORREF color)
1.f);
}
D2D1_RECT_F ZonesOverlay::ConvertRect(RECT rect)
D2D1_RECT_F ZoneWindowDrawing::ConvertRect(RECT rect)
{
return D2D1::RectF((float)rect.left + 0.5f, (float)rect.top + 0.5f, (float)rect.right - 0.5f, (float)rect.bottom - 0.5f);
}
ZonesOverlay::ZonesOverlay(HWND window)
ZoneWindowDrawing::ZoneWindowDrawing(HWND window)
{
HRESULT hr;
m_window = window;
@ -83,7 +84,7 @@ ZonesOverlay::ZonesOverlay(HWND window)
// Obtain the size of the drawing area.
if (!GetClientRect(window, &m_clientRect))
{
Logger::error("couldn't initialize ZonesOverlay: GetClientRect failed");
Logger::error("couldn't initialize ZoneWindowDrawing: GetClientRect failed");
return;
}
@ -102,14 +103,14 @@ ZonesOverlay::ZonesOverlay(HWND window)
if (!SUCCEEDED(hr))
{
Logger::error("couldn't initialize ZonesOverlay: CreateHwndRenderTarget failed with {}", hr);
Logger::error("couldn't initialize ZoneWindowDrawing: CreateHwndRenderTarget failed with {}", hr);
return;
}
m_renderThread = std::thread([this]() { RenderLoop(); });
}
ZonesOverlay::RenderResult ZonesOverlay::Render()
ZoneWindowDrawing::RenderResult ZoneWindowDrawing::Render()
{
std::unique_lock lock(m_mutex);
@ -192,7 +193,7 @@ ZonesOverlay::RenderResult ZonesOverlay::Render()
return RenderResult::Ok;
}
void ZonesOverlay::RenderLoop()
void ZoneWindowDrawing::RenderLoop()
{
while (!m_abortThread)
{
@ -211,7 +212,7 @@ void ZonesOverlay::RenderLoop()
}
}
void ZonesOverlay::Hide()
void ZoneWindowDrawing::Hide()
{
_TRACER_;
bool shouldHideWindow = true;
@ -228,7 +229,7 @@ void ZonesOverlay::Hide()
}
}
void ZonesOverlay::Show()
void ZoneWindowDrawing::Show()
{
_TRACER_;
bool shouldShowWindow = true;
@ -256,7 +257,7 @@ void ZonesOverlay::Show()
m_cv.notify_all();
}
void ZonesOverlay::Flash()
void ZoneWindowDrawing::Flash()
{
_TRACER_;
bool shouldShowWindow = true;
@ -276,9 +277,9 @@ void ZonesOverlay::Flash()
m_cv.notify_all();
}
void ZonesOverlay::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
const ZoneIndexSet& highlightZones,
const ZoneColors& colors)
void ZoneWindowDrawing::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
const ZoneIndexSet& highlightZones,
const ZoneColors& colors)
{
_TRACER_;
std::unique_lock lock(m_mutex);
@ -344,7 +345,7 @@ void ZonesOverlay::DrawActiveZoneSet(const IZoneSet::ZonesMap& zones,
}
}
ZonesOverlay::~ZonesOverlay()
ZoneWindowDrawing::~ZoneWindowDrawing()
{
{
std::unique_lock lock(m_mutex);

View file

@ -13,7 +13,7 @@
#include "FancyZones.h"
#include "ZoneColors.h"
class ZonesOverlay
class ZoneWindowDrawing
{
struct DrawableRect
{
@ -60,8 +60,8 @@ class ZonesOverlay
public:
~ZonesOverlay();
ZonesOverlay(HWND window);
~ZoneWindowDrawing();
ZoneWindowDrawing(HWND window);
void Hide();
void Show();
void Flash();

View file

@ -369,22 +369,6 @@ namespace FancyZonesUtils
::SetWindowPlacement(window, &placement);
}
void SwitchToWindow(HWND window) noexcept
{
// Check if the window is minimized
if (IsIconic(window))
{
// Show the window since SetForegroundWindow fails on minimized windows
ShowWindow(window, SW_RESTORE);
}
// This is a hack to bypass the restriction on setting the foreground window
INPUT inputs[1] = { { .type = INPUT_MOUSE } };
SendInput(ARRAYSIZE(inputs), inputs, sizeof(INPUT));
SetForegroundWindow(window);
}
bool HasNoVisibleOwner(HWND window) noexcept
{
auto owner = GetWindow(window, GW_OWNER);

View file

@ -195,8 +195,6 @@ namespace FancyZonesUtils
// Parameter rect must be in screen coordinates (e.g. obtained from GetWindowRect)
void SizeWindowToRect(HWND window, RECT rect) noexcept;
void SwitchToWindow(HWND window) noexcept;
bool HasNoVisibleOwner(HWND window) noexcept;
bool IsStandardWindow(HWND window);
bool IsCandidateForLastKnownZone(HWND window, const std::vector<std::wstring>& excludedApps) noexcept;

View file

@ -3,8 +3,6 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows.Media.Imaging;
namespace ImageResizer.Extensions
@ -45,14 +43,7 @@ namespace ImageResizer.Extensions
try
{
if (metadata.ContainsQuery(query))
{
return metadata.GetQuery(query);
}
else
{
return null;
}
return metadata.GetQuery(query);
}
catch (NotSupportedException)
{
@ -60,179 +51,5 @@ namespace ImageResizer.Extensions
return null;
}
}
public static void RemoveQuerySafe(this BitmapMetadata metadata, string query)
{
if (metadata == null || string.IsNullOrWhiteSpace(query))
{
return;
}
try
{
if (metadata.ContainsQuery(query))
{
metadata.RemoveQuery(query);
}
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Debug.WriteLine($"Exception while trying to remove metadata entry at position: {query}");
Debug.WriteLine(ex);
}
}
public static void SetQuerySafe(this BitmapMetadata metadata, string query, object value)
{
if (metadata == null || string.IsNullOrWhiteSpace(query) || value == null)
{
return;
}
try
{
metadata.SetQuery(query, value);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Debug.WriteLine($"Exception while trying to set metadata {value} at position: {query}");
Debug.WriteLine(ex);
}
}
/// <summary>
/// Gets all metadata
/// Iterates recursively through all metadata
/// </summary>
public static List<(string metadataPath, object value)> GetListOfMetadata(this BitmapMetadata metadata)
{
var listOfAllMetadata = new List<(string metadataPath, object value)>();
GetMetadataRecursively(metadata, string.Empty);
return listOfAllMetadata;
void GetMetadataRecursively(BitmapMetadata metadata, string query)
{
foreach (string relativeQuery in metadata)
{
string absolutePath = query + relativeQuery;
object metadataQueryReader = null;
try
{
metadataQueryReader = GetQueryWithPreCheck(metadata, relativeQuery);
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
Debug.WriteLine($"Removing corrupt metadata property {absolutePath}. Skipping metadata entry | {ex.Message}");
Debug.WriteLine(ex);
}
if (metadataQueryReader != null)
{
listOfAllMetadata.Add((absolutePath, metadataQueryReader));
}
else
{
Debug.WriteLine($"No metadata found for query {absolutePath}. Skipping empty null entry because its invalid.");
}
if (metadataQueryReader is BitmapMetadata innerMetadata)
{
GetMetadataRecursively(innerMetadata, absolutePath);
}
}
}
object GetQueryWithPreCheck(BitmapMetadata metadata, string query)
{
if (metadata == null || string.IsNullOrWhiteSpace(query))
{
return null;
}
if (metadata.ContainsQuery(query))
{
return metadata.GetQuery(query);
}
else
{
return null;
}
}
}
/// <summary>
/// Prints all metadata to debug console
/// </summary>
/// <remarks>
/// Intented for debug only!!!
/// </remarks>
public static void PrintsAllMetadataToDebugOutput(this BitmapMetadata metadata)
{
if (metadata == null)
{
Debug.WriteLine($"Metadata was null.");
}
var listOfMetadata = metadata.GetListOfMetadataForDebug();
foreach (var metadataItem in listOfMetadata)
{
// Debug.WriteLine($"modifiableMetadata.RemoveQuerySafe(\"{metadataItem.metadataPath}\");");
Debug.WriteLine($"{metadataItem.metadataPath} | {metadataItem.value}");
}
}
/// <summary>
/// Gets all metadata
/// Iterates recursively through all metadata
/// </summary>
/// <remarks>
/// Intented for debug only!!!
/// </remarks>
public static List<(string metadataPath, object value)> GetListOfMetadataForDebug(this BitmapMetadata metadata)
{
var listOfAllMetadata = new List<(string metadataPath, object value)>();
GetMetadataRecursively(metadata, string.Empty);
return listOfAllMetadata;
void GetMetadataRecursively(BitmapMetadata metadata, string query)
{
foreach (string relativeQuery in metadata)
{
string absolutePath = query + relativeQuery;
object metadataQueryReader = null;
try
{
metadataQueryReader = metadata.GetQuerySafe(relativeQuery);
listOfAllMetadata.Add((absolutePath, metadataQueryReader));
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
listOfAllMetadata.Add((absolutePath, $"######## INVALID METADATA: {ex.Message}"));
Debug.WriteLine(ex);
}
if (metadataQueryReader is BitmapMetadata innerMetadata)
{
GetMetadataRecursively(innerMetadata, absolutePath);
}
}
}
}
}
}

View file

@ -3,7 +3,6 @@
// See the LICENSE file in the project root for more information. Code forked from Brice Lambson's https://github.com/bricelam/ImageResizer/
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.IO.Abstractions;
@ -84,36 +83,11 @@ namespace ImageResizer.Models
try
{
// Detect whether metadata can copied successfully
var modifiableMetadata = metadata.Clone();
#if DEBUG
Debug.WriteLine($"### Processing metadata of file {_file}");
modifiableMetadata.PrintsAllMetadataToDebugOutput();
#endif
// read all metadata and build up metadata object from the scratch. Discard invalid (unreadable/unwritable) metadata.
var newMetadata = new BitmapMetadata(metadata.Format);
var listOfMetadata = modifiableMetadata.GetListOfMetadata();
foreach (var (metadataPath, value) in listOfMetadata)
{
if (value is BitmapMetadata bitmapMetadata)
{
var innerMetadata = new BitmapMetadata(bitmapMetadata.Format);
newMetadata.SetQuerySafe(metadataPath, innerMetadata);
}
else
{
newMetadata.SetQuerySafe(metadataPath, value);
}
}
metadata = newMetadata;
_ = metadata.Clone();
}
catch (ArgumentException ex)
catch (ArgumentException)
{
metadata = null;
Debug.WriteLine(ex);
}
}
@ -131,9 +105,9 @@ namespace ImageResizer.Models
encoder.Frames.Add(
BitmapFrame.Create(
Transform(originalFrame),
originalFrame.Thumbnail,
thumbnail: null,
metadata,
originalFrame.ColorContexts));
colorContexts: null));
}
path = GetDestinationPath(encoder);

View file

@ -17,7 +17,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\UnitConverter\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Community.UnitConverter\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@ -30,7 +30,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\UnitConverter\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Community.UnitConverter\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View file

@ -17,7 +17,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Folder\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.Plugin.Folder\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@ -30,7 +30,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Folder\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Microsoft.Plugin.Folder\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View file

@ -17,7 +17,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Indexer\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.Plugin.Indexer\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@ -30,7 +30,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Indexer\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Microsoft.Plugin.Indexer\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View file

@ -18,7 +18,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Program\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.Plugin.Program\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@ -31,7 +31,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Program\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Microsoft.Plugin.Program\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View file

@ -17,7 +17,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Shell\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.Plugin.Shell\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@ -29,7 +29,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Shell\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Microsoft.Plugin.Shell\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View file

@ -11,85 +11,62 @@ namespace Microsoft.Plugin.Uri.UnitTests.UriHelper
public class ExtendedUriParserTests
{
[DataTestMethod]
[DataRow("google.com", true, "https://google.com/", true)]
[DataRow("http://google.com", true, "http://google.com/", true)]
[DataRow("localhost", true, "https://localhost/", true)]
[DataRow("http://localhost", true, "http://localhost/", true)]
[DataRow("127.0.0.1", true, "https://127.0.0.1/", true)]
[DataRow("http://127.0.0.1", true, "http://127.0.0.1/", true)]
[DataRow("http://127.0.0.1:80", true, "http://127.0.0.1/", true)]
[DataRow("127", false, null, false)]
[DataRow("", false, null, false)]
[DataRow("https://google.com", true, "https://google.com/", true)]
[DataRow("ftps://google.com", true, "ftps://google.com/", false)]
[DataRow(null, false, null, false)]
[DataRow("bing.com/search?q=gmx", true, "https://bing.com/search?q=gmx", true)]
[DataRow("http://bing.com/search?q=gmx", true, "http://bing.com/search?q=gmx", true)]
[DataRow("h", true, "https://h/", true)]
[DataRow("http://h", true, "http://h/", true)]
[DataRow("ht", true, "https://ht/", true)]
[DataRow("http://ht", true, "http://ht/", true)]
[DataRow("htt", true, "https://htt/", true)]
[DataRow("http://htt", true, "http://htt/", true)]
[DataRow("http", true, "https://http/", true)]
[DataRow("http://http", true, "http://http/", true)]
[DataRow("http:", false, null, false)]
[DataRow("http:/", false, null, false)]
[DataRow("http://", false, null, false)]
[DataRow("http://t", true, "http://t/", true)]
[DataRow("http://te", true, "http://te/", true)]
[DataRow("http://tes", true, "http://tes/", true)]
[DataRow("http://test", true, "http://test/", true)]
[DataRow("http://test.", false, null, false)]
[DataRow("http://test.c", true, "http://test.c/", true)]
[DataRow("http://test.co", true, "http://test.co/", true)]
[DataRow("http://test.com", true, "http://test.com/", true)]
[DataRow("http:3", true, "https://http:3/", true)]
[DataRow("http://http:3", true, "http://http:3/", true)]
[DataRow("[::]", true, "https://[::]/", true)]
[DataRow("http://[::]", true, "http://[::]/", true)]
[DataRow("[2001:0DB8::1]", true, "https://[2001:db8::1]/", true)]
[DataRow("http://[2001:0DB8::1]", true, "http://[2001:db8::1]/", true)]
[DataRow("[2001:0DB8::1]:80", true, "https://[2001:db8::1]/", true)]
[DataRow("http://[2001:0DB8::1]:80", true, "http://[2001:db8::1]/", true)]
[DataRow("mailto:example@mail.com", true, "mailto:example@mail.com", false)]
[DataRow("tel:411", true, "tel:411", false)]
[DataRow("ftp://example.com", true, "ftp://example.com/", false)]
[DataRow("google.com", true, "https://google.com/")]
[DataRow("http://google.com", true, "http://google.com/")]
[DataRow("localhost", true, "https://localhost/")]
[DataRow("http://localhost", true, "http://localhost/")]
[DataRow("127.0.0.1", true, "https://127.0.0.1/")]
[DataRow("http://127.0.0.1", true, "http://127.0.0.1/")]
[DataRow("http://127.0.0.1:80", true, "http://127.0.0.1/")]
[DataRow("127", false, null)]
[DataRow("", false, null)]
[DataRow("https://google.com", true, "https://google.com/")]
[DataRow("ftps://google.com", true, "ftps://google.com/")]
[DataRow(null, false, null)]
[DataRow("bing.com/search?q=gmx", true, "https://bing.com/search?q=gmx")]
[DataRow("http://bing.com/search?q=gmx", true, "http://bing.com/search?q=gmx")]
[DataRow("h", true, "https://h/")]
[DataRow("http://h", true, "http://h/")]
[DataRow("ht", true, "https://ht/")]
[DataRow("http://ht", true, "http://ht/")]
[DataRow("htt", true, "https://htt/")]
[DataRow("http://htt", true, "http://htt/")]
[DataRow("http", true, "https://http/")]
[DataRow("http://http", true, "http://http/")]
[DataRow("http:", false, null)]
[DataRow("http:/", false, null)]
[DataRow("http://", false, null)]
[DataRow("http://t", true, "http://t/")]
[DataRow("http://te", true, "http://te/")]
[DataRow("http://tes", true, "http://tes/")]
[DataRow("http://test", true, "http://test/")]
[DataRow("http://test.", false, null)]
[DataRow("http://test.c", true, "http://test.c/")]
[DataRow("http://test.co", true, "http://test.co/")]
[DataRow("http://test.com", true, "http://test.com/")]
[DataRow("http:3", true, "https://http:3/")]
[DataRow("http://http:3", true, "http://http:3/")]
[DataRow("[::]", true, "https://[::]/")]
[DataRow("http://[::]", true, "http://[::]/")]
[DataRow("[2001:0DB8::1]", true, "https://[2001:db8::1]/")]
[DataRow("http://[2001:0DB8::1]", true, "http://[2001:db8::1]/")]
[DataRow("[2001:0DB8::1]:80", true, "https://[2001:db8::1]/")]
[DataRow("http://[2001:0DB8::1]:80", true, "http://[2001:db8::1]/")]
[DataRow("mailto:example@mail.com", true, "mailto:example@mail.com")]
[DataRow("tel:411", true, "tel:411")]
[DataRow("ftp://example.com", true, "ftp://example.com/")]
[DataRow("example.com:443", true, "example.com:443")]
// This has been parsed as an application URI. Linked issue: #14260
[DataRow("example.com:443", true, "example.com:443", false)]
[DataRow("mailto:", true, "mailto:", false)]
[DataRow("mailto:/", false, null, false)]
[DataRow("ms-settings:", true, "ms-settings:", false)]
[DataRow("ms-settings:/", false, null, false)]
[DataRow("ms-settings://", false, null, false)]
[DataRow("ms-settings://privacy", true, "ms-settings://privacy/", false)]
[DataRow("ms-settings://privacy/", true, "ms-settings://privacy/", false)]
[DataRow("ms-settings:privacy", true, "ms-settings:privacy", false)]
[DataRow("ms-settings:powersleep", true, "ms-settings:powersleep", false)]
[DataRow("microsoft-edge:http://google.com", true, "microsoft-edge:http://google.com", false)]
[DataRow("microsoft-edge:https://google.com", true, "microsoft-edge:https://google.com", false)]
[DataRow("microsoft-edge:google.com", true, "microsoft-edge:google.com", false)]
[DataRow("microsoft-edge:google.com/", true, "microsoft-edge:google.com/", false)]
[DataRow("microsoft-edge:https://google.com/", true, "microsoft-edge:https://google.com/", false)]
[DataRow("ftp://user:password@localhost:8080", true, "ftp://user:password@localhost:8080/", false)]
[DataRow("ftp://user:password@localhost:8080/", true, "ftp://user:password@localhost:8080/", false)]
[DataRow("ftp://user:password@google.com", true, "ftp://user:password@google.com/", false)]
[DataRow("ftp://user:password@google.com:2121", true, "ftp://user:password@google.com:2121/", false)]
[DataRow("ftp://user:password@1.1.1.1", true, "ftp://user:password@1.1.1.1/", false)]
[DataRow("ftp://user:password@1.1.1.1:2121", true, "ftp://user:password@1.1.1.1:2121/", false)]
public void TryParseCanParseHostName(string query, bool expectedSuccess, string expectedResult, bool expectedIsWebUri)
public void TryParseCanParseHostName(string query, bool expectedSuccess, string expectedResult)
{
// Arrange
var parser = new ExtendedUriParser();
// Act
var success = parser.TryParse(query, out var result, out var isWebUriResult);
var success = parser.TryParse(query, out var result);
// Assert
Assert.AreEqual(expectedResult, result?.ToString());
Assert.AreEqual(expectedIsWebUri, isWebUriResult);
Assert.AreEqual(expectedSuccess, success);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -6,6 +6,6 @@ namespace Microsoft.Plugin.Uri.Interfaces
{
public interface IUriParser
{
bool TryParse(string input, out System.Uri result, out bool isWebUri);
bool TryParse(string input, out System.Uri result);
}
}

View file

@ -63,15 +63,17 @@ namespace Microsoft.Plugin.Uri
{
results.Add(new Result
{
Title = Properties.Resources.Microsoft_plugin_uri_open,
Title = Properties.Resources.Microsoft_plugin_uri_default_browser,
SubTitle = BrowserPath,
IcoPath = DefaultIconPath,
IcoPath = _uriSettings.ShowBrowserIcon
? BrowserIconPath
: DefaultIconPath,
Action = action =>
{
if (!Helper.OpenInShell(BrowserPath))
{
var title = $"Plugin: {Properties.Resources.Microsoft_plugin_uri_plugin_name}";
var message = $"{Properties.Resources.Microsoft_plugin_uri_open_failed}: ";
var message = $"{Properties.Resources.Microsoft_plugin_default_browser_open_failed}: ";
Context.API.ShowMsg(title, message);
return false;
}
@ -83,19 +85,16 @@ namespace Microsoft.Plugin.Uri
}
if (!string.IsNullOrEmpty(query?.Search)
&& _uriParser.TryParse(query.Search, out var uriResult, out var isWebUri)
&& _uriParser.TryParse(query.Search, out var uriResult)
&& _uriResolver.IsValidHost(uriResult))
{
var uriResultString = uriResult.ToString();
var isWebUriBool = isWebUri;
results.Add(new Result
{
Title = uriResultString,
SubTitle = isWebUriBool
? Properties.Resources.Microsoft_plugin_uri_website
: Properties.Resources.Microsoft_plugin_uri_open,
IcoPath = isWebUriBool
SubTitle = Properties.Resources.Microsoft_plugin_uri_website,
IcoPath = _uriSettings.ShowBrowserIcon
? BrowserIconPath
: DefaultIconPath,
Action = action =>
@ -119,7 +118,7 @@ namespace Microsoft.Plugin.Uri
private static bool IsActivationKeyword(Query query)
{
return !string.IsNullOrEmpty(query?.ActionKeyword)
&& query?.ActionKeyword == query?.RawQuery;
&& query?.ActionKeyword == query?.RawQuery;
}
private bool IsDefaultBrowserSet()
@ -156,23 +155,16 @@ namespace Microsoft.Plugin.Uri
UpdateBrowserIconPath(newTheme);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage(
"Design",
"CA1031:Do not catch general exception types",
Justification = "We want to keep the process alive but will log the exception")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "We want to keep the process alive but will log the exception")]
private void UpdateBrowserIconPath(Theme newTheme)
{
try
{
var progId = _registryWrapper.GetRegistryValue(
"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice",
"ProgId");
var progId = _registryWrapper.GetRegistryValue("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\http\\UserChoice", "ProgId");
var programLocation =
// Resolve App Icon (UWP)
_registryWrapper.GetRegistryValue(
"HKEY_CLASSES_ROOT\\" + progId + "\\Application",
"ApplicationIcon")
_registryWrapper.GetRegistryValue("HKEY_CLASSES_ROOT\\" + progId + "\\Application", "ApplicationIcon")
// Resolves default file association icon (UWP + Normal)
?? _registryWrapper.GetRegistryValue("HKEY_CLASSES_ROOT\\" + progId + "\\DefaultIcon", null);
@ -182,21 +174,14 @@ namespace Microsoft.Plugin.Uri
if (programLocation.StartsWith("@", StringComparison.Ordinal))
{
var directProgramLocationStringBuilder = new StringBuilder(128);
if (NativeMethods.SHLoadIndirectString(
programLocation,
directProgramLocationStringBuilder,
(uint)directProgramLocationStringBuilder.Capacity,
IntPtr.Zero) ==
if (NativeMethods.SHLoadIndirectString(programLocation, directProgramLocationStringBuilder, (uint)directProgramLocationStringBuilder.Capacity, IntPtr.Zero) ==
NativeMethods.Hresult.Ok)
{
// Check if there's a postfix with contract-white/contrast-black icon is available and use that instead
var directProgramLocation = directProgramLocationStringBuilder.ToString();
var themeIcon = newTheme == Theme.Light || newTheme == Theme.HighContrastWhite
? "contrast-white"
: "contrast-black";
var themeIcon = newTheme == Theme.Light || newTheme == Theme.HighContrastWhite ? "contrast-white" : "contrast-black";
var extension = Path.GetExtension(directProgramLocation);
var themedProgLocation =
$"{directProgramLocation.Substring(0, directProgramLocation.Length - extension.Length)}_{themeIcon}{extension}";
var themedProgLocation = $"{directProgramLocation.Substring(0, directProgramLocation.Length - extension.Length)}_{themeIcon}{extension}";
BrowserIconPath = File.Exists(themedProgLocation)
? themedProgLocation
: directProgramLocation;

View file

@ -17,7 +17,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Uri\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.Plugin.Uri\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@ -30,7 +30,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Uri\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Microsoft.Plugin.Uri\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View file

@ -70,7 +70,7 @@ namespace Microsoft.Plugin.Uri.Properties {
}
/// <summary>
/// Looks up a localized string similar to Open default browser.
/// Looks up a localized string similar to Open Default Browser.
/// </summary>
public static string Microsoft_plugin_uri_default_browser {
get {
@ -79,16 +79,7 @@ namespace Microsoft.Plugin.Uri.Properties {
}
/// <summary>
/// Looks up a localized string similar to Open URI.
/// </summary>
public static string Microsoft_plugin_uri_open {
get {
return ResourceManager.GetString("Microsoft_plugin_uri_open", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Failed to open URI.
/// Looks up a localized string similar to Failed to open URL.
/// </summary>
public static string Microsoft_plugin_uri_open_failed {
get {

View file

@ -123,11 +123,8 @@
<data name="Microsoft_plugin_uri_default_browser" xml:space="preserve">
<value>Open default browser</value>
</data>
<data name="Microsoft_plugin_uri_open" xml:space="preserve">
<value>Open URI</value>
</data>
<data name="Microsoft_plugin_uri_open_failed" xml:space="preserve">
<value>Failed to open URI</value>
<value>Failed to open URL</value>
</data>
<data name="Microsoft_plugin_uri_plugin_description" xml:space="preserve">
<value>Opens URLs and UNC network shares.</value>
@ -138,4 +135,4 @@
<data name="Microsoft_plugin_uri_website" xml:space="preserve">
<value>Open in default browser</value>
</data>
</root>
</root>

View file

@ -10,37 +10,22 @@ namespace Microsoft.Plugin.Uri.UriHelper
{
public class ExtendedUriParser : IUriParser
{
public bool TryParse(string input, out System.Uri result, out bool isWebUri)
public bool TryParse(string input, out System.Uri result)
{
if (string.IsNullOrEmpty(input))
{
result = default;
isWebUri = false;
return false;
}
// Handling URL with only scheme, typically mailto or application uri.
// Do nothing, return the result without urlBuilder
if (input.EndsWith(":", StringComparison.OrdinalIgnoreCase)
&& !input.StartsWith("http", StringComparison.OrdinalIgnoreCase)
&& !input.Contains("/", StringComparison.OrdinalIgnoreCase)
&& !input.All(char.IsDigit))
{
result = new System.Uri(input);
isWebUri = false;
return true;
}
// Handle common cases UriBuilder does not handle
// Using CurrentCulture since this is a user typed string
if (input.EndsWith(":", StringComparison.CurrentCulture)
|| input.EndsWith(".", StringComparison.CurrentCulture)
|| input.EndsWith(":/", StringComparison.CurrentCulture)
|| input.EndsWith("://", StringComparison.CurrentCulture)
|| input.All(char.IsDigit))
{
result = default;
isWebUri = false;
return false;
}
@ -50,31 +35,27 @@ namespace Microsoft.Plugin.Uri.UriHelper
var hadDefaultPort = urlBuilder.Uri.IsDefaultPort;
urlBuilder.Port = hadDefaultPort ? -1 : urlBuilder.Port;
if (input.StartsWith("HTTP://", StringComparison.OrdinalIgnoreCase))
if (input.Contains("HTTP://", StringComparison.OrdinalIgnoreCase))
{
urlBuilder.Scheme = System.Uri.UriSchemeHttp;
isWebUri = true;
}
else if (input.Contains(":", StringComparison.OrdinalIgnoreCase) &&
!input.StartsWith("http", StringComparison.OrdinalIgnoreCase) &&
!input.Contains("http", StringComparison.OrdinalIgnoreCase) &&
!input.Contains("[", StringComparison.OrdinalIgnoreCase))
{
// Do nothing, leave unchanged
isWebUri = false;
}
else
{
urlBuilder.Scheme = System.Uri.UriSchemeHttps;
isWebUri = true;
}
result = urlBuilder.Uri;
return true;
}
catch (UriFormatException)
catch (System.UriFormatException)
{
result = default;
isWebUri = false;
return false;
}
}

View file

@ -17,7 +17,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\WindowWalker\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@ -29,7 +29,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\WindowWalker\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Microsoft.Plugin.WindowWalker\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View file

@ -15,7 +15,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Registry\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
@ -27,7 +27,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Registry\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.Registry\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View file

@ -18,7 +18,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\WindowsSettings\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Debug\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<Optimize>false</Optimize>
<DebugType>full</DebugType>
@ -31,7 +31,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\WindowsSettings\</OutputPath>
<OutputPath>..\..\..\..\..\x64\Release\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>

View file

@ -134,7 +134,6 @@ bool AppWindow::OnCreate(HWND, LPCREATESTRUCT) noexcept
try
{
PopulateExplorerItems();
UpdateCounts();
SetHandlers();
ReadSettings();
}
@ -247,6 +246,11 @@ void AppWindow::PopulateExplorerItems()
m_prManager->GetVisibleItemCount(&count);
Logger::debug(L"Number of visible items: {}", count);
UINT currDepth = 0;
std::stack<UINT> parents{};
UINT prevId = 0;
parents.push(0);
for (UINT i = 0; i < count; ++i)
{
CComPtr<IPowerRenameItem> renameItem;
@ -270,8 +274,23 @@ void AppWindow::PopulateExplorerItems()
bool isSubFolderContent = false;
winrt::check_hresult(renameItem->GetIsFolder(&isFolder));
if (depth > currDepth)
{
parents.push(prevId);
currDepth = depth;
}
else
{
while (currDepth > depth)
{
parents.pop();
currDepth--;
}
currDepth = depth;
}
m_mainUserControl.AddExplorerItem(
id, originalName, newName == nullptr ? hstring{} : hstring{ newName }, isFolder ? 0 : 1, depth, selected);
id, originalName, newName == nullptr ? hstring{} : hstring{ newName }, isFolder ? 0 : 1, parents.top(), selected);
prevId = id;
}
}
}
@ -619,7 +638,6 @@ void AppWindow::SwitchView()
m_prManager->SwitchFilter(0);
PopulateExplorerItems();
UpdateCounts();
}
void AppWindow::Rename(bool closeWindow)
@ -833,12 +851,11 @@ void AppWindow::UpdateCounts()
m_selectedCount = selectedCount;
m_renamingCount = renamingCount;
// Update counts UI elements if/when added
// Update Rename button state
m_mainUserControl.UIUpdatesItem().ButtonRenameEnabled(renamingCount > 0);
}
m_mainUserControl.UIUpdatesItem().OriginalCount(std::to_wstring(m_mainUserControl.ExplorerItems().Size()));
m_mainUserControl.UIUpdatesItem().RenamedCount(std::to_wstring(m_renamingCount));
}
HRESULT AppWindow::OnItemAdded(_In_ IPowerRenameItem* renameItem)
@ -861,6 +878,7 @@ HRESULT AppWindow::OnUpdate(_In_ IPowerRenameItem* renameItem)
}
}
UpdateCounts();
return S_OK;
}
@ -917,7 +935,6 @@ HRESULT AppWindow::OnRegExCompleted(_In_ DWORD threadId)
}
}
UpdateCounts();
return S_OK;
}

View file

@ -1,7 +1,6 @@
//Microsoft Visual C++ generated resource script.
⼀⼀ഀ<EFBFBD>
⌀椀渀挀氀甀搀攀 ∀爀攀猀漀甀爀挀攀⸀栀∀ഀ<EFBFBD>
#include "../../../common/version/version.h"
<EFBFBD>
⌀搀攀昀椀渀攀 䄀倀匀吀唀䐀䤀伀开刀䔀䄀䐀伀一䰀夀开匀夀䴀䈀伀䰀匀ഀ<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
@ -31,6 +30,70 @@
䤀䐀䤀开倀伀圀䔀刀刀䔀一䄀䴀䔀唀䤀䠀伀匀吀       䤀䌀伀一         ∀倀漀眀攀爀刀攀渀愀洀攀唀䤀䠀漀猀琀⸀椀挀漀∀ഀ<EFBFBD>
䤀䐀䤀开匀䴀䄀䰀䰀                   䤀䌀伀一         ∀猀洀愀氀氀⸀椀挀漀∀ഀ<EFBFBD>
<EFBFBD>
/////////////////////////////////////////////////////////////////////////////
//
// Menu
//
IDC_POWERRENAMEUIHOST MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "E&xit", IDM_EXIT
END
POPUP "&Help"
BEGIN
MENUITEM "&About ...", IDM_ABOUT
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDC_POWERRENAMEUIHOST ACCELERATORS
BEGIN
"?", IDM_ABOUT, ASCII, ALT
"/", IDM_ABOUT, ASCII, ALT
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_ABOUTBOX DIALOGEX 0, 0, 170, 62
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "About PowerRenameUIHost"
FONT 8, "MS Shell Dlg"
BEGIN
ICON IDR_MAINFRAME,IDC_STATIC,14,14,21,20
LTEXT "PowerRenameUIHost, Version 1.0",IDC_STATIC,42,14,114,8,SS_NOPREFIX
LTEXT "Copyright (c) 2021",IDC_STATIC,42,26,114,8
DEFPUSHBUTTON "OK",IDOK,113,41,50,14,WS_GROUP
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_ABOUTBOX, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 163
TOPMARGIN, 7
BOTTOMMARGIN, 55
END
END
#endif // APSTUDIO_INVOKED
⌀椀昀搀攀昀 䄀倀匀吀唀䐀䤀伀开䤀一嘀伀䬀䔀䐀ഀ<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
⼀⼀ഀ<EFBFBD>
@ -74,41 +137,14 @@
⌀攀渀搀椀昀ഀ<EFBFBD>
⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀⼀ഀ<EFBFBD>
<EFBFBD>
///////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
⼀⼀ഀ<EFBFBD>
// Version
// Generated from the TEXTINCLUDE resource.
⼀⼀ഀ<EFBFBD>
<EFBFBD>
VS_VERSION_INFO VERSIONINFO
FILEVERSION FILE_VERSION
PRODUCTVERSION PRODUCT_VERSION
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", COMPANY_NAME
VALUE "FileDescription", "PowerToys PowerRename"
VALUE "FileVersion", FILE_VERSION_STRING
VALUE "InternalName", "PowerRename"
VALUE "LegalCopyright", COPYRIGHT_NOTE
VALUE "OriginalFilename", "PowerRename.exe"
VALUE "ProductName", PRODUCT_NAME
VALUE "ProductVersion", PRODUCT_VERSION_STRING
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED
<EFBFBD>

View file

@ -615,6 +615,453 @@
</Setter>
</Style>
<Style TargetType="TextBox" x:Key="AutoSuggestBoxTextBoxStyle">
<Setter Property="MinWidth" Value="{ThemeResource TextControlThemeMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource TextControlThemeMinHeight}" />
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}" />
<Setter Property="Background" Value="{ThemeResource TextControlBackground}" />
<Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}" />
<Setter Property="SelectionHighlightColor" Value="{ThemeResource TextControlSelectionHighlightColor}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="AcceptsReturn" Value="False" />
<Setter Property="ScrollViewer.HorizontalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.VerticalScrollMode" Value="Auto" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Hidden" />
<Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
<Setter Property="Padding" Value="{ThemeResource TextControlThemePadding}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TextBox">
<Grid>
<Grid.Resources>
<Style x:Name="DeleteButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="ButtonLayoutGrid"
BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{ThemeResource TextControlButtonBackground}"
Margin="{StaticResource AutoSuggestBoxDeleteButtonMargin}"
contract7Present:CornerRadius="{ThemeResource ControlCornerRadius}"
contract7NotPresent:CornerRadius="{ThemeResource ControlCornerRadius}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ButtonLayoutGrid" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GlyphElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ButtonLayoutGrid"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock x:Name="GlyphElement"
Foreground="{ThemeResource TextControlButtonForeground}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
FontStyle="Normal"
FontSize="{ThemeResource AutoSuggestBoxIconFontSize}"
Text="&#xE10A;"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
AutomationProperties.AccessibilityView="Raw" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Name="QueryButtonStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter x:Name="ContentPresenter"
Background="{ThemeResource TextControlButtonBackground}"
contract7Present:BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{ThemeResource TextControlButtonBorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
contract7NotPresent:CornerRadius="{Binding Source={ThemeResource ControlCornerRadius}, Converter={StaticResource RightCornerRadiusFilterConverter}}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
FontSize="{ThemeResource AutoSuggestBoxIconFontSize}"
Margin="{ThemeResource AutoSuggestBoxInnerButtonMargin}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
muxc:AnimatedIcon.State="Normal">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(muxc:AnimatedIcon.State)" Value="PointerOver"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(muxc:AnimatedIcon.State)" Value="Pressed"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Opacity"
To="0"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlHeaderForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Focused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="PlaceholderTextContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlPlaceholderForegroundFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBackgroundFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderBrushFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderElement" Storyboard.TargetProperty="BorderThickness">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlBorderThemeThicknessFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentElement" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlForegroundFocused}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="QueryButton" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource TextControlButtonForeground}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ButtonStates">
<VisualState x:Name="ButtonVisible">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DeleteButton" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="ButtonCollapsed" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="{ThemeResource AutoSuggestBoxRightButtonMargin}" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border x:Name="BorderElement"
Grid.Row="1"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Grid.ColumnSpan="4"
Grid.RowSpan="1"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
contract7NotPresent:CornerRadius="{ThemeResource ControlCornerRadius}" />
<ContentPresenter x:Name="HeaderContentPresenter"
x:DeferLoadStrategy="Lazy"
Visibility="Collapsed"
Grid.Row="0"
Foreground="{ThemeResource TextControlHeaderForeground}"
Margin="{ThemeResource AutoSuggestBoxTopHeaderMargin}"
Grid.ColumnSpan="4"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
FontWeight="Normal"
TextWrapping="Wrap" />
<ScrollViewer x:Name="ContentElement"
Grid.Row="1"
HorizontalScrollMode="{TemplateBinding ScrollViewer.HorizontalScrollMode}"
HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
VerticalScrollMode="{TemplateBinding ScrollViewer.VerticalScrollMode}"
VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}"
IsHorizontalRailEnabled="{TemplateBinding ScrollViewer.IsHorizontalRailEnabled}"
IsVerticalRailEnabled="{TemplateBinding ScrollViewer.IsVerticalRailEnabled}"
IsDeferredScrollingEnabled="{TemplateBinding ScrollViewer.IsDeferredScrollingEnabled}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
IsTabStop="False"
AutomationProperties.AccessibilityView="Raw"
ZoomMode="Disabled" />
<ContentControl x:Name="PlaceholderTextContentPresenter"
Grid.Row="1"
Foreground="{ThemeResource TextControlPlaceholderForeground}"
Margin="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
VerticalAlignment="Center"
IsTabStop="False"
Grid.ColumnSpan="4"
Content="{TemplateBinding PlaceholderText}"
IsHitTestVisible="False" />
<Button x:Name="DeleteButton"
Grid.Row="1"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
Style="{StaticResource DeleteButtonStyle}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{ThemeResource HelperButtonThemePadding}"
Margin="0,0,36,0"
IsTabStop="False"
Grid.Column="1"
Visibility="Collapsed"
FontSize="{TemplateBinding FontSize}"
Width="32"
AutomationProperties.AccessibilityView="Raw"
VerticalAlignment="Stretch" />
<Button x:Name="QueryButton"
Grid.Row="1"
Grid.Column="2"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"
Style="{StaticResource QueryButtonStyle}"
BorderThickness="{TemplateBinding BorderThickness}"
Margin="2,0,0,0"
Padding="{ThemeResource HelperButtonThemePadding}"
IsTabStop="False"
FontSize="{TemplateBinding FontSize}"
Width="32"
Height="28"
VerticalAlignment="Stretch"
AutomationProperties.AccessibilityView="Raw"/>
<contract7Present:ContentPresenter x:Name="DescriptionPresenter"
Grid.Row="2"
Grid.ColumnSpan="4"
Content="{TemplateBinding Description}"
x:Load="False"
Foreground="{ThemeResource SystemControlDescriptionTextForegroundBrush}"
AutomationProperties.AccessibilityView="Raw" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="AutoSuggestBox" BasedOn="{StaticResource CustomAutoSuggestBoxStyle}" />
<Style x:Key="CustomAutoSuggestBoxStyle" TargetType="AutoSuggestBox">
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Foreground" Value="{ThemeResource TextControlForeground}" />
<Setter Property="Background" Value="{ThemeResource TextControlBackground}" />
<Setter Property="BorderBrush" Value="{ThemeResource TextControlBorderBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource TextControlBorderThemeThickness}" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="TextBoxStyle" Value="{StaticResource AutoSuggestBoxTextBoxStyle}" />
<!--<contract6Present:Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}" />-->
<Setter Property="UseSystemFocusVisuals" Value="{ThemeResource IsApplicationFocusVisualKindReveal}" />
<!--<contract7Present:Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />-->
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="primitives:AutoSuggestBoxHelper.KeepInteriorCornersSquare" Value="true"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="AutoSuggestBox">
<Grid x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Orientation">
<VisualState x:Name="Landscape" />
<VisualState x:Name="Portrait" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox x:Name="TextBox"
Style="{TemplateBinding TextBoxStyle}"
PlaceholderText="{TemplateBinding PlaceholderText}"
Header="{TemplateBinding Header}"
Width="{TemplateBinding Width}"
contract7Present:Description="{TemplateBinding Description}"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
FontSize="{TemplateBinding FontSize}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontStretch="{TemplateBinding FontStretch}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
ScrollViewer.BringIntoViewOnFocusChange="False"
Canvas.ZIndex="0"
Margin="0"
DesiredCandidateWindowAlignment="BottomEdge"
UseSystemFocusVisuals="{TemplateBinding UseSystemFocusVisuals}"
contract7Present:CornerRadius="{TemplateBinding CornerRadius}"/>
<Popup x:Name="SuggestionsPopup">
<Border x:Name="SuggestionsContainer"
Padding="{ThemeResource AutoSuggestListMargin}"
BorderThickness="{ThemeResource AutoSuggestListBorderThemeThickness}"
BorderBrush="{ThemeResource AutoSuggestBoxSuggestionsListBorderBrush}"
Background="{ThemeResource AutoSuggestBoxSuggestionsListBackground}"
CornerRadius="{ThemeResource OverlayCornerRadius}">
<Border.RenderTransform>
<contract7NotPresent:TranslateTransform x:Name="UpwardTransform" />
</Border.RenderTransform>
<ListView
x:Name="SuggestionsList"
DisplayMemberPath="{TemplateBinding DisplayMemberPath}"
IsItemClickEnabled="True"
ItemTemplate="{TemplateBinding ItemTemplate}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
ItemContainerStyle="{TemplateBinding ItemContainerStyle}"
MaxHeight="{ThemeResource AutoSuggestListMaxHeight}"
Margin="{ThemeResource AutoSuggestListPadding}">
<ListView.ItemContainerTransitions>
<contract7NotPresent:TransitionCollection />
</ListView.ItemContainerTransitions>
</ListView>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Application.Resources>
</Toolkit:XamlApplication>

View file

@ -2,17 +2,15 @@
#include "ExplorerItem.h"
#include "ExplorerItem.g.cpp"
namespace {
const wchar_t fileImagePath[] = L"ms-appx:///Assets/file.png";
const wchar_t folderImagePath[] = L"ms-appx:///Assets/folder.png";
}
namespace winrt::PowerRenameUILib::implementation
{
ExplorerItem::ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, uint32_t depth, bool checked) :
m_id{ id }, m_idStr{ std::to_wstring(id) }, m_original{ original }, m_renamed{ renamed }, m_type{ type }, m_depth{ depth }, m_checked{ checked }
ExplorerItem::ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, bool checked) :
m_id{ id }, m_idStr{ std::to_wstring(id) }, m_original{ original }, m_renamed{ renamed }, m_type{ type }, m_checked{ checked }
{
m_imagePath = (m_type == static_cast<UINT>(ExplorerItemType::Folder)) ? folderImagePath : fileImagePath;
if (m_type == static_cast<UINT>(ExplorerItemType::Folder))
{
m_children = winrt::single_threaded_observable_vector<PowerRenameUILib::ExplorerItem>();
}
}
int32_t ExplorerItem::Id()
@ -53,15 +51,6 @@ namespace winrt::PowerRenameUILib::implementation
}
}
double ExplorerItem::Indentation() {
return static_cast<double>(m_depth) * 12;
}
hstring ExplorerItem::ImagePath()
{
return m_imagePath;
}
int32_t ExplorerItem::Type()
{
return m_type;
@ -90,6 +79,20 @@ namespace winrt::PowerRenameUILib::implementation
}
}
winrt::Windows::Foundation::Collections::IObservableVector<winrt::PowerRenameUILib::ExplorerItem> ExplorerItem::Children()
{
return m_children;
}
void ExplorerItem::Children(Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::ExplorerItem> const& value)
{
if (m_children != value)
{
m_children = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Children" });
}
}
winrt::event_token ExplorerItem::PropertyChanged(winrt::Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
return m_propertyChanged.add(handler);

View file

@ -11,17 +11,15 @@ namespace winrt::PowerRenameUILib::implementation
File = 1
};
ExplorerItem() = default;
ExplorerItem() = delete;
ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, uint32_t depth, bool checked);
ExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, bool checked);
int32_t Id();
hstring IdStr();
hstring Original();
void Original(hstring const& value);
hstring Renamed();
void Renamed(hstring const& value);
double Indentation();
hstring ImagePath();
int32_t Type();
void Type(int32_t value);
bool Checked();
@ -36,8 +34,6 @@ namespace winrt::PowerRenameUILib::implementation
hstring m_idStr;
winrt::hstring m_original;
winrt::hstring m_renamed;
uint32_t m_depth;
hstring m_imagePath;
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::ExplorerItem> m_children;
int32_t m_type;
bool m_checked;

View file

@ -2,15 +2,13 @@ namespace PowerRenameUILib
{
runtimeclass ExplorerItem : Windows.UI.Xaml.Data.INotifyPropertyChanged
{
ExplorerItem();
ExplorerItem(Int32 id, String original, String renamed, Int32 type, UInt32 depth, Boolean checked);
ExplorerItem(Int32 id, String original, String renamed, Int32 type, Boolean checked);
Int32 Id { get; };
String IdStr { get; };
String Original;
String Renamed;
Double Indentation { get; };
String ImagePath { get; };
Int32 Type;
Boolean Checked;
Windows.Foundation.Collections.IObservableVector<ExplorerItem> Children;
}
}

View file

@ -0,0 +1,37 @@
#include "pch.h"
#include "ExplorerItemTemplateSelector.h"
#include "ExplorerItemTemplateSelector.g.cpp"
namespace winrt::PowerRenameUILib::implementation
{
Windows::UI::Xaml::DataTemplate ExplorerItemTemplateSelector::SelectTemplateCore(IInspectable const& item)
{
ExplorerItem explorerItem = (ExplorerItem&)item;
return explorerItem.Type() == 0 ? m_folderTemplate : m_fileTemplate;
}
Windows::UI::Xaml::DataTemplate ExplorerItemTemplateSelector::SelectTemplateCore(IInspectable const&, Windows::UI::Xaml::DependencyObject const&)
{
return Windows::UI::Xaml::DataTemplate();
}
winrt::Windows::UI::Xaml::DataTemplate ExplorerItemTemplateSelector::FolderTemplate()
{
return m_folderTemplate;
}
void ExplorerItemTemplateSelector::FolderTemplate(winrt::Windows::UI::Xaml::DataTemplate const& value)
{
m_folderTemplate = value;
}
winrt::Windows::UI::Xaml::DataTemplate ExplorerItemTemplateSelector::FileTemplate()
{
return m_fileTemplate;
}
void ExplorerItemTemplateSelector::FileTemplate(winrt::Windows::UI::Xaml::DataTemplate const& value)
{
m_fileTemplate = value;
}
}

View file

@ -0,0 +1,28 @@
#pragma once
#include "ExplorerItemTemplateSelector.g.h"
namespace winrt::PowerRenameUILib::implementation
{
struct ExplorerItemTemplateSelector : ExplorerItemTemplateSelectorT<ExplorerItemTemplateSelector>
{
ExplorerItemTemplateSelector() = default;
Windows::UI::Xaml::DataTemplate SelectTemplateCore(IInspectable const&);
Windows::UI::Xaml::DataTemplate SelectTemplateCore(IInspectable const&, Windows::UI::Xaml::DependencyObject const&);
winrt::Windows::UI::Xaml::DataTemplate FolderTemplate();
void FolderTemplate(winrt::Windows::UI::Xaml::DataTemplate const& value);
winrt::Windows::UI::Xaml::DataTemplate FileTemplate();
void FileTemplate(winrt::Windows::UI::Xaml::DataTemplate const& value);
private:
Windows::UI::Xaml::DataTemplate m_folderTemplate{ nullptr };
Windows::UI::Xaml::DataTemplate m_fileTemplate{ nullptr };
};
}
namespace winrt::PowerRenameUILib::factory_implementation
{
struct ExplorerItemTemplateSelector : ExplorerItemTemplateSelectorT<ExplorerItemTemplateSelector, implementation::ExplorerItemTemplateSelector>
{
};
}

View file

@ -0,0 +1,11 @@
namespace PowerRenameUILib
{
[bindable]
[default_interface] runtimeclass ExplorerItemTemplateSelector : Windows.UI.Xaml.Controls.DataTemplateSelector
{
ExplorerItemTemplateSelector();
Windows.UI.Xaml.DataTemplate FolderTemplate;
Windows.UI.Xaml.DataTemplate FileTemplate;
}
}

View file

@ -163,11 +163,18 @@ namespace winrt::PowerRenameUILib::implementation
return m_uiUpdatesItem;
}
void MainWindow::AddExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, uint32_t depth, bool checked)
void MainWindow::AddExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, int32_t parentId, bool checked)
{
auto newItem = winrt::make<PowerRenameUILib::implementation::ExplorerItem>(id, original, renamed, type, depth, checked);
m_explorerItems.Append(newItem);
m_explorerItemsMap[id] = newItem;
auto newItem = winrt::make<PowerRenameUILib::implementation::ExplorerItem>(id, original, renamed, type, checked);
if (parentId == 0)
{
m_explorerItems.Append(newItem);
}
else
{
auto parent = FindById(parentId);
parent.Children().Append(newItem);
}
}
void MainWindow::UpdateExplorerItem(int32_t id, hstring const& newName)
@ -201,12 +208,43 @@ namespace winrt::PowerRenameUILib::implementation
PowerRenameUILib::ExplorerItem MainWindow::FindById(int32_t id)
{
return m_explorerItemsMap.contains(id) ? m_explorerItemsMap[id] : NULL;
auto fakeRoot = winrt::make<PowerRenameUILib::implementation::ExplorerItem>(0, L"Fake", L"", 0, false);
fakeRoot.Children(m_explorerItems);
return FindById(fakeRoot, id);
}
void MainWindow::ToggleAll(bool checked)
PowerRenameUILib::ExplorerItem MainWindow::FindById(PowerRenameUILib::ExplorerItem& root, int32_t id)
{
std::for_each(m_explorerItems.begin(), m_explorerItems.end(), [checked](auto item) { item.Checked(checked); });
if (root.Id() == id)
return root;
if (root.Type() == static_cast<UINT>(ExplorerItem::ExplorerItemType::Folder))
{
for (auto c : root.Children())
{
auto result = FindById(c, id);
if (result != NULL)
return result;
}
}
return NULL;
}
void MainWindow::ToggleAll(PowerRenameUILib::ExplorerItem node, bool checked)
{
if (node == NULL)
return;
node.Checked(checked);
if (node.Type() == static_cast<UINT>(ExplorerItem::ExplorerItemType::Folder))
{
for (auto c : node.Children())
{
ToggleAll(c, checked);
}
}
}
void MainWindow::Checked_ids(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const&)
@ -214,7 +252,7 @@ namespace winrt::PowerRenameUILib::implementation
auto checkbox = sender.as<Windows::UI::Xaml::Controls::CheckBox>();
auto id = std::stoi(std::wstring{ checkbox.Name() });
auto item = FindById(id);
if (item != NULL && checkbox.IsChecked().GetBoolean() != item.Checked())
if (checkbox.IsChecked().GetBoolean() != item.Checked())
{
m_uiUpdatesItem.Checked(checkbox.IsChecked().GetBoolean());
m_uiUpdatesItem.ChangedExplorerItemId(id);
@ -225,7 +263,9 @@ namespace winrt::PowerRenameUILib::implementation
{
if (checkBox_selectAll().IsChecked().GetBoolean() != m_allSelected)
{
ToggleAll(checkBox_selectAll().IsChecked().GetBoolean());
auto fakeRoot = winrt::make<PowerRenameUILib::implementation::ExplorerItem>(0, L"Fake", L"", 0, false);
fakeRoot.Children(m_explorerItems);
ToggleAll(fakeRoot, checkBox_selectAll().IsChecked().GetBoolean());
m_uiUpdatesItem.ToggleAll();
m_allSelected = !m_allSelected;
}
@ -238,7 +278,6 @@ namespace winrt::PowerRenameUILib::implementation
if (!m_uiUpdatesItem.ShowAll())
{
m_explorerItems.Clear();
m_explorerItemsMap.clear();
m_uiUpdatesItem.ShowAll(true);
}
}
@ -250,7 +289,6 @@ namespace winrt::PowerRenameUILib::implementation
if (m_uiUpdatesItem.ShowAll())
{
m_explorerItems.Clear();
m_explorerItemsMap.clear();
m_uiUpdatesItem.ShowAll(false);
}
}

View file

@ -7,7 +7,7 @@
#include "MainWindow.g.h"
#include "PatternSnippet.h"
#include "ExplorerItem.h"
#include <map>
#include "ExplorerItemTemplateSelector.h"
namespace winrt::PowerRenameUILib::implementation
{
@ -47,7 +47,7 @@ namespace winrt::PowerRenameUILib::implementation
PowerRenameUILib::UIUpdates UIUpdatesItem();
void AddExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, uint32_t depth, bool checked);
void AddExplorerItem(int32_t id, hstring const& original, hstring const& renamed, int32_t type, int32_t parentId, bool checked);
void UpdateExplorerItem(int32_t id, hstring const& newName);
void UpdateRenamedExplorerItem(int32_t id, hstring const& newOriginalName);
void AppendSearchMRU(hstring const& value);
@ -61,13 +61,13 @@ namespace winrt::PowerRenameUILib::implementation
private:
bool m_allSelected;
PowerRenameUILib::UIUpdates m_uiUpdatesItem;
inline PowerRenameUILib::ExplorerItem FindById(int32_t id);
void ToggleAll(bool checked);
PowerRenameUILib::ExplorerItem FindById(int32_t id);
PowerRenameUILib::ExplorerItem FindById(PowerRenameUILib::ExplorerItem& root, int32_t id);
void ToggleAll(PowerRenameUILib::ExplorerItem node, bool checked);
winrt::Windows::Foundation::Collections::IObservableVector<hstring> m_searchMRU;
winrt::Windows::Foundation::Collections::IObservableVector<hstring> m_replaceMRU;
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::ExplorerItem> m_explorerItems;
std::map<int32_t, PowerRenameUILib::ExplorerItem> m_explorerItemsMap;
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::PatternSnippet> m_searchRegExShortcuts;
winrt::Windows::Foundation::Collections::IObservableVector<PowerRenameUILib::PatternSnippet> m_dateTimeShortcuts;

View file

@ -14,8 +14,6 @@ namespace PowerRenameUILib
void CloseUIWindow(Boolean closeUIWindow);
Boolean ButtonRenameEnabled;
void Rename();
String OriginalCount;
String RenamedCount;
}
[default_interface] runtimeclass MainWindow : Windows.UI.Xaml.Controls.UserControl
@ -52,7 +50,7 @@ namespace PowerRenameUILib
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonTitleCase { get; };
Windows.UI.Xaml.Controls.Primitives.ToggleButton ToggleButtonCapitalize { get; };
void AddExplorerItem(Int32 id, String original, String renamed, Int32 type, UInt32 depth, Boolean checked);
void AddExplorerItem(Int32 id, String original, String renamed, Int32 type, Int32 parentId, Boolean checked);
void UpdateExplorerItem(Int32 id, String newName);
void UpdateRenamedExplorerItem(Int32 id, String newOriginalName);
void AppendSearchMRU(String value);

View file

@ -1,6 +1,78 @@
<UserControl x:Class="PowerRenameUILib.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:PowerRenameUILib" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:controls="using:Microsoft.UI.Xaml.Controls" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" controls:BackdropMaterial.ApplyToRootOrPageBackground="True" xmlns:animatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals" mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Padding="12">
<UserControl.Resources>
<local:ExplorerItemTemplateSelector x:Key="ExplorerItemTemplateSelector" FolderTemplate="{StaticResource FolderTemplate}" FileTemplate="{StaticResource FileTemplate}" />
<local:ExplorerItemTemplateSelector x:Key="RenamedExplorerItemTemplateSelector" FolderTemplate="{StaticResource RenamedFolderTemplate}" FileTemplate="{StaticResource RenamedFileTemplate}" />
<DataTemplate x:Key="FileTemplate" x:DataType="local:ExplorerItem">
<Grid Height="24" Margin="0,4,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="36" />
<ColumnDefinition Width="36" />
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<CheckBox TabIndex="0" Grid.Column="0" XYFocusKeyboardNavigation="Enabled" Checked="Checked_ids" IsTabStop="True" Unchecked="Checked_ids" Content="" Name="{x:Bind IdStr}" AutomationProperties.Name="{x:Bind Original}" AutomationProperties.HelpText="{x:Bind Renamed}" IsChecked="{x:Bind Checked, Mode=TwoWay}" />
<Image Width="16" Source="ms-appx:///Assets/file.png" HorizontalAlignment="Left" Grid.Column="1" />
<TextBlock Text="{x:Bind Original, Mode=OneWay}" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" FontSize="12" Grid.Column="2" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="FolderTemplate" x:DataType="local:ExplorerItem">
<Grid Margin="0,4,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="36" />
<ColumnDefinition Width="36" />
<ColumnDefinition Width="300" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<CheckBox TabIndex="0" IsTabStop="True" XYFocusKeyboardNavigation="Enabled" Grid.Row="0" Grid.Column="0" Checked="Checked_ids" Unchecked="Checked_ids" Content="" Name="{x:Bind IdStr}" AutomationProperties.Name="{x:Bind Original}" AutomationProperties.HelpText="{x:Bind Renamed}" IsChecked="{x:Bind Checked, Mode=TwoWay}" />
<Image Width="16" Source="ms-appx:///Assets/folder.png" HorizontalAlignment="Left" Grid.Column="1" />
<TextBlock Text="{x:Bind Original, Mode=OneWay}" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" FontSize="12" Grid.Column="2" />
<ListView Grid.ColumnSpan="3" IsTabStop="false" XYFocusKeyboardNavigation="Enabled" SelectionMode="None" IsItemClickEnabled="False" ItemsSource="{x:Bind Children}" Grid.Row="1" ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</DataTemplate>
<DataTemplate x:Key="RenamedFileTemplate" x:DataType="local:ExplorerItem">
<Grid Height="24" Margin="0,4,0,0">
<TextBlock Text="{x:Bind Renamed, Mode=OneWay}" FontWeight="SemiBold" VerticalAlignment="Center" FontSize="14" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="RenamedFolderTemplate" x:DataType="local:ExplorerItem">
<Grid Margin="0,4,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="24" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock Text="{x:Bind Renamed, Mode=OneWay}" FontWeight="Bold" VerticalAlignment="Center" FontSize="14" />
<ListView IsTabStop="false" Margin="-12,0,0,0" SelectionMode="None" IsItemClickEnabled="False" ItemsSource="{x:Bind Children}" Grid.Row="1" ItemTemplateSelector="{StaticResource RenamedExplorerItemTemplateSelector}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
</Grid>
</DataTemplate>
</UserControl.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Padding="20">
<Grid.RowDefinitions>
<RowDefinition Height="0" /> <!-- 48 if we need to draw the title bar ourself -->
<RowDefinition Height="*" />
@ -10,45 +82,27 @@
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="1"
Grid.Column="1"
Background="{ThemeResource LayerFillColorDefaultBrush}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
CornerRadius="8"
BorderThickness="1"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}">
<Grid Grid.Row="1" Grid.Column="1" Background="{ThemeResource LayerFillColorDefaultBrush}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" CornerRadius="8" BorderThickness="1" BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="36" />
<ColumnDefinition Width="48" />
<ColumnDefinition Width="Auto" MinWidth="324" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="48" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal">
<CheckBox x:Name="checkBox_selectAll" IsChecked="True" MinWidth="0" Content="" x:Uid="SelectAllCheckBox" Margin="10,0,0,0" Checked="SelectAll" Unchecked="SelectAll" />
<Image Width="16" Margin="4,0,0,0" Source="ms-appx:///Assets/file.png" HorizontalAlignment="Left" />
<CheckBox x:Name="checkBox_selectAll" IsChecked="True" Content="" x:Uid="SelectAllCheckBox" Margin="16,0,0,0" Checked="SelectAll" Unchecked="SelectAll" />
<Image Width="16" Grid.Column="1" Source="ms-appx:///Assets/file.png" HorizontalAlignment="Center" />
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Grid.Column="2" Margin="6,-2,0,0" >
<TextBlock x:Uid="TxtBlock_Original" FontWeight="Medium" />
<TextBlock FontWeight="Medium" Margin="4,0,0,0" >
<Run Text="(" /><Run Text="{x:Bind UIUpdatesItem.OriginalCount, Mode=OneWay}" /><Run Text=")" />
</TextBlock>
</StackPanel>
</StackPanel>
<AppBarSeparator Margin="-6,4,0,4" HorizontalAlignment="Right" />
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Grid.Column="2" Margin="4,-2,0,0" >
<TextBlock x:Uid="TxtBlock_Renamed" FontWeight="Medium" />
<TextBlock FontWeight="Medium" Margin="4,0,0,0" >
<Run Text="(" /><Run Text="{x:Bind UIUpdatesItem.RenamedCount, Mode=OneWay}" /><Run Text=")" />
</TextBlock>
</StackPanel>
<Button Content="&#xE16E;" Background="Transparent" FontFamily="{ThemeResource SymbolThemeFontFamily}" Height="32" x:Uid="FilterButton" Grid.Column="1" BorderThickness="0" HorizontalAlignment="Right" Margin="0,0,8,0">
<TextBlock x:Uid="TxtBlock_Original" Grid.Column="2" FontWeight="Medium" Margin="2,-2,0,0" VerticalAlignment="Center" />
<AppBarSeparator Grid.Column="3" Margin="-6,4,0,4" HorizontalAlignment="Left" />
<TextBlock x:Uid="TxtBlock_Renamed" FontWeight="Medium" Grid.Column="3" Margin="4,-2,0,0" HorizontalAlignment="Left" VerticalAlignment="Center" />
<Button Content="&#xE16E;" Background="Transparent" FontFamily="{ThemeResource SymbolThemeFontFamily}" Height="32" x:Uid="FilterButton" Grid.Column="4" BorderThickness="0" HorizontalAlignment="Right" Margin="0,0,8,0">
<Button.Flyout>
<MenuBarItemFlyout Placement="Bottom">
<controls:RadioMenuFlyoutItem x:Name="button_showAll" Click="ShowAll" x:Uid="ShowAll" IsChecked="True" GroupName="Filter" />
@ -58,95 +112,47 @@
</Button>
<Rectangle Height="1" Grid.ColumnSpan="5" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" />
<ListView IsTabStop="false"
SelectionMode="None"
XYFocusKeyboardNavigation="Enabled"
IsItemClickEnabled="False"
Grid.ColumnSpan="6"
ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}"
Grid.Row="1">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<StackPanel Orientation="Vertical">
<ContentPresenter />
<Rectangle Height="1" Margin="0,4,0,0" Opacity="0.8" Grid.ColumnSpan="5" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:Name="ExplorerItemTemplate" x:DataType="local:ExplorerItem">
<Grid Height="20" Margin="10,4,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" Grid.Column="0">
<StackPanel MinWidth="{x:Bind Indentation}"/>
<CheckBox TabIndex="0"
MinWidth="0"
XYFocusKeyboardNavigation="Enabled"
Checked="Checked_ids"
IsTabStop="True"
Unchecked="Checked_ids"
Content=""
Name="{x:Bind IdStr}"
AutomationProperties.Name="{x:Bind Original}"
AutomationProperties.HelpText="{x:Bind Renamed}"
IsChecked="{x:Bind Checked, Mode=TwoWay}" />
<Image Width="16" Margin="4,0,0,0" Source="{x:Bind ImagePath}" HorizontalAlignment="Left" />
<TextBlock Margin="6,0,0,0"
Text="{x:Bind Original, Mode=OneWay}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
VerticalAlignment="Center"
FontSize="12" />
</StackPanel>
<TextBlock Text="{x:Bind Renamed, Mode=OneWay}" Grid.Column="1" FontWeight="Bold" VerticalAlignment="Center" FontSize="12" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ScrollViewer Grid.ColumnSpan="6" HorizontalScrollMode="Enabled" Grid.Row="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="286" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListView IsTabStop="false" SelectionMode="None" XYFocusKeyboardNavigation="Enabled" IsItemClickEnabled="False" ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}" Margin="4,0,0,0" ItemTemplateSelector="{StaticResource ExplorerItemTemplateSelector}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
<!--<controls:ItemsRepeater ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}"
Margin="16,0,0,0"
ItemTemplate="{StaticResource ExplorerItemTemplateSelector}" />-->
<ListView Grid.Column="1" IsTabStop="false" SelectionMode="None" IsItemClickEnabled="False" ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}" ItemTemplateSelector="{StaticResource RenamedExplorerItemTemplateSelector}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsTabStop" Value="False" />
</Style>
</ListView.ItemContainerStyle>
</ListView>
<!--<controls:ItemsRepeater ItemsSource="{x:Bind ExplorerItems, Mode=OneWay}"
Grid.Column="1"
ItemTemplate="{StaticResource RenamedExplorerItemTemplateSelector}" />-->
</Grid>
</ScrollViewer>
</Grid>
<Grid Grid.Column="0" Grid.Row="1" MaxWidth="357" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid Grid.Column="0" Grid.Row="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="48" />
</Grid.RowDefinitions>
<StackPanel Orientation="Vertical" Padding="0,0,0,16" Margin="0,0,12,0">
<ScrollViewer>
<StackPanel Orientation="Vertical" Padding="0,0,0,16" Margin="0,0,20,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<AutoSuggestBox x:Name="textBox_search" x:Uid="SearchBox" Height="40" VerticalContentAlignment="Center" ItemsSource="{x:Bind SearchMRU}" />
<AutoSuggestBox x:Name="textBox_search" x:Uid="SearchBox" Height="48" VerticalContentAlignment="Center" ItemsSource="{x:Bind SearchMRU}" />
<Button Grid.Column="1"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
VerticalAlignment="Center"
Visibility="{Binding ElementName=checkBox_regex, Path=IsChecked}"
Height="40"
Width="28"
Padding="0"
Margin="0,0,-4,0"
BorderBrush="Transparent"
Background="Transparent"
x:Uid="RegExButton"
Content="&#xE946;"
HorizontalAlignment="Right">
<Button FontFamily="{ThemeResource SymbolThemeFontFamily}" VerticalAlignment="Center" Visibility="{Binding ElementName=checkBox_regex, Path=IsChecked}" MinHeight="32" Margin="4" x:Uid="RegExButton" Background="Transparent" BorderBrush="Transparent" Content="&#xE946;" HorizontalAlignment="Right">
<Button.Flyout>
<Flyout x:Name="RegExFlyout">
<Grid>
@ -168,7 +174,7 @@
<TextBlock FontFamily="Consolas" Foreground="{ThemeResource ButtonForeground}" Text="{x:Bind Code}" />
</Border>
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Margin="0,0,0,0" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
@ -183,30 +189,15 @@
</Grid>
<CheckBox x:Name="checkBox_regex" x:Uid="CheckBox_RegEx" Margin="2,6,0,0" />
<CheckBox x:Name="checkBox_matchAll" x:Uid="CheckBox_MatchAll" Margin="2,0,0,0" />
<CheckBox x:Name="checkBox_case" x:Uid="CheckBox_Case" Margin="2,0,0,0" />
<CheckBox x:Name="checkBox_regex" x:Uid="CheckBox_RegEx" Margin="2,12,0,0" />
<CheckBox x:Name="checkBox_matchAll" x:Uid="CheckBox_MatchAll" Margin="2,4,0,0" />
<CheckBox x:Name="checkBox_case" x:Uid="CheckBox_Case" Margin="2,4,0,0" />
<Rectangle Height="1" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" Margin="0,16,0,20" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<AutoSuggestBox x:Name="textBox_replace" x:Uid="ReplaceBox" Height="40" VerticalContentAlignment="Center" Padding="12,12,0,0" ItemsSource="{x:Bind ReplaceMRU}" />
<AutoSuggestBox x:Name="textBox_replace" Margin="0,0,0,0" x:Uid="ReplaceBox" Height="48" VerticalContentAlignment="Center" Padding="12,12,0,0" ItemsSource="{x:Bind ReplaceMRU}" />
<Button FontFamily="{ThemeResource SymbolThemeFontFamily}"
VerticalAlignment="Center"
x:Uid="FileCreationButton"
Grid.Column="1"
Width="28"
Height="40"
Padding="0"
Margin="0,0,-4,0"
BorderBrush="Transparent"
Background="Transparent"
Content="&#xE946;"
HorizontalAlignment="Right">
<Button FontFamily="{ThemeResource SymbolThemeFontFamily}" VerticalAlignment="Center" MinHeight="32" Margin="4" x:Uid="FileCreationButton" Background="Transparent" BorderBrush="Transparent" Content="&#xE946;" HorizontalAlignment="Right">
<Button.Flyout>
<Flyout x:Name="DateTimeFlyout" ShouldConstrainToRootBounds="False">
<Grid>
@ -227,7 +218,7 @@
<TextBlock FontFamily="Consolas" Foreground="{ThemeResource ButtonForeground}" Text="{x:Bind Code}" />
</Border>
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
<TextBlock Text="{x:Bind Description}" FontSize="12" Grid.Column="1" Margin="0,0,0,0" Foreground="{ThemeResource TextFillColorSecondaryBrush}" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
@ -239,7 +230,7 @@
</Button>
</Grid>
<TextBlock x:Uid="TextBox_ApplyTo" x:Name="ApplyToLabel" FontSize="12" Margin="0,12,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<TextBlock x:Uid="TextBox_ApplyTo" x:Name="ApplyToLabel" FontSize="12" Margin="0,20,0,8" Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
<StackPanel Orientation="Horizontal" Grid.Column="1" Spacing="4" Grid.Row="1">
<ComboBox x:Name="comboBox_renameParts" SelectedIndex="0" Width="200" AutomationProperties.LabeledBy="{Binding ElementName=ApplyToLabel}" HorizontalAlignment="Stretch" Grid.Column="0" Grid.Row="1">
@ -248,59 +239,50 @@
<x:String>Extension only</x:String>
</ComboBox>
<AppBarSeparator Margin="5,0,5,0" />
<ToggleButton x:Name="toggleButton_includeFiles" Content="&#xE160;" MinHeight="0" Height="31" IsChecked="True" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="ToggleButton_IncludeFiles" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_includeFolders" Content="&#xE8B7;" MinHeight="0" Height="31" IsChecked="True" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="ToggleButton_IncludeFolders" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_includeSubfolders" Content="&#xE12F;" MinHeight="0" Height="31" IsChecked="True" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="ToggleButton_IncludeSubFolders" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_includeFiles" Content="&#xE160;" MinHeight="32" IsChecked="True" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="ToggleButton_IncludeFiles" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_includeFolders" Content="&#xE8B7;" MinHeight="32" IsChecked="True" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="ToggleButton_IncludeFolders" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_includeSubfolders" Content="&#xE12F;" MinHeight="32" IsChecked="True" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="ToggleButton_IncludeSubFolders" Style="{StaticResource CustomToggleButtonStyle}" />
</StackPanel>
<TextBlock x:Uid="TextBlock_TextFormatting" FontSize="12" Foreground="{ThemeResource TextFillColorSecondaryBrush}" Margin="0,12,0,8" />
<TextBlock x:Uid="TextBlock_TextFormatting" FontSize="12" Foreground="{ThemeResource TextFillColorSecondaryBrush}" Margin="0,20,0,8" />
<StackPanel Orientation="Horizontal" Spacing="4">
<ToggleButton x:Name="toggleButton_lowerCase" Content="aa" FontWeight="Medium" MinHeight="0" Height="31" x:Uid="ToggleButton_Lowercase" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_upperCase" Content="AA" FontWeight="Medium" MinHeight="0" Height="31" x:Uid="ToggleButton_Uppercase" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_titleCase" Content="Aa" FontWeight="Medium" MinHeight="0" Height="31" x:Uid="ToggleButton_TitleCase" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_capitalize" Content="Aa Aa" FontWeight="Medium" MinHeight="0" Height="31" x:Uid="ToggleButton_Capitalize" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_lowerCase" Content="aa" FontWeight="Medium" MinHeight="32" x:Uid="ToggleButton_Lowercase" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_upperCase" Content="AA" FontWeight="Medium" MinHeight="32" x:Uid="ToggleButton_Uppercase" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_titleCase" Content="Aa" FontWeight="Medium" MinHeight="32" x:Uid="ToggleButton_TitleCase" Style="{StaticResource CustomToggleButtonStyle}" />
<ToggleButton x:Name="toggleButton_capitalize" Content="Aa Aa" FontWeight="Medium" MinHeight="32" x:Uid="ToggleButton_Capitalize" Style="{StaticResource CustomToggleButtonStyle}" />
<AppBarSeparator Margin="5,0,5,0" />
<ToggleButton x:Name="toggleButton_enumItems" Content="&#xEA40;" FontFamily="{ThemeResource SymbolThemeFontFamily}" MinHeight="32" x:Uid="ToggleButton_EnumItems" Style="{StaticResource CustomToggleButtonStyle}" />
</StackPanel>
</StackPanel>
</ScrollViewer>
<Rectangle Height="1" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" Margin="0,0,12,0" VerticalAlignment="Top" Grid.Row="1" />
<Rectangle Height="1" Fill="{ThemeResource CardStrokeColorDefaultBrush}" HorizontalAlignment="Stretch" Margin="0,0,20,0" VerticalAlignment="Top" Grid.Row="1" />
</Grid>
<StackPanel Orientation="Horizontal" Grid.Row="1" Spacing="8" Margin="0" Grid.Column="1" VerticalAlignment="Bottom" HorizontalAlignment="Left">
<StackPanel Orientation="Horizontal"
Grid.Row="2"
Spacing="8"
Margin="0"
Grid.Column="0"
VerticalAlignment="Bottom"
HorizontalAlignment="Left">
<Button x:Name="button_settings" Height="32" x:Uid="TxtBlock_ButtonSettings" FontFamily="{ThemeResource SymbolThemeFontFamily}" Grid.Row="5" Padding="6" Background="Transparent" BorderBrush="Transparent" Grid.Column="1">
<Button.Content>
<controls:AnimatedIcon x:Name="SearchAnimatedIcon">
<controls:AnimatedIcon.Source>
<animatedVisuals:AnimatedSettingsVisualSource />
</controls:AnimatedIcon.Source>
<controls:AnimatedIcon.FallbackIconSource>
<controls:SymbolIconSource Symbol="Setting" />
</controls:AnimatedIcon.FallbackIconSource>
</controls:AnimatedIcon>
<Button x:Name="button_settings" Height="32" x:Uid="TxtBlock_ButtonSettings" FontFamily="{ThemeResource SymbolThemeFontFamily}" Grid.Row="5" Padding="6" Background="Transparent" BorderBrush="Transparent" Grid.Column="1">
<Button.Content>
<controls:AnimatedIcon x:Name="SearchAnimatedIcon">
<controls:AnimatedIcon.Source>
<animatedVisuals:AnimatedSettingsVisualSource />
</controls:AnimatedIcon.Source>
<controls:AnimatedIcon.FallbackIconSource>
<controls:SymbolIconSource Symbol="Setting" />
</controls:AnimatedIcon.FallbackIconSource>
</controls:AnimatedIcon>
</Button.Content>
</Button>
</Button.Content>
</Button>
<Button x:Name="button_docs" Content="&#xE11B;" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="DocsButton" Background="Transparent" BorderBrush="Transparent" Grid.Row="1" Height="32" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="OpenDocs" />
<Button x:Name="button_docs" Content="&#xE11B;" FontFamily="{ThemeResource SymbolThemeFontFamily}" x:Uid="DocsButton" Background="Transparent" BorderBrush="Transparent" Grid.Row="1" Height="32" VerticalAlignment="Bottom" HorizontalAlignment="Left" Click="OpenDocs" />
<!--<Button Content="&#xE728;"
<!--<Button Content="&#xE728;"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
ToolTipService.ToolTip="Presets"
Background="Transparent"
@ -318,27 +300,26 @@
</Button.Flyout>
</Button>-->
</StackPanel>
</StackPanel>
<muxc:SplitButton Grid.Row="2" Style="{StaticResource SplitAccentButtonStyle}" Grid.Column="0" Margin="0,0,12,1" x:Name="button_rename" x:Uid="ButtonApply" Click="button_rename_Click" HorizontalAlignment="Right" VerticalAlignment="Bottom" IsEnabled="{x:Bind UIUpdatesItem.ButtonRenameEnabled, Mode=OneWay}">
<muxc:SplitButton.KeyboardAccelerators>
<KeyboardAccelerator Key="Enter" />
<KeyboardAccelerator Key="Enter" Modifiers="Control" />
</muxc:SplitButton.KeyboardAccelerators>
<muxc:SplitButton.Content>
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE13E;" FontSize="14" VerticalAlignment="Center" Margin="0,2,10,0" />
<TextBlock x:Uid="TxtBlock_ButtonApply" />
</StackPanel>
</muxc:SplitButton.Content>
<muxc:SplitButton.Flyout>
<MenuFlyout>
<MenuFlyoutItem x:Uid="TxtBlock_ButtonApplyAndClose" Click="MenuFlyoutItem_Click" />
</MenuFlyout>
</muxc:SplitButton.Flyout>
</muxc:SplitButton>
<muxc:SplitButton Grid.Row="1" Style="{StaticResource SplitAccentButtonStyle}" x:Name="button_rename" Margin="0,0,20,0" x:Uid="ButtonApply" Click="button_rename_Click" HorizontalAlignment="Right" VerticalAlignment="Bottom" IsEnabled="{x:Bind UIUpdatesItem.ButtonRenameEnabled, Mode=OneWay}">
<muxc:SplitButton.KeyboardAccelerators>
<KeyboardAccelerator Key="Enter" />
<KeyboardAccelerator Key="Enter" Modifiers="Control" />
</muxc:SplitButton.KeyboardAccelerators>
<muxc:SplitButton.Content>
<StackPanel Orientation="Horizontal">
<FontIcon Glyph="&#xE13E;" FontSize="14" VerticalAlignment="Center" Margin="0,2,10,0" />
<TextBlock x:Uid="TxtBlock_ButtonApply" />
</StackPanel>
</muxc:SplitButton.Content>
<muxc:SplitButton.Flyout>
<MenuFlyout>
<MenuFlyoutItem x:Uid="TxtBlock_ButtonApplyAndClose" Click="MenuFlyoutItem_Click" />
</MenuFlyout>
</muxc:SplitButton.Flyout>
</muxc:SplitButton>
</Grid>
<!--<StackPanel x:Name="TitleBar" Orientation="Horizontal">
<Image Source="Assets/PowerRename.png" Width="16" Height="16" VerticalAlignment="Top" Margin="20,9,0,0"/>

View file

@ -54,8 +54,7 @@
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="ExtensionSettings"></ImportGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
@ -109,6 +108,7 @@
<ItemGroup>
<ClInclude Include="app.base.h" />
<ClInclude Include="ExplorerItem.h" />
<ClInclude Include="ExplorerItemTemplateSelector.h" />
<ClInclude Include="MainWindow.h">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
@ -146,6 +146,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="ExplorerItem.cpp" />
<ClCompile Include="ExplorerItemTemplateSelector.cpp" />
<ClCompile Include="MainWindow.cpp">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
@ -165,6 +166,7 @@
<DependentUpon>App.xaml</DependentUpon>
</Midl>
<Midl Include="ExplorerItem.idl" />
<Midl Include="ExplorerItemTemplateSelector.idl" />
<Midl Include="MainWindow.idl">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>

View file

@ -64,34 +64,6 @@ namespace winrt::PowerRenameUILib::implementation
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Rename" });
}
hstring UIUpdates::OriginalCount()
{
return m_originalCount;
}
void UIUpdates::OriginalCount(hstring value)
{
if (m_originalCount != value)
{
m_originalCount = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"OriginalCount" });
}
}
hstring UIUpdates::RenamedCount()
{
return m_renamedCount;
}
void UIUpdates::RenamedCount(hstring value)
{
if (m_renamedCount != value)
{
m_renamedCount = value;
m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"RenamedCount" });
}
}
bool UIUpdates::CloseUIWindow()
{
return m_closeUIWindow;

View file

@ -21,10 +21,6 @@ namespace winrt::PowerRenameUILib::implementation
bool ButtonRenameEnabled();
void ButtonRenameEnabled(bool value);
void Rename();
hstring OriginalCount();
void OriginalCount(hstring value);
hstring RenamedCount();
void RenamedCount(hstring value);
private:
bool m_showAll;
@ -32,8 +28,6 @@ namespace winrt::PowerRenameUILib::implementation
bool m_checked;
bool m_closeUIWindow;
bool m_buttonRenameEnabled;
hstring m_originalCount;
hstring m_renamedCount;
winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
};
}

View file

@ -16,7 +16,6 @@
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
#include <winrt/Windows.UI.Xaml.Data.h>
#include <winrt/Windows.UI.Xaml.Documents.h>
#include <winrt/Windows.UI.Xaml.Interop.h>
#include <winrt/Windows.UI.Xaml.Markup.h>
#include <winrt/Windows.UI.Xaml.Navigation.h>

View file

@ -148,8 +148,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
L"modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.dll",
L"modules/ColorPicker/ColorPicker.dll",
L"modules/Awake/AwakeModuleInterface.dll",
L"modules/MouseUtils/FindMyMouse.dll" ,
L"modules/MouseUtils/MouseHighlighter.dll"
L"modules/MouseUtils/FindMyMouse.dll"
};
const auto VCM_PATH = L"modules/VideoConference/VideoConferenceModule.dll";

View file

@ -457,17 +457,7 @@ void bring_settings_to_front()
}
if (wcsncmp(title, windowTitle.c_str(), len) == 0)
{
auto lStyles = GetWindowLong(hwnd, GWL_STYLE);
if (lStyles & WS_MAXIMIZE)
{
ShowWindow(hwnd, SW_MAXIMIZE);
}
else
{
ShowWindow(hwnd, SW_RESTORE);
}
ShowWindow(hwnd, SW_RESTORE);
SetForegroundWindow(hwnd);
return FALSE;
}

View file

@ -191,22 +191,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
}
private bool mouseHighlighter = true;
[JsonPropertyName("MouseHighlighter")]
public bool MouseHighlighter
{
get => mouseHighlighter;
set
{
if (mouseHighlighter != value)
{
LogTelemetryEvent(value);
mouseHighlighter = value;
}
}
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);

View file

@ -65,15 +65,5 @@ namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
/// Color presentation as CIEXYZ color space (X[0..95], Y[0..100], Z[0..109]
/// </summary>
CIEXYZ = 10,
/// <summary>
/// Color presentation as RGB float (red[0..1], green[0..1], blue[0..1])
/// </summary>
VEC4 = 11,
/// <summary>
/// Color presentation as integer decimal value 0-16777215
/// </summary>
DecimalValue = 12,
}
}

View file

@ -11,33 +11,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library
[JsonPropertyName("do_not_activate_on_game_mode")]
public BoolProperty DoNotActivateOnGameMode { get; set; }
[JsonPropertyName("background_color")]
public StringProperty BackgroundColor { get; set; }
[JsonPropertyName("spotlight_color")]
public StringProperty SpotlightColor { get; set; }
[JsonPropertyName("overlay_opacity")]
public IntProperty OverlayOpacity { get; set; }
[JsonPropertyName("spotlight_radius")]
public IntProperty SpotlightRadius { get; set; }
[JsonPropertyName("animation_duration_ms")]
public IntProperty AnimationDurationMs { get; set; }
[JsonPropertyName("spotlight_initial_zoom")]
public IntProperty SpotlightInitialZoom { get; set; }
public FindMyMouseProperties()
{
DoNotActivateOnGameMode = new BoolProperty(true);
BackgroundColor = new StringProperty("#000000");
SpotlightColor = new StringProperty("#FFFFFF");
OverlayOpacity = new IntProperty(50);
SpotlightRadius = new IntProperty(100);
AnimationDurationMs = new IntProperty(500);
SpotlightInitialZoom = new IntProperty(9);
}
}
}

View file

@ -9,7 +9,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
{
public class FindMyMouseSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "FindMyMouse";
public const string ModuleName = "Find My Mouse";
[JsonPropertyName("properties")]
public FindMyMouseProperties Properties { get; set; }

View file

@ -1,39 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Drawing;
using System.Globalization;
namespace Microsoft.PowerToys.Settings.UI.Library.Helpers
{
public static class SettingsUtilities
{
public static string ToRGBHex(string color)
{
if (color == null)
{
return "#FFFFFF";
}
// Using InvariantCulture as these are expected to be hex codes.
bool success = int.TryParse(
color.Replace("#", string.Empty),
System.Globalization.NumberStyles.HexNumber,
CultureInfo.InvariantCulture,
out int argb);
if (success)
{
Color clr = Color.FromArgb(argb);
return "#" + clr.R.ToString("X2", CultureInfo.InvariantCulture) +
clr.G.ToString("X2", CultureInfo.InvariantCulture) +
clr.B.ToString("X2", CultureInfo.InvariantCulture);
}
else
{
return "#FFFFFF";
}
}
}
}

View file

@ -1,43 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class MouseHighlighterProperties
{
[JsonPropertyName("activation_shortcut")]
public HotkeySettings ActivationShortcut { get; set; }
[JsonPropertyName("left_button_click_color")]
public StringProperty LeftButtonClickColor { get; set; }
[JsonPropertyName("right_button_click_color")]
public StringProperty RightButtonClickColor { get; set; }
[JsonPropertyName("highlight_opacity")]
public IntProperty HighlightOpacity { get; set; }
[JsonPropertyName("highlight_radius")]
public IntProperty HighlightRadius { get; set; }
[JsonPropertyName("highlight_fade_delay_ms")]
public IntProperty HighlightFadeDelayMs { get; set; }
[JsonPropertyName("highlight_fade_duration_ms")]
public IntProperty HighlightFadeDurationMs { get; set; }
public MouseHighlighterProperties()
{
ActivationShortcut = new HotkeySettings(true, false, false, true, 0x48);
LeftButtonClickColor = new StringProperty("#FFFF00");
RightButtonClickColor = new StringProperty("#0000FF");
HighlightOpacity = new IntProperty(160);
HighlightRadius = new IntProperty(20);
HighlightFadeDelayMs = new IntProperty(500);
HighlightFadeDurationMs = new IntProperty(250);
}
}
}

View file

@ -1,35 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json.Serialization;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class MouseHighlighterSettings : BasePTModuleSettings, ISettingsConfig
{
public const string ModuleName = "MouseHighlighter";
[JsonPropertyName("properties")]
public MouseHighlighterProperties Properties { get; set; }
public MouseHighlighterSettings()
{
Name = ModuleName;
Properties = new MouseHighlighterProperties();
Version = "1.0";
}
public string GetModuleName()
{
return Name;
}
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
{
return false;
}
}
}

View file

@ -1,29 +0,0 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.PowerToys.Settings.UI.Library
{
public class MouseHighlighterSettingsIPCMessage
{
[JsonPropertyName("powertoys")]
public SndMouseHighlighterSettings Powertoys { get; set; }
public MouseHighlighterSettingsIPCMessage()
{
}
public MouseHighlighterSettingsIPCMessage(SndMouseHighlighterSettings settings)
{
this.Powertoys = settings;
}
public string ToJsonString()
{
return JsonSerializer.Serialize(this);
}
}
}

Some files were not shown because too many files have changed in this diff Show more