Compare commits

..

15 commits

Author SHA1 Message Date
Laute c4a0364d57 Updates to titlebar 2021-11-20 16:16:08 +01:00
Stefan Markovic e6c6a8a046 Cleanup 2 2021-11-19 11:25:33 +01:00
Stefan Markovic a466bb3c14 Merge branch 'stefan/settings_to_winui3' of github.com:microsoft/PowerToys into stefan/settings_to_winui3 2021-11-19 11:01:31 +01:00
Stefan Markovic b57b40bf2f Various fixes 2021-11-19 11:01:08 +01:00
Laute 128106e603 Merge branch 'stefan/settings_to_winui3' of https://github.com/microsoft/PowerToys into stefan/settings_to_winui3 2021-11-18 09:39:59 +01:00
Stefan Markovic 2f698aae4c Use latest packages 2021-11-17 19:51:55 +01:00
Laute 9d6bb2fc43 Titlebar tweaks 2021-11-14 14:26:22 +01:00
Laute c49d41d6a8 Updated titlebar 2021-11-12 10:01:32 +01:00
Stefan Markovic 24474f82a9 VCM working 2021-11-10 15:34:46 +01:00
Stefan Markovic 85922cef2c Use it in runner - POC 2021-11-09 16:24:34 +01:00
Laute 5fce8863d8 Titlebar improvements 2021-11-07 14:59:27 +01:00
Stefan Markovic 9ad691a282 Make it work - WIP 2021-11-06 18:03:16 +01:00
Stefan Markovic 79bd4031be Make it build 2021-11-06 00:27:30 +01:00
Stefan Markovic ea7341bd1b Init 2 2021-11-05 18:04:26 +01:00
Stefan Markovic 00a2651664 Init 2021-11-05 08:53:25 +01:00
350 changed files with 14746 additions and 7157 deletions

View file

@ -631,7 +631,6 @@ Farbraum
FARPROC
fdw
feimage
FFAA
ffcd
FFDDDDDD
fff
@ -656,6 +655,7 @@ finalizer
findfast
findstr
FIXEDFILEINFO
FFAA
FLASHZONES
FLASHZONESONQUICKSWITCH
flt
@ -699,7 +699,6 @@ gdi
gdiplus
GDISCALED
generatesqlfromuserquery
GETDESKWALLPAPER
GETDISPINFO
GETDLGCODE
GETDPISCALEDSIZE
@ -734,7 +733,6 @@ Hardlines
HARDWAREINPUT
hashcode
Hashset
Hashtable
HASHVAL
hbitmap
hbmp
@ -763,10 +761,8 @@ hglobal
hhk
HHmmss
HHOOK
hhx
HICON
HIDEWINDOW
highlighter
HIMAGELIST
himl
hinst
@ -790,7 +786,6 @@ hmonitor
HOLDENTER
HOLDESC
homljgmgpmcbpjbnjpfijnhipfkiclkd
homepage
HOOKPROC
hostname
hotkeycontrol
@ -2086,7 +2081,6 @@ Switchbetweenvirtualdesktops
SWP
swprintf
SWRESTORE
swscanf
SYMED
SYMOPT
SYNCMFT
@ -2338,7 +2332,7 @@ VTABLE
Vtbl
wav
WBounds
wca
Wca
wcautil
WCE
wcex
@ -2443,7 +2437,6 @@ workaround
Workflow
workspaces
wostream
wostringstream
wox
wparam
wpf

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

@ -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,7 +371,7 @@ 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}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.PowerToys.Settings.UI.WinUI3", "src\settings-ui\Microsoft.PowerToys.Settings.UI.WinUI3\Microsoft.PowerToys.Settings.UI.WinUI3.csproj", "{496AB2AA-4BF0-4C1D-9598-DCCDA2B6E289}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -989,12 +988,12 @@ 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
{496AB2AA-4BF0-4C1D-9598-DCCDA2B6E289}.Debug|x64.ActiveCfg = Debug|x64
{496AB2AA-4BF0-4C1D-9598-DCCDA2B6E289}.Debug|x64.Build.0 = Debug|x64
{496AB2AA-4BF0-4C1D-9598-DCCDA2B6E289}.Debug|x86.ActiveCfg = Debug|x64
{496AB2AA-4BF0-4C1D-9598-DCCDA2B6E289}.Release|x64.ActiveCfg = Release|x64
{496AB2AA-4BF0-4C1D-9598-DCCDA2B6E289}.Release|x64.Build.0 = Release|x64
{496AB2AA-4BF0-4C1D-9598-DCCDA2B6E289}.Release|x86.ActiveCfg = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -1114,7 +1113,7 @@ 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}
{496AB2AA-4BF0-4C1D-9598-DCCDA2B6E289} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
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

View file

@ -26,7 +26,6 @@ The `WindowsSettings.json` use a JSON schema file that make it easier to edit it
| `Note` | Yes | String | `Note` |
| `IntroducedInBuild` | Yes | Integer | |
| `DeprecatedInBuild` | Yes | Integer | |
| `ShowAsFirstResult` | Yes | Boolean | |
A minimum entry for the `WindowsSettings.json` looks like:
@ -49,8 +48,7 @@ A full entry for the `WindowsSettings.json` looks like:
"AltNames": [ "NiceSetting" ],
"Note": "NoteMySettingNote",
"IntroducedInBuild" : 1903,
"DeprecatedInBuild" : 2004,
"ShowAsFirstResult" : true
"DeprecatedInBuild" : 2004
}
```
@ -67,12 +65,11 @@ A full entry for the `WindowsSettings.json` looks like:
There are three different score types with different start values.
| Score type | Start value |
| ------------------ | ------------ |
| First result score | 10500 |
| High score | 10000 |
| Medium score | 5000 |
| Low score | 1000 |
| Score type | Start value |
| ------------ | ------------ |
| High score | 10000 |
| Medium score | 5000 |
| Low score | 1000 |
Each score will decreased by one when a condition match.
@ -86,9 +83,6 @@ Each score will decreased by one when a condition match.
| 6. | One alternative name of the settings starts with the search value | Medium score |
| x. | no condition match | Low score |
### Remarks
* For each score condition we check if the property "ShowAsFirstResult" of the setting is true. If yes we use the firstResultScore instead of condition`s score.
## Important for developers
### General

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

@ -7,10 +7,6 @@ Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysSetup", "PowerToys
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToysSetupCustomActions", "PowerToysSetupCustomActions\PowerToysSetupCustomActions.vcxproj", "{32F3882B-F2D6-4586-B5ED-11E39E522BD3}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spdlog", "..\src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logger", "..\src\common\logger\logger.vcxproj", "{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
@ -25,14 +21,6 @@ Global
{32F3882B-F2D6-4586-B5ED-11E39E522BD3}.Debug|x64.Build.0 = Debug|x64
{32F3882B-F2D6-4586-B5ED-11E39E522BD3}.Release|x64.ActiveCfg = Release|x64
{32F3882B-F2D6-4586-B5ED-11E39E522BD3}.Release|x64.Build.0 = Release|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.Build.0 = Release|x64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.ActiveCfg = Debug|x64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.Build.0 = Debug|x64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.ActiveCfg = Release|x64
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

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

@ -2,9 +2,6 @@
#include "resource.h"
#include <ProjectTelemetry.h>
#include <spdlog/sinks/base_sink.h>
#include "../../src/common/logger/logger.h"
#include "../../src/common/utils/MsiUtils.h"
#include "../../src/common/utils/modulesRegistry.h"
#include "../../src/common/updating/installer.h"
@ -29,24 +26,6 @@ const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
struct WcaSink : spdlog::sinks::base_sink<std::mutex>
{
virtual void sink_it_(const spdlog::details::log_msg& msg) override
{
WcaLog(LOGMSG_STANDARD, msg.payload.data());
}
virtual void flush_() override
{
// we don't need to flush wca log manually
}
};
void initSystemLogger()
{
static std::once_flag initLoggerFlag;
std::call_once(initLoggerFlag, []() { Logger::init(std::vector<spdlog::sink_ptr>{ std::make_shared<WcaSink>() }); });
}
HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring& installationDir)
{
DWORD len = 0;
@ -55,7 +34,7 @@ HRESULT getInstallFolder(MSIHANDLE hInstall, std::wstring& installationDir)
len += 1;
installationDir.resize(len);
HRESULT hr = MsiGetPropertyW(hInstall, L"CustomActionData", installationDir.data(), &len);
if (installationDir.length())
if(installationDir.length())
{
installationDir.resize(installationDir.length() - 1);
}
@ -65,30 +44,24 @@ LExit:
}
UINT __stdcall ApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
{
initSystemLogger();
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder;
bool failedToApply = false;
hr = WcaInitialize(hInstall, "ApplyModulesRegistryChangeSets");
ExitOnFailure(hr, "Failed to initialize");
hr = getInstallFolder(hInstall, installationFolder);
ExitOnFailure(hr, "Failed to get installFolder.");
for (const auto& changeSet : getAllModulesChangeSets(installationFolder, false))
{
if (!changeSet.apply())
{
WcaLog(LOGMSG_STANDARD, "Couldn't apply registry changeSet");
failedToApply = true;
}
}
if (!failedToApply)
{
WcaLog(LOGMSG_STANDARD, "All registry changeSets applied successfully");
}
ExitOnFailure(hr, "Failed to extract msix");
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
@ -96,7 +69,6 @@ LExit:
UINT __stdcall UnApplyModulesRegistryChangeSetsCA(MSIHANDLE hInstall)
{
initSystemLogger();
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
std::wstring installationFolder;

View file

@ -30,7 +30,6 @@
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="..\..\deps\spdlog.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
@ -123,11 +122,6 @@
<ItemGroup>
<ResourceCompile Include="Resource.rc" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\common\logger\logger.vcxproj">
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View file

@ -27,7 +27,6 @@
#include <psapi.h>
#include <vector>
#include <array>
#include <mutex>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>

View file

@ -3,7 +3,7 @@
#include "pch.h"
#include "framework.h"
#include "logger.h"
#include <unordered_map>
#include <map>
#include <spdlog/sinks/daily_file_sink.h>
#include <spdlog/sinks/msvc_sink.h>
#include <spdlog/sinks/null_sink.h>
@ -16,32 +16,26 @@ using spdlog::sinks::daily_file_sink_mt;
using spdlog::sinks::msvc_sink_mt;
using std::make_shared;
namespace
{
const std::unordered_map<std::wstring, level_enum> logLevelMapping = {
{ L"trace", level_enum::trace },
{ L"debug", level_enum::debug },
{ L"info", level_enum::info },
{ L"warn", level_enum::warn },
{ L"err", level_enum::err },
{ L"critical", level_enum::critical },
{ L"off", level_enum::off },
};
}
std::map<std::wstring, level_enum> logLevelMapping = {
{ L"trace", level_enum::trace },
{ L"debug", level_enum::debug },
{ L"info", level_enum::info },
{ L"warn", level_enum::warn },
{ L"err", level_enum::err },
{ L"critical", level_enum::critical },
{ L"off", level_enum::off },
};
level_enum getLogLevel(std::wstring_view logSettingsPath)
{
auto logLevel = get_log_settings(logSettingsPath).logLevel;
if (auto it = logLevelMapping.find(logLevel); it != logLevelMapping.end())
level_enum result = logLevelMapping[LogSettings::defaultLogLevel];
if (logLevelMapping.find(logLevel) != logLevelMapping.end())
{
return it->second;
result = logLevelMapping[logLevel];
}
if (auto it = logLevelMapping.find(LogSettings::defaultLogLevel); it != logLevelMapping.end())
{
return it->second;
}
return level_enum::trace;
return result;
}
std::shared_ptr<spdlog::logger> Logger::logger = spdlog::null_logger_mt("null");
@ -95,14 +89,3 @@ void Logger::init(std::string loggerName, std::wstring logFilePath, std::wstring
spdlog::flush_every(std::chrono::seconds(3));
logger->info("{} logger is initialized", loggerName);
}
void Logger::init(std::vector<spdlog::sink_ptr> sinks)
{
auto logger = std::make_shared<spdlog::logger>("", begin(sinks), end(sinks));
if (!logger)
{
return;
}
Logger::logger = logger;
}

View file

@ -13,7 +13,6 @@ public:
Logger() = delete;
static void init(std::string loggerName, std::wstring logFilePath, std::wstring_view logSettingsPath);
static void init(std::vector<spdlog::sink_ptr> sinks);
// log message should not be localized
template<typename FormatString, typename... Args>

View file

@ -31,14 +31,12 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="call_tracer.h" />
<ClInclude Include="framework.h" />
<ClInclude Include="logger.h" />
<ClInclude Include="logger_settings.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="call_tracer.cpp" />
<ClCompile Include="logger.cpp" />
<ClCompile Include="logger_settings.cpp" />
<ClCompile Include="pch.cpp">
@ -52,6 +50,9 @@
<ProjectReference Include="..\..\logging\logging.vcxproj">
<Project>{7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f}</Project>
</ProjectReference>
<ProjectReference Include="..\SettingsAPI\SetttingsAPI.vcxproj">
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View file

@ -27,9 +27,6 @@
<ClInclude Include="logger_settings.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="call_tracer.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="logger.cpp">
@ -41,9 +38,6 @@
<ClCompile Include="logger_settings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="call_tracer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View file

@ -9,7 +9,7 @@ using namespace winrt::Windows::Data::Json;
LogSettings::LogSettings()
{
logLevel = defaultLogLevel;
this->logLevel = LogSettings::defaultLogLevel;
}
std::optional<JsonObject> from_file(std::wstring_view file_name)

View file

@ -13,8 +13,6 @@ struct LogSettings
inline const static std::wstring actionRunnerLogPath = L"RunnerLogs\\action-runner-log.txt";
inline const static std::string updateLoggerName = "update";
inline const static std::wstring updateLogPath = L"UpdateLogs\\update-log.txt";
inline const static std::string fileExplorerLoggerName = "FileExplorer";
inline const static std::wstring fileExplorerLogPath = L"Logs\\file-explorer-log.txt";
inline const static std::string launcherLoggerName = "launcher";
inline const static std::wstring launcherLogPath = L"LogsModuleInterface\\launcher-log.txt";
inline const static std::wstring awakeLogPath = L"Logs\\awake-log.txt";
@ -26,8 +24,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;
LogSettings();

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,10 +8,7 @@
#include <vector>
#include <optional>
#include <cassert>
#include <sstream>
#include "../logger/logger.h"
#include "../utils/winapi_error.h"
#include "../version/version.h"
namespace registry
@ -38,28 +35,7 @@ namespace registry
template<class... Ts>
overloaded(Ts...) -> overloaded<Ts...>;
inline const wchar_t* getScopeName(HKEY scope)
{
if (scope == HKEY_LOCAL_MACHINE)
{
return L"HKLM";
}
else if (scope == HKEY_CURRENT_USER)
{
return L"HKCU";
}
else if (scope == HKEY_CLASSES_ROOT)
{
return L"HKCR";
}
else
{
return L"HK??";
}
}
}
struct ValueChange
{
using value_t = std::variant<DWORD, std::wstring>;
@ -75,28 +51,11 @@ namespace registry
{
}
std::wstring toString() const
{
using namespace detail;
std::wstring value_str;
std::visit(overloaded{ [&](DWORD value) {
std::wostringstream oss;
oss << value;
value_str = oss.str();
},
[&](const std::wstring& value) { value_str = value; } },
value);
return fmt::format(L"{}\\{}\\{}:{}", detail::getScopeName(scope), path, name ? *name : L"Default", value_str);
}
bool isApplied() const
{
HKEY key{};
if (auto res = RegOpenKeyExW(scope, path.c_str(), 0, KEY_READ, &key); res != ERROR_SUCCESS)
if (RegOpenKeyExW(scope, path.c_str(), 0, KEY_READ, &key) != ERROR_SUCCESS)
{
Logger::info(L"isApplied of {}: RegOpenKeyExW failed: {}", toString(), get_last_error_or_default(res));
return false;
}
detail::on_exit closeKey{ [key] { RegCloseKey(key); } };
@ -106,15 +65,13 @@ namespace registry
DWORD retrievedType{};
wchar_t buffer[VALUE_BUFFER_SIZE];
DWORD valueSize = sizeof(buffer);
if (auto res = RegQueryValueExW(key,
name.has_value() ? name->c_str() : nullptr,
0,
&retrievedType,
reinterpret_cast<LPBYTE>(&buffer),
&valueSize);
res != ERROR_SUCCESS)
if (RegQueryValueExW(key,
name.has_value() ? name->c_str() : nullptr,
0,
&retrievedType,
reinterpret_cast<LPBYTE>(&buffer),
&valueSize) != ERROR_SUCCESS)
{
Logger::info(L"isApplied of {}: RegQueryValueExW failed: {}", toString(), get_last_error_or_default(res));
return false;
}
@ -137,10 +94,9 @@ namespace registry
{
HKEY key{};
if (auto res = RegCreateKeyExW(scope, path.c_str(), 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &key, nullptr); res !=
ERROR_SUCCESS)
if (RegCreateKeyExW(scope, path.c_str(), 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &key, nullptr) !=
ERROR_SUCCESS)
{
Logger::error(L"apply of {}: RegCreateKeyExW failed: {}", toString(), get_last_error_or_default(res));
return false;
}
detail::on_exit closeKey{ [key] { RegCloseKey(key); } };
@ -150,35 +106,26 @@ namespace registry
DWORD valueType;
valueToBuffer(value, buffer, valueSize, valueType);
if (auto res = RegSetValueExW(key,
name.has_value() ? name->c_str() : nullptr,
0,
valueType,
reinterpret_cast<BYTE*>(buffer),
valueSize);
res != ERROR_SUCCESS)
{
Logger::error(L"apply of {}: RegSetValueExW failed: {}", toString(), get_last_error_or_default(res));
return false;
}
return true;
return RegSetValueExW(key,
name.has_value() ? name->c_str() : nullptr,
0,
valueType,
reinterpret_cast<BYTE*>(buffer),
valueSize) == ERROR_SUCCESS;
}
bool unApply() const
{
HKEY key{};
if (auto res = RegOpenKeyExW(scope, path.c_str(), 0, KEY_ALL_ACCESS, &key); res != ERROR_SUCCESS)
if (RegOpenKeyExW(scope, path.c_str(), 0, KEY_ALL_ACCESS, &key) != ERROR_SUCCESS)
{
Logger::error(L"unApply of {}: RegOpenKeyExW failed: {}", toString(), get_last_error_or_default(res));
return false;
}
detail::on_exit closeKey{ [key] { RegCloseKey(key); } };
// delete the value itself
if (auto res = RegDeleteKeyValueW(scope, path.c_str(), name.has_value() ? name->c_str() : nullptr); res != ERROR_SUCCESS)
if (RegDeleteKeyValueW(scope, path.c_str(), name.has_value() ? name->c_str() : nullptr) != ERROR_SUCCESS)
{
Logger::error(L"unApply of {}: RegDeleteKeyValueW failed: {}", toString(), get_last_error_or_default(res));
return false;
}

View file

@ -19,6 +19,8 @@ namespace ABI
}
#endif
bool m_doNotActivateOnGameMode = true;
#pragma region Super_Sonar_Base_Code
template<typename D>
@ -53,16 +55,13 @@ protected:
POINT m_sonarPos = ptNowhere;
// Only consider double left control click if at least 100ms passed between the clicks, to avoid keyboards that might be sending rapid clicks.
// 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 +140,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 +149,6 @@ void SuperSonar<D>::Terminate()
{
auto dispatcherQueue = m_dispatcherQueueController.DispatcherQueue();
bool enqueueSucceeded = dispatcherQueue.TryEnqueue([=]() {
m_destroyed = true;
DestroyWindow(m_hwndOwner);
});
if (!enqueueSucceeded)
@ -314,10 +312,9 @@ void SuperSonar<D>::OnSonarKeyboardInput(RAWINPUT const& input)
auto now = GetTickCount();
auto doubleClickInterval = now - m_lastKeyTime;
POINT ptCursor{};
auto doubleClickTimeSetting = GetDoubleClickTime();
if (GetCursorPos(&ptCursor) &&
doubleClickInterval >= min(MIN_DOUBLE_CLICK_TIME, doubleClickTimeSetting / 5) &&
doubleClickInterval <= doubleClickTimeSetting &&
doubleClickInterval >= MIN_DOUBLE_CLICK_TIME &&
doubleClickInterval <= GetDoubleClickTime() &&
IsEqual(m_lastKeyPos, ptCursor))
{
m_sonarState = SonarState::ControlDown2;
@ -458,7 +455,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 +487,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 +529,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 +579,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 +586,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 +629,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 +664,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 +790,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 +805,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 +821,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

@ -157,9 +157,6 @@
<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>
<ProjectReference Include="..\..\..\common\Themes\Themes.vcxproj">
<Project>{98537082-0fdb-40de-abd8-0dc5a4269bab}</Project>
</ProjectReference>

View file

@ -463,36 +463,27 @@ void D2DOverlayWindow::init()
{
colors.update();
landscape.load(L"svgs\\overlay.svg", d2d_dc.get())
.find_thumbnail(L"monitorRect")
.find_window_group(L"WindowControlsGroup")
.recolor(0x2582FB, colors.start_color_menu);
.find_thumbnail(L"path-1")
.find_window_group(L"Group-1")
.recolor(0x000000, colors.start_color_menu);
portrait.load(L"svgs\\overlay_portrait.svg", d2d_dc.get())
.find_thumbnail(L"monitorRect")
.find_window_group(L"WindowControlsGroup")
.recolor(0x2582FB, colors.start_color_menu);
.find_thumbnail(L"path-1")
.find_window_group(L"Group-1")
.recolor(0x000000, colors.start_color_menu);
no_active.load(L"svgs\\no_active_window.svg", d2d_dc.get());
arrows.resize(10);
for (unsigned i = 0; i < arrows.size(); ++i)
{
arrows[i].load(L"svgs\\" + std::to_wstring((i + 1) % 10) + L".svg", d2d_dc.get()).recolor(0x2582FB, colors.start_color_menu);
arrows[i].load(L"svgs\\" + std::to_wstring((i + 1) % 10) + L".svg", d2d_dc.get()).recolor(0x000000, colors.start_color_menu);
}
light_mode = (theme_setting == Light) || (theme_setting == System && colors.light_mode);
if (light_mode)
if (!light_mode)
{
landscape.recolor(0x2E17FC, 0x000000);
portrait.recolor(0x2E17FC, 0x000000);
landscape.recolor(0x222222, 0xDDDDDD);
portrait.recolor(0x222222, 0xDDDDDD);
for (auto& arrow : arrows)
{
arrow.recolor(0x222222, 0x000000);
}
}
else
{
landscape.recolor(0x2E17FC, 0xFFFFFF);
portrait.recolor(0x2E17FC, 0xFFFFFF);
for (auto& arrow : arrows)
{
arrow.recolor(0x222222, 0xFFFFFF);
arrow.recolor(0x222222, 0xDDDDDD);
}
}
}
@ -505,13 +496,13 @@ void D2DOverlayWindow::resize()
{ // portrait is broke right now
use_overlay = &landscape;
no_active_scale = 0.3f;
font = 12.0f;
font = 15.0f;
}
else
{
use_overlay = &portrait;
no_active_scale = 0.5f;
font = 13.0f;
font = 16.0f;
}
use_overlay->resize(0, 0, window_width, window_height, 0.8f);
auto thumb_no_active_rect = use_overlay->get_thumbnail_rect_and_scale(0, 0, no_active.width(), no_active.height(), no_active_scale).rect;
@ -727,7 +718,7 @@ void D2DOverlayWindow::render(ID2D1DeviceContext5* d2d_dc)
// render the monitors
if (render_monitors)
{
brushColor = D2D1::ColorF(colors.start_color_menu, miniature_shown ? current_anim_value * 0.9f : current_anim_value * 0.3f);
brushColor = D2D1::ColorF(colors.desktop_fill_color, miniature_shown ? current_anim_value : current_anim_value * 0.3f);
brush = nullptr;
winrt::check_hresult(d2d_dc->CreateSolidColorBrush(brushColor, brush.put()));
for (auto& monitor : monitors)

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_0" data-name="0">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M13.968,15.171a2.7,2.7,0,0,1-2.427-1.251,6.713,6.713,0,0,1-.813-3.644,7.215,7.215,0,0,1,.868-3.9,2.784,2.784,0,0,1,2.481-1.343,2.684,2.684,0,0,1,2.468,1.251,7.283,7.283,0,0,1,.772,3.76,6.981,6.981,0,0,1-.861,3.8A2.79,2.79,0,0,1,13.968,15.171ZM14.05,6.3a1.365,1.365,0,0,0-1.289.981,7.967,7.967,0,0,0-.414,2.943,7.039,7.039,0,0,0,.414,2.758,1.345,1.345,0,0,0,1.268.919,1.323,1.323,0,0,0,1.268-.94,7.716,7.716,0,0,0,.393-2.827A7.991,7.991,0,0,0,15.3,7.258,1.315,1.315,0,0,0,14.05,6.3Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>0</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-7.000000, -159.000000)">
<g id="0" transform="translate(7.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<path d="M26.5,31.1376953 C24.166655,31.1376953 23,29.4993653 23,26.2226562 C23,24.522778 23.3155893,23.2273808 23.9467773,22.3364258 C24.5779654,21.4454708 25.4928325,21 26.6914062,21 C28.9700635,21 30.109375,22.6656734 30.109375,25.9970703 C30.109375,27.6559328 29.798343,28.9274044 29.1762695,29.8115234 C28.5541961,30.6956424 27.6621152,31.1376953 26.5,31.1376953 Z M26.5957031,22.6474609 C25.6614537,22.6474609 25.1943359,23.8209518 25.1943359,26.1679688 C25.1943359,28.3782663 25.6523392,29.4833984 26.5683594,29.4833984 C27.461593,29.4833984 27.9082031,28.3440869 27.9082031,26.0654297 C27.9082031,23.7867725 27.4707075,22.6474609 26.5957031,22.6474609 Z" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_1" data-name="1">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M15.277,15H13.691V7.022a4.525,4.525,0,0,1-.868.482,8.428,8.428,0,0,1-1.08.4l-.437-1.319a8.886,8.886,0,0,0,1.716-.673,7.345,7.345,0,0,0,1.436-.933h.82Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
</svg>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>1</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-67.000000, -159.000000)">
<g id="1" transform="translate(67.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<polygon fill="#FFFFFF" fill-rule="nonzero" points="30.2548828 30.9667969 24.0546875 30.9667969 24.0546875 29.2578125 26.0849609 29.2578125 26.0849609 23.1533203 24 23.6044922 24 21.8544922 28.2382812 21 28.2382812 29.2578125 30.2548828 29.2578125"></polygon>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_2" data-name="2">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M10.974,15v-.6a3.649,3.649,0,0,1,.188-1.217A3.508,3.508,0,0,1,11.7,12.2a5.092,5.092,0,0,1,.827-.851q.485-.4,1.073-.831a7.588,7.588,0,0,0,.824-.66,5.023,5.023,0,0,0,.571-.625,1.98,1.98,0,0,0,.328-.625,2.443,2.443,0,0,0,.109-.742,1.561,1.561,0,0,0-.4-1.1,1.448,1.448,0,0,0-1.121-.431,3.157,3.157,0,0,0-1.135.229,3.742,3.742,0,0,0-1.135.708L10.8,6.291A4.651,4.651,0,0,1,14.1,5.033a2.9,2.9,0,0,1,2.167.786,2.564,2.564,0,0,1,.772,1.859,3.645,3.645,0,0,1-.178,1.2,3.375,3.375,0,0,1-.479.913,4.918,4.918,0,0,1-.728.807,10.746,10.746,0,0,1-.94.745q-.526.369-.909.66a5.2,5.2,0,0,0-.629.55,1.988,1.988,0,0,0-.373.526,1.324,1.324,0,0,0-.12.561h4.553V15Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>2</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-127.000000, -159.000000)">
<g id="2" transform="translate(127.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<path d="M26.4746094,29.1347656 L26.4746094,29.1757812 L30.453125,29.1757812 L30.453125,30.9667969 L24,30.9667969 L24,29.2851562 L26.8095703,26.5986328 C27.3746773,26.0563124 27.772297,25.6017271 28.0024414,25.2348633 C28.2325858,24.8679995 28.3476562,24.4817729 28.3476562,24.0761719 C28.3476562,23.1738236 27.8623095,22.7226562 26.8916016,22.7226562 C26.0484984,22.7226562 25.2418658,23.0576138 24.4716797,23.7275391 L24.4716797,21.8271484 C25.3238975,21.2757134 26.2854764,21 27.3564453,21 C28.3590545,21 29.1417615,21.2517878 29.7045898,21.7553711 C30.2674182,22.2589543 30.5488281,22.9391233 30.5488281,23.7958984 C30.5488281,24.9397844 29.8629626,26.1223897 28.4912109,27.34375 L26.4746094,29.1347656 Z" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_3" data-name="3">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M10.857,14.344l.663-1.094a4.564,4.564,0,0,0,1.036.5,3.6,3.6,0,0,0,1.083.154,2,2,0,0,0,1.446-.461,1.516,1.516,0,0,0,.475-1.131,1.453,1.453,0,0,0-.636-1.3,3.3,3.3,0,0,0-1.832-.424h-.807V9.319h.752a2.827,2.827,0,0,0,1.644-.393,1.435,1.435,0,0,0,.55-1.254,1.3,1.3,0,0,0-.4-1.022A1.477,1.477,0,0,0,13.817,6.3a3.274,3.274,0,0,0-1.008.164,4.127,4.127,0,0,0-1.029.513l-.67-1.053A4.8,4.8,0,0,1,14,5.033a3.1,3.1,0,0,1,2.071.663,2.192,2.192,0,0,1,.786,1.764,2.46,2.46,0,0,1-.455,1.5,2.608,2.608,0,0,1-1.371.9v.027a2.585,2.585,0,0,1,1.555.762,2.2,2.2,0,0,1,.6,1.583,2.679,2.679,0,0,1-.926,2.129,3.629,3.629,0,0,1-2.464.8,5.294,5.294,0,0,1-2.933-.827Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>3</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-187.000000, -159.000000)">
<g id="3" transform="translate(187.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<path d="M24,30.6455078 L24,28.765625 C24.6562533,29.244143 25.4218706,29.4833984 26.296875,29.4833984 C26.84831,29.4833984 27.2778305,29.36491 27.5854492,29.1279297 C27.8930679,28.8909493 28.046875,28.560549 28.046875,28.1367188 C28.046875,27.6992166 27.85661,27.3619804 27.4760742,27.125 C27.0955385,26.8880196 26.5725945,26.7695312 25.9072266,26.7695312 L25.0253906,26.7695312 L25.0253906,25.1152344 L25.8388672,25.1152344 C27.1149152,25.1152344 27.7529297,24.6914105 27.7529297,23.84375 C27.7529297,23.04622 27.2630257,22.6474609 26.2832031,22.6474609 C25.6269498,22.6474609 24.9889354,22.8593729 24.3691406,23.2832031 L24.3691406,21.5195312 C25.0572951,21.1731754 25.8593704,21 26.7753906,21 C27.7779998,21 28.5584282,21.2255837 29.1166992,21.6767578 C29.6749702,22.1279319 29.9541016,22.7135381 29.9541016,23.4335938 C29.9541016,24.7141991 29.304694,25.5162744 28.0058594,25.8398438 L28.0058594,25.8740234 C28.6985712,25.9606124 29.2454407,26.2124003 29.6464844,26.6293945 C30.047528,27.0463888 30.2480469,27.5579397 30.2480469,28.1640625 C30.2480469,29.0800827 29.9130893,29.8046848 29.2431641,30.3378906 C28.5732388,30.8710964 27.6481179,31.1376953 26.4677734,31.1376953 C25.4560496,31.1376953 24.6334667,30.9736345 24,30.6455078 Z" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_4" data-name="4">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M16.576,5.149v6.405h1.032V12.86H16.576v2.194H14.983V12.86H10.43V11.555q.629-.69,1.275-1.494t1.241-1.637q.595-.834,1.1-1.671a15.328,15.328,0,0,0,.858-1.6Zm-4.532,6.405h2.939v-4.2q-.41.7-.8,1.3t-.752,1.114q-.376.52-.721.957T12.043,11.555Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
</svg>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>4</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-247.000000, -159.000000)">
<g id="4" transform="translate(247.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<path d="M30.4169922,28.7177734 L29.2412109,28.7177734 L29.2412109,30.8027344 L27.2724609,30.8027344 L27.2724609,28.7177734 L23,28.7177734 L23,27.34375 L27.1152344,21 L29.2412109,21 L29.2412109,27.1796875 L30.4169922,27.1796875 L30.4169922,28.7177734 Z M27.2998047,23.1601562 L27.2587891,23.1601562 C27.1949867,23.3242196 27.071941,23.5794254 26.8896484,23.9257812 L24.7910156,27.1796875 L27.2724609,27.1796875 L27.2724609,24.0966797 C27.2724609,23.8232408 27.2815754,23.5110695 27.2998047,23.1601562 Z" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_5" data-name="5">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M10.816,14.18l.772-1.012a3.292,3.292,0,0,0,2.1.731,1.913,1.913,0,0,0,1.395-.513,1.753,1.753,0,0,0,.526-1.312,1.613,1.613,0,0,0-.588-1.35,2.748,2.748,0,0,0-1.723-.461q-.39,0-.841.027t-.861.075L11.944,5.2h4.826V6.551H13.223l-.171,2.461q.239-.014.475-.024t.427-.01a3.435,3.435,0,0,1,2.4.79,2.8,2.8,0,0,1,.868,2.177,3.054,3.054,0,0,1-.954,2.328,3.532,3.532,0,0,1-2.526.9,4.532,4.532,0,0,1-2.926-.991Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>5</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-307.000000, -159.000000)">
<g id="5" transform="translate(307.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<path d="M24,30.5498047 L24,28.7041016 C24.6699252,29.1142599 25.3831342,29.3193359 26.1396484,29.3193359 C26.7093127,29.3193359 27.1547835,29.1837579 27.4760742,28.9125977 C27.7973649,28.6414374 27.9580078,28.2734398 27.9580078,27.8085938 C27.9580078,26.8378858 27.2721423,26.3525391 25.9003906,26.3525391 C25.4537738,26.3525391 24.9137401,26.3935543 24.2802734,26.4755859 L24.2802734,21 L29.7080078,21 L29.7080078,22.7636719 L26.1259766,22.7636719 L26.1259766,24.7255859 C26.4130874,24.6982421 26.6842435,24.6845703 26.9394531,24.6845703 C27.9466196,24.6845703 28.7350232,24.9488906 29.3046875,25.4775391 C29.8743518,26.0061875 30.1591797,26.7171179 30.1591797,27.6103516 C30.1591797,28.5992888 29.8196649,29.4070607 29.140625,30.0336914 C28.4615851,30.6603221 27.5410214,30.9736328 26.3789062,30.9736328 C25.4355422,30.9736328 24.6425813,30.8323582 24,30.5498047 Z" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_6" data-name="6">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M17.249,11.849a3.289,3.289,0,0,1-.9,2.4,3.053,3.053,0,0,1-2.283.926A2.824,2.824,0,0,1,11.654,14a5.564,5.564,0,0,1-.865-3.346,10.182,10.182,0,0,1,.236-2.211,5.023,5.023,0,0,1,.837-1.89,3.714,3.714,0,0,1,1.292-1.142,3.851,3.851,0,0,1,1.777-.376,3.546,3.546,0,0,1,1.039.161,3.365,3.365,0,0,1,1.06.571l-.807,1a2.328,2.328,0,0,0-.636-.352,2.2,2.2,0,0,0-.731-.113,2.074,2.074,0,0,0-.995.232,2.535,2.535,0,0,0-.81.731,3.2,3.2,0,0,0-.513,1.094,5.618,5.618,0,0,0-.185,1.436h.034a2.468,2.468,0,0,1,.947-.749,2.885,2.885,0,0,1,1.193-.25,2.5,2.5,0,0,1,1.979.844A3.228,3.228,0,0,1,17.249,11.849Zm-1.545.082a2.094,2.094,0,0,0-.417-1.422,1.413,1.413,0,0,0-1.114-.472,1.652,1.652,0,0,0-1.289.516,1.818,1.818,0,0,0-.468,1.268,2.34,2.34,0,0,0,.461,1.49,1.461,1.461,0,0,0,1.207.588,1.477,1.477,0,0,0,1.179-.513A2.167,2.167,0,0,0,15.7,11.931Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>6</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-367.000000, -159.000000)">
<g id="6" transform="translate(367.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<path d="M30.2070312,21.2666016 L30.2070312,23.0712891 C29.710284,22.7887356 29.1679717,22.6474609 28.5800781,22.6474609 C27.8554651,22.6474609 27.2709983,22.9243136 26.8266602,23.4780273 C26.382322,24.031741 26.1510418,24.7734329 26.1328125,25.703125 L26.1738281,25.703125 C26.6432315,25.0104132 27.3290971,24.6640625 28.2314453,24.6640625 C29.0517619,24.6640625 29.7023088,24.9420545 30.1831055,25.4980469 C30.6639021,26.0540392 30.9042969,26.7900345 30.9042969,27.7060547 C30.9042969,28.6904346 30.5852896,29.5084603 29.9472656,30.1601562 C29.3092416,30.8118522 28.4980518,31.1376953 27.5136719,31.1376953 C26.4108018,31.1376953 25.5494823,30.7389363 24.9296875,29.9414062 C24.3098927,29.1438762 24,28.0250723 24,26.5849609 C24,24.88964 24.398759,23.5349986 25.1962891,22.5209961 C25.9938191,21.5069936 27.076165,21 28.4433594,21 C29.1998736,21 29.7877583,21.0888663 30.2070312,21.2666016 Z M27.5,26.2636719 C27.1035136,26.2636719 26.7879244,26.4026679 26.5532227,26.6806641 C26.318521,26.9586602 26.2011719,27.3141254 26.2011719,27.7470703 C26.2011719,28.2255883 26.3207996,28.6346012 26.5600586,28.9741211 C26.7993176,29.313641 27.1171855,29.4833984 27.5136719,29.4833984 C27.9010436,29.4833984 28.2109363,29.33187 28.4433594,29.0288086 C28.6757824,28.7257472 28.7919922,28.3304061 28.7919922,27.8427734 C28.7919922,26.7900338 28.3613324,26.2636719 27.5,26.2636719 Z" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_7" data-name="7">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M17.164,6.113A43.443,43.443,0,0,0,15.1,10.4,19.372,19.372,0,0,0,13.869,15h-1.62a18.538,18.538,0,0,1,1.285-4.539,37.232,37.232,0,0,1,1.935-3.91H10.875V5.2h6.289Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>7</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-427.000000, -159.000000)">
<g id="7" transform="translate(427.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<polygon fill="#FFFFFF" fill-rule="nonzero" points="30.8222656 21.9980469 27.3632812 30.8027344 25.0800781 30.8027344 28.5664062 22.7636719 24 22.7636719 24 21 30.8222656 21"></polygon>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_8" data-name="8">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M10.728,12.307A2.72,2.72,0,0,1,12.5,9.764a2.918,2.918,0,0,1-1.019-.93,2.225,2.225,0,0,1-.369-1.251,2.323,2.323,0,0,1,.827-1.825,3.059,3.059,0,0,1,2.092-.725,3.069,3.069,0,0,1,2.1.725,2.309,2.309,0,0,1,.827,1.812,2.157,2.157,0,0,1-.383,1.244,3.029,3.029,0,0,1-1.039.93,2.666,2.666,0,0,1,1.319,1.046,2.742,2.742,0,0,1,.458,1.511,2.613,2.613,0,0,1-.909,2.061,3.479,3.479,0,0,1-2.379.8,3.518,3.518,0,0,1-2.382-.793A2.59,2.59,0,0,1,10.728,12.307Zm1.565-.137a1.693,1.693,0,0,0,.482,1.278,1.905,1.905,0,0,0,2.5-.007,1.672,1.672,0,0,0,.5-1.271,1.74,1.74,0,0,0-.479-1.23,1.64,1.64,0,0,0-1.258-.513,1.689,1.689,0,0,0-1.743,1.743Zm.321-4.457a1.415,1.415,0,0,0,.424,1.053,1.423,1.423,0,0,0,2.013,0,1.409,1.409,0,0,0,.427-1.053A1.414,1.414,0,0,0,14.043,6.25a1.362,1.362,0,0,0-1.029.417A1.451,1.451,0,0,0,12.614,7.713Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>8</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-487.000000, -159.000000)">
<g id="8" transform="translate(487.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<path d="M25.9755859,25.8740234 L25.9755859,25.8398438 C24.8544866,25.379555 24.2939453,24.6344453 24.2939453,23.6044922 C24.2939453,22.847978 24.5947236,22.2247746 25.1962891,21.7348633 C25.7978546,21.244952 26.574865,21 27.5273438,21 C28.4980517,21 29.2727836,21.2290016 29.8515625,21.6870117 C30.4303414,22.1450218 30.7197266,22.7363245 30.7197266,23.4609375 C30.7197266,24.5319064 30.0999411,25.32031 28.8603516,25.8261719 L28.8603516,25.8535156 C29.5257195,26.0494801 30.0418276,26.3719053 30.4086914,26.8208008 C30.7755552,27.2696963 30.9589844,27.7744113 30.9589844,28.3349609 C30.9589844,29.2008507 30.6388378,29.8844376 29.9985352,30.3857422 C29.3582325,30.8870468 28.4638729,31.1376953 27.3154297,31.1376953 C26.3219351,31.1376953 25.5209991,30.8927433 24.9125977,30.402832 C24.3041962,29.9129207 24,29.2646525 24,28.4580078 C24,27.286778 24.6585221,26.4254585 25.9755859,25.8740234 Z M28.6894531,23.6455078 C28.6894531,23.3128239 28.5834972,23.0473643 28.371582,22.8491211 C28.1596669,22.6508779 27.878257,22.5517578 27.5273438,22.5517578 C27.1855452,22.5517578 26.9018566,22.6554352 26.6762695,22.862793 C26.4506825,23.0701508 26.3378906,23.3356104 26.3378906,23.6591797 C26.3378906,24.2698598 26.7298138,24.7324203 27.5136719,25.046875 C28.29753,24.7233057 28.6894531,24.2561879 28.6894531,23.6455078 Z M27.4179688,26.6943359 C26.5019485,27.0543638 26.0439453,27.6057906 26.0439453,28.3486328 C26.0439453,28.7041033 26.1840806,28.9980457 26.4643555,29.2304688 C26.7446303,29.4628918 27.0852845,29.5791016 27.4863281,29.5791016 C27.919273,29.5791016 28.2679023,29.4651704 28.5322266,29.2373047 C28.7965508,29.009439 28.9287109,28.7086607 28.9287109,28.3349609 C28.9287109,27.5875614 28.4251352,27.0406918 27.4179688,26.6943359 Z" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -1,21 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="53px" height="52px" viewBox="0 0 53 52" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Artboard" clip-path="url(#clip-Artboard)">
<g id="_9" data-name="9">
<rect id="Rectangle" width="29" height="36" rx="4" transform="translate(13 8)" fill="#2582fb"/>
<g id="bottom">
<rect id="carat" width="14" height="14" transform="translate(18 39) rotate(-45)" fill="#2582fb"/>
</g>
<g id="left">
<rect id="carat-2" data-name="carat" width="14" height="14" transform="translate(7.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="right">
<rect id="carat-3" data-name="carat" width="14" height="14" transform="translate(26.899 26) rotate(-45)" fill="#2582fb"/>
</g>
<g id="top">
<rect id="carat-4" data-name="carat" width="14" height="14" transform="translate(18 13) rotate(-45)" fill="#2582fb"/>
</g>
<path id="A" d="M17.27,9.565a7.426,7.426,0,0,1-.974,4.163,3.4,3.4,0,0,1-3.032,1.442,3.851,3.851,0,0,1-1.336-.222,3.755,3.755,0,0,1-1.159-.7l.827-.978a2.674,2.674,0,0,0,.779.465,2.74,2.74,0,0,0,.957.15,2.071,2.071,0,0,0,1.791-.865,4.586,4.586,0,0,0,.622-2.663l-.034-.007a2.05,2.05,0,0,1-.834.81,2.651,2.651,0,0,1-1.237.27,2.617,2.617,0,0,1-2.017-.854,3.1,3.1,0,0,1-.786-2.187,3.316,3.316,0,0,1,.913-2.427,3.13,3.13,0,0,1,2.334-.93,2.708,2.708,0,0,1,2.348,1.189A5.744,5.744,0,0,1,17.27,9.565Zm-1.6-1.073a2.551,2.551,0,0,0-.465-1.576,1.487,1.487,0,0,0-2.362-.068,2.071,2.071,0,0,0-.461,1.377,2.044,2.044,0,0,0,.461,1.429,1.572,1.572,0,0,0,1.22.506,1.513,1.513,0,0,0,1.148-.485A1.659,1.659,0,0,0,15.67,8.492Z" transform="translate(13.5 15.689)" fill="#fff"/>
</g>
</g>
<!-- Generator: Sketch 54.1 (76490) - https://sketchapp.com -->
<title>9</title>
<desc>Created with Sketch.</desc>
<g id="Devices" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard" transform="translate(-547.000000, -159.000000)">
<g id="9" transform="translate(547.000000, 159.000000)">
<rect id="Rectangle" fill="#000000" x="7" y="6" width="40" height="40"></rect>
<g id="left" transform="translate(0.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="bottom" transform="translate(15.000000, 28.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="right" transform="translate(29.000000, 14.000000)" fill="#000000">
<rect id="carat" transform="translate(12.000000, 12.000000) rotate(-314.000000) translate(-12.000000, -12.000000) " x="4" y="4" width="16" height="16"></rect>
</g>
<g id="top" transform="translate(16.000000, 0.000000)" fill="#000000">
<rect id="carat" transform="translate(11.311985, 12.000000) rotate(-314.000000) translate(-11.311985, -12.000000) " x="3.31198537" y="4" width="16" height="16"></rect>
</g>
<path d="M24.5605469,30.7548828 L24.5605469,28.9775391 C25.0755234,29.3147803 25.6953089,29.4833984 26.4199219,29.4833984 C27.1764361,29.4833984 27.7609029,29.2270533 28.1733398,28.7143555 C28.5857768,28.2016576 28.7942708,27.4736375 28.7988281,26.5302734 L28.7578125,26.5166016 C28.3248676,27.1591829 27.6663456,27.4804688 26.7822266,27.4804688 C25.9801392,27.4804688 25.3159206,27.2001981 24.7895508,26.6396484 C24.263181,26.0790988 24,25.352218 24,24.4589844 C24,23.4153594 24.3212858,22.5779654 24.9638672,21.9467773 C25.6064485,21.3155893 26.4381459,21 27.4589844,21 C28.5071667,21 29.342282,21.3964804 29.9643555,22.1894531 C30.5864289,22.9824258 30.8974609,24.1171801 30.8974609,25.59375 C30.8974609,27.3437587 30.5226274,28.705236 29.7729492,29.6782227 C29.023271,30.6512093 27.9762437,31.1376953 26.6318359,31.1376953 C25.8343059,31.1376953 25.1438831,31.0100924 24.5605469,30.7548828 Z M27.3974609,22.6474609 C27.0237612,22.6474609 26.716147,22.7989894 26.4746094,23.1020508 C26.2330717,23.4051122 26.1123047,23.795896 26.1123047,24.2744141 C26.1123047,24.7711613 26.2319324,25.1619452 26.4711914,25.4467773 C26.7104504,25.7316095 27.0351542,25.8740234 27.4453125,25.8740234 C27.8190123,25.8740234 28.1243478,25.7384454 28.3613281,25.4672852 C28.5983085,25.1961249 28.7167969,24.8554708 28.7167969,24.4453125 C28.7167969,23.930336 28.5926119,23.5019548 28.3442383,23.1601562 C28.0958646,22.8183577 27.7802754,22.6474609 27.3974609,22.6474609 Z" fill="#FFFFFF" fill-rule="nonzero"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 177 KiB

After

Width:  |  Height:  |  Size: 362 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 177 KiB

After

Width:  |  Height:  |  Size: 368 KiB

View file

@ -80,9 +80,6 @@
<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>
<ItemGroup>
<EmbeddedResource Include="Resources.resx" />

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

@ -166,9 +166,6 @@
<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>
<ProjectReference Include="..\FancyZonesLib\FancyZonesLib.vcxproj">
<Project>{f9c68edf-ac74-4b77-9af1-005d9c9f6a99}</Project>
</ProjectReference>

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

@ -1,7 +1,5 @@
#include "pch.h"
#include "call_tracer.h"
#include <map>
#include "CallTracer.h"
#include <thread>
namespace

View file

@ -1,8 +1,6 @@
#pragma once
#include <string>
#include "logger.h"
#include "common/logger/logger.h"
#define _TRACER_ CallTracer callTracer(__FUNCTION__)

View file

@ -4,7 +4,6 @@
#include <common/display/dpi_aware.h>
#include <common/interop/shared_constants.h>
#include <common/logger/logger.h>
#include <common/logger/call_tracer.h>
#include <common/utils/EventWaiter.h>
#include <common/utils/resources.h>
#include <common/utils/winapi_error.h>
@ -26,6 +25,7 @@
#include "VirtualDesktop.h"
#include "MonitorWorkAreaHandler.h"
#include "util.h"
#include "CallTracer.h"
#include <FancyZonesLib/SecondaryMouseButtonsHook.h>
#include <winrt/Windows.UI.ViewManagement.h>
@ -148,19 +148,19 @@ public:
LRESULT WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
void OnDisplayChange(DisplayChangeType changeType) noexcept;
void AddWorkArea(HMONITOR monitor, const std::wstring& deviceId) noexcept;
void AddZoneWindow(HMONITOR monitor, const std::wstring& deviceId) noexcept;
protected:
static LRESULT CALLBACK s_WndProc(HWND, UINT, WPARAM, LPARAM) noexcept;
private:
void UpdateWorkAreas() noexcept;
void UpdateZoneWindows() noexcept;
void UpdateWindowsPositions(bool suppressMove = false) noexcept;
void CycleTabs(bool reverse) noexcept;
bool OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexcept;
bool OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept;
bool OnSnapHotkey(DWORD vkCode) noexcept;
bool ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept;
bool ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> zoneWindow) noexcept;
void RegisterVirtualDesktopUpdates() noexcept;
@ -168,7 +168,7 @@ private:
void OnSettingsChanged() noexcept;
std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> GetAppZoneHistoryInfo(HWND window, HMONITOR monitor, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept;
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> workArea, const ZoneIndexSet& zoneIndexSet) noexcept;
void MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> zoneWindow, const ZoneIndexSet& zoneIndexSet) noexcept;
bool MoveToAppLastZone(HWND window, HMONITOR active, HMONITOR primary) noexcept;
void OnEditorExitEvent() noexcept;
@ -324,18 +324,14 @@ std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet> FancyZones::GetAppZoneHistory
return std::pair<winrt::com_ptr<IWorkArea>, ZoneIndexSet>{ nullptr, {} };
}
void FancyZones::MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> workArea, const ZoneIndexSet& zoneIndexSet) noexcept
void FancyZones::MoveWindowIntoZone(HWND window, winrt::com_ptr<IWorkArea> zoneWindow, const ZoneIndexSet& zoneIndexSet) noexcept
{
_TRACER_;
auto& fancyZonesData = FancyZonesDataInstance();
if (!fancyZonesData.IsAnotherWindowOfApplicationInstanceZoned(window, workArea->UniqueId()))
if (!fancyZonesData.IsAnotherWindowOfApplicationInstanceZoned(window, zoneWindow->UniqueId()))
{
if (workArea)
{
Trace::FancyZones::SnapNewWindowIntoZone(workArea->ZoneSet());
}
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, workArea);
fancyZonesData.UpdateProcessIdToHandleMap(window, workArea->UniqueId());
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, zoneWindow);
fancyZonesData.UpdateProcessIdToHandleMap(window, zoneWindow->UniqueId());
}
}
@ -480,7 +476,7 @@ FancyZones::OnKeyDown(PKBDLLHOOKSTRUCT info) noexcept
digitPressed = info->vkCode - VK_NUMPAD0;
}
bool dragging = m_windowMoveHandler.InDragging();
bool dragging = m_windowMoveHandler.InMoveSize();
bool changeLayoutWhileNotDragging = !dragging && !shift && win && ctrl && alt && digitPressed != -1;
bool changeLayoutWhileDragging = dragging && digitPressed != -1;
@ -749,7 +745,7 @@ LRESULT FancyZones::WndProc(HWND window, UINT message, WPARAM wparam, LPARAM lpa
}
else if (message == WM_PRIV_LOCATIONCHANGE)
{
if (m_windowMoveHandler.InDragging())
if (m_windowMoveHandler.InMoveSize())
{
if (auto monitor = MonitorFromPoint(ptScreen, MONITOR_DEFAULTTONULL))
{
@ -820,7 +816,8 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
}
}
UpdateWorkAreas();
UpdateZoneWindows();
if ((changeType == DisplayChangeType::WorkArea) || (changeType == DisplayChangeType::DisplayChange))
{
@ -831,7 +828,7 @@ void FancyZones::OnDisplayChange(DisplayChangeType changeType) noexcept
}
}
void FancyZones::AddWorkArea(HMONITOR monitor, const std::wstring& deviceId) noexcept
void FancyZones::AddZoneWindow(HMONITOR monitor, const std::wstring& deviceId) noexcept
{
_TRACER_;
if (m_workAreaHandler.IsNewWorkArea(m_currentDesktopId, monitor))
@ -897,11 +894,11 @@ LRESULT CALLBACK FancyZones::s_WndProc(HWND window, UINT message, WPARAM wparam,
DefWindowProc(window, message, wparam, lparam);
}
void FancyZones::UpdateWorkAreas() noexcept
void FancyZones::UpdateZoneWindows() noexcept
{
if (m_settings->GetSettings()->spanZonesAcrossMonitors)
{
AddWorkArea(nullptr, {});
AddZoneWindow(nullptr, {});
}
else
{
@ -922,7 +919,7 @@ void FancyZones::UpdateWorkAreas() noexcept
FancyZones* fancyZones = params->fancyZones;
std::wstring deviceId = FancyZonesUtils::GetDisplayDeviceId(mi.szDevice, displayDeviceIdxMap);
fancyZones->AddWorkArea(monitor, deviceId);
fancyZones->AddZoneWindow(monitor, deviceId);
}
return TRUE;
};
@ -937,10 +934,10 @@ void FancyZones::UpdateWindowsPositions(bool suppressMove) noexcept
for (const auto [window, desktopId] : m_virtualDesktop.GetWindowsRelatedToDesktops())
{
auto zoneIndexSet = GetZoneIndexSet(window);
auto workArea = m_workAreaHandler.GetWorkArea(window, desktopId);
if (workArea)
auto zoneWindow = m_workAreaHandler.GetWorkArea(window, desktopId);
if (zoneWindow)
{
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, workArea, suppressMove);
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, zoneIndexSet, zoneWindow, suppressMove);
}
}
}
@ -969,10 +966,8 @@ bool FancyZones::OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexce
auto currMonitorInfo = std::find(std::begin(monitorInfo), std::end(monitorInfo), current);
do
{
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, *currMonitorInfo);
if (m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, false /* cycle through zones */, workArea))
if (m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, false /* cycle through zones */, m_workAreaHandler.GetWorkArea(m_currentDesktopId, *currMonitorInfo)))
{
Trace::FancyZones::KeyboardSnapWindowToZone(workArea->ZoneSet());
return true;
}
// We iterated through all zones in current monitor zone layout, move on to next one (or previous depending on direction).
@ -996,30 +991,20 @@ bool FancyZones::OnSnapHotkeyBasedOnZoneNumber(HWND window, DWORD vkCode) noexce
}
else
{
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, current);
// Single monitor environment, or combined multi-monitor environment.
if (m_settings->GetSettings()->restoreSize)
{
bool moved = m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, false /* cycle through zones */, workArea);
bool moved = m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, false /* cycle through zones */, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
if (!moved)
{
FancyZonesUtils::RestoreWindowOrigin(window);
FancyZonesUtils::RestoreWindowSize(window);
}
else
{
Trace::FancyZones::KeyboardSnapWindowToZone(workArea->ZoneSet());
}
return moved;
return true;
}
else
{
bool moved = m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, true /* cycle through zones */, workArea);
if (moved)
{
Trace::FancyZones::KeyboardSnapWindowToZone(workArea->ZoneSet());
}
return moved;
return m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, true /* cycle through zones */, m_workAreaHandler.GetWorkArea(m_currentDesktopId, current));
}
}
@ -1058,7 +1043,7 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
if (workArea)
{
auto zoneSet = workArea->ZoneSet();
auto zoneSet = workArea->ActiveZoneSet();
if (zoneSet)
{
const auto zones = zoneSet->GetZones();
@ -1091,9 +1076,8 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
if (chosenIdx < zoneRects.size())
{
// Moving to another monitor succeeded
const auto& [trueZoneIdx, workArea] = zoneRectsInfo[chosenIdx];
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, { trueZoneIdx }, workArea);
Trace::FancyZones::KeyboardSnapWindowToZone(workArea->ZoneSet());
const auto& [trueZoneIdx, zoneWindow] = zoneRectsInfo[chosenIdx];
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, { trueZoneIdx }, zoneWindow);
return true;
}
@ -1106,7 +1090,7 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, current);
if (workArea)
{
auto zoneSet = workArea->ZoneSet();
auto zoneSet = workArea->ActiveZoneSet();
if (zoneSet)
{
const auto zones = zoneSet->GetZones();
@ -1136,9 +1120,8 @@ bool FancyZones::OnSnapHotkeyBasedOnPosition(HWND window, DWORD vkCode) noexcept
if (chosenIdx < zoneRects.size())
{
// Moving to another monitor succeeded
const auto& [trueZoneIdx, workArea] = zoneRectsInfo[chosenIdx];
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, { trueZoneIdx }, workArea);
Trace::FancyZones::KeyboardSnapWindowToZone(workArea->ZoneSet());
const auto& [trueZoneIdx, zoneWindow] = zoneRectsInfo[chosenIdx];
m_windowMoveHandler.MoveWindowIntoZoneByIndexSet(window, { trueZoneIdx }, zoneWindow);
return true;
}
else
@ -1169,26 +1152,16 @@ bool FancyZones::OnSnapHotkey(DWORD vkCode) noexcept
return false;
}
bool FancyZones::ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept
bool FancyZones::ProcessDirectedSnapHotkey(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> zoneWindow) noexcept
{
// Check whether Alt is used in the shortcut key combination
if (GetAsyncKeyState(VK_MENU) & 0x8000)
{
bool result = m_windowMoveHandler.ExtendWindowByDirectionAndPosition(window, vkCode, workArea);
if (result)
{
Trace::FancyZones::KeyboardSnapWindowToZone(workArea->ZoneSet());
}
return result;
return m_windowMoveHandler.ExtendWindowByDirectionAndPosition(window, vkCode, zoneWindow);
}
else
{
bool result = m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle, workArea);
if (result)
{
Trace::FancyZones::KeyboardSnapWindowToZone(workArea->ZoneSet());
}
return result;
return m_windowMoveHandler.MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle, zoneWindow);
}
}
@ -1275,8 +1248,8 @@ bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
{
HMONITOR monitor = WorkAreaKeyFromWindow(window);
auto workArea = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
if (workArea && workArea->ZoneSet() && workArea->ZoneSet()->LayoutType() != FancyZonesDataTypes::ZoneSetLayoutType::Blank)
auto zoneWindow = m_workAreaHandler.GetWorkArea(m_currentDesktopId, monitor);
if (zoneWindow && zoneWindow->ActiveZoneSet() && zoneWindow->ActiveZoneSet()->LayoutType() != FancyZonesDataTypes::ZoneSetLayoutType::Blank)
{
if (vkCode == VK_UP || vkCode == VK_DOWN)
{
@ -1294,11 +1267,11 @@ bool FancyZones::ShouldProcessSnapHotkey(DWORD vkCode) noexcept
void FancyZones::ApplyQuickLayout(int key) noexcept
{
std::wstring uuid;
for (auto [layoutUuid, hotkey] : FancyZonesDataInstance().GetLayoutQuickKeys())
for (auto [zoneUuid, hotkey] : FancyZonesDataInstance().GetLayoutQuickKeys())
{
if (hotkey == key)
{
uuid = layoutUuid;
uuid = zoneUuid;
}
}
@ -1347,7 +1320,7 @@ std::vector<std::pair<HMONITOR, RECT>> FancyZones::GetRawMonitorData() noexcept
const auto& activeWorkAreaMap = m_workAreaHandler.GetWorkAreasByDesktopId(m_currentDesktopId);
for (const auto& [monitor, workArea] : activeWorkAreaMap)
{
if (workArea->ZoneSet() != nullptr)
if (workArea->ActiveZoneSet() != nullptr)
{
MONITORINFOEX mi;
mi.cbSize = sizeof(mi);

View file

@ -4,10 +4,10 @@
#include "JsonHelpers.h"
#include "ZoneSet.h"
#include "Settings.h"
#include "CallTracer.h"
#include "GuidUtils.h"
#include <common/Display/dpi_aware.h>
#include <common/logger/call_tracer.h>
#include <common/utils/json.h>
#include <FancyZonesLib/util.h>
#include <FancyZonesLib/FancyZonesWindowProperties.h>

View file

@ -178,7 +178,7 @@ namespace FancyZonesDataTypes
}
/*
Refer to FancyZonesUtils::GenerateUniqueId parts contain:
Refer to ZoneWindowUtils::GenerateUniqueId parts contain:
1. monitor id [string]
2. width of device [int]
3. height of device [int]
@ -258,7 +258,7 @@ namespace FancyZonesDataTypes
}
/*
Refer to FancyZonesUtils::GenerateUniqueId parts contain:
Refer to ZoneWindowUtils::GenerateUniqueId parts contain:
1. monitor id [string]
2. width of device [int]
3. height of device [int]

View file

@ -37,6 +37,7 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="CallTracer.h" />
<ClInclude Include="FancyZones.h" />
<ClInclude Include="FancyZonesDataTypes.h" />
<ClInclude Include="FancyZonesWinHookEventIDs.h" />
@ -61,9 +62,10 @@
<ClInclude Include="ZoneColors.h" />
<ClInclude Include="ZoneSet.h" />
<ClInclude Include="WorkArea.h" />
<ClInclude Include="ZonesOverlay.h" />
<ClInclude Include="ZoneWindowDrawing.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="CallTracer.cpp" />
<ClCompile Include="FancyZones.cpp" />
<ClCompile Include="FancyZonesDataTypes.cpp" />
<ClCompile Include="FancyZonesWinHookEventIDs.cpp" />
@ -84,7 +86,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,10 @@
<ClInclude Include="KeyState.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZonesOverlay.h">
<ClInclude Include="ZoneWindowDrawing.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CallTracer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MonitorUtils.h">
@ -140,12 +143,15 @@
<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">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CallTracer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="MonitorUtils.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View file

@ -134,9 +134,9 @@ void MonitorWorkAreaHandler::UpdateZoneColors(const ZoneColors& colors)
{
for (const auto& workArea : workAreaMap)
{
for (const auto& workAreaPtr : workArea.second)
for (const auto& zoneWindow : workArea.second)
{
workAreaPtr.second->SetZoneColors(colors);
zoneWindow.second->SetZoneColors(colors);
}
}
}
@ -145,9 +145,9 @@ void MonitorWorkAreaHandler::UpdateOverlappingAlgorithm(OverlappingZonesAlgorith
{
for (const auto& workArea : workAreaMap)
{
for (const auto& workAreaPtr : workArea.second)
for (const auto& zoneWindow : workArea.second)
{
workAreaPtr.second->SetOverlappingZonesAlgorithm(overlappingAlgorithm);
zoneWindow.second->SetOverlappingZonesAlgorithm(overlappingAlgorithm);
}
}
}

View file

@ -1,8 +1,7 @@
#include "pch.h"
#include <common/logger/call_tracer.h>
#include "on_thread_executor.h"
#include "CallTracer.h"
OnThreadExecutor::OnThreadExecutor() :
_shutdown_request{ false }, _worker_thread{ [this] { worker_thread(); } }

View file

@ -59,24 +59,24 @@ WindowMoveHandler::WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>&
{
}
void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept
void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& zoneWindowMap) noexcept
{
if (!FancyZonesUtils::IsCandidateForZoning(window, m_settings->GetSettings()->excludedAppsArray) || WindowMoveHandlerUtils::IsCursorTypeIndicatingSizeEvent())
{
return;
}
m_draggedWindowInfo.hasNoVisibleOwner = FancyZonesUtils::HasNoVisibleOwner(window);
m_draggedWindowInfo.isStandardWindow = FancyZonesUtils::IsStandardWindow(window);
m_inDragging = true;
m_moveSizeWindowInfo.hasNoVisibleOwner = FancyZonesUtils::HasNoVisibleOwner(window);
m_moveSizeWindowInfo.isStandardWindow = FancyZonesUtils::IsStandardWindow(window);
m_inMoveSize = true;
auto iter = workAreaMap.find(monitor);
if (iter == end(workAreaMap))
auto iter = zoneWindowMap.find(monitor);
if (iter == end(zoneWindowMap))
{
return;
}
m_draggedWindow = window;
m_windowMoveSize = window;
if (m_settings->GetSettings()->mouseSwitch)
{
@ -94,51 +94,51 @@ void WindowMoveHandler::MoveSizeStart(HWND window, HMONITOR monitor, POINT const
if (m_dragEnabled)
{
m_draggedWindowWorkArea = iter->second;
SetWindowTransparency(m_draggedWindow);
m_draggedWindowWorkArea->MoveSizeEnter(m_draggedWindow);
m_zoneWindowMoveSize = iter->second;
SetWindowTransparency(m_windowMoveSize);
m_zoneWindowMoveSize->MoveSizeEnter(m_windowMoveSize);
if (m_settings->GetSettings()->showZonesOnAllMonitors)
{
for (auto [keyMonitor, workArea] : workAreaMap)
for (auto [keyMonitor, zoneWindow] : zoneWindowMap)
{
// Skip calling ShowZonesOverlay for iter->second (m_draggedWindowWorkArea) since it
// Skip calling ShowZoneWindow for iter->second (m_zoneWindowMoveSize) since it
// was already called in MoveSizeEnter
const bool moveSizeEnterCalled = workArea == m_draggedWindowWorkArea;
if (workArea && !moveSizeEnterCalled)
const bool moveSizeEnterCalled = zoneWindow == m_zoneWindowMoveSize;
if (zoneWindow && !moveSizeEnterCalled)
{
workArea->ShowZonesOverlay();
zoneWindow->ShowZoneWindow();
}
}
}
}
else if (m_draggedWindowWorkArea)
else if (m_zoneWindowMoveSize)
{
ResetWindowTransparency();
m_draggedWindowWorkArea = nullptr;
for (auto [keyMonitor, workArea] : workAreaMap)
m_zoneWindowMoveSize = nullptr;
for (auto [keyMonitor, zoneWindow] : zoneWindowMap)
{
if (workArea)
if (zoneWindow)
{
workArea->HideZonesOverlay();
zoneWindow->HideZoneWindow();
}
}
}
auto workArea = workAreaMap.find(monitor);
if (workArea != workAreaMap.end())
auto zoneWindow = zoneWindowMap.find(monitor);
if (zoneWindow != zoneWindowMap.end())
{
const auto workAreaPtr = workArea->second;
const auto zoneSet = workAreaPtr->ZoneSet();
if (zoneSet)
const auto zoneWindowPtr = zoneWindow->second;
const auto activeZoneSet = zoneWindowPtr->ActiveZoneSet();
if (activeZoneSet)
{
zoneSet->DismissWindow(window);
activeZoneSet->DismissWindow(window);
}
}
}
void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept
void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& zoneWindowMap) noexcept
{
if (!m_inDragging)
if (!m_inMoveSize)
{
return;
}
@ -146,44 +146,44 @@ void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen,
// This updates m_dragEnabled depending on if the shift key is being held down.
UpdateDragState();
if (m_draggedWindowWorkArea)
if (m_zoneWindowMoveSize)
{
// Update the WorkArea already handling move/size
if (!m_dragEnabled)
{
// Drag got disabled, tell it to cancel and hide all windows
m_draggedWindowWorkArea = nullptr;
m_zoneWindowMoveSize = nullptr;
ResetWindowTransparency();
for (auto [keyMonitor, workArea] : workAreaMap)
for (auto [keyMonitor, zoneWindow] : zoneWindowMap)
{
if (workArea)
if (zoneWindow)
{
workArea->HideZonesOverlay();
zoneWindow->HideZoneWindow();
}
}
}
else
{
auto iter = workAreaMap.find(monitor);
if (iter != workAreaMap.end())
auto iter = zoneWindowMap.find(monitor);
if (iter != zoneWindowMap.end())
{
if (iter->second != m_draggedWindowWorkArea)
if (iter->second != m_zoneWindowMoveSize)
{
// The drag has moved to a different monitor.
m_draggedWindowWorkArea->ClearSelectedZones();
m_zoneWindowMoveSize->ClearSelectedZones();
if (!m_settings->GetSettings()->showZonesOnAllMonitors)
{
m_draggedWindowWorkArea->HideZonesOverlay();
m_zoneWindowMoveSize->HideZoneWindow();
}
m_draggedWindowWorkArea = iter->second;
m_draggedWindowWorkArea->MoveSizeEnter(m_draggedWindow);
m_zoneWindowMoveSize = iter->second;
m_zoneWindowMoveSize->MoveSizeEnter(m_windowMoveSize);
}
for (auto [keyMonitor, workArea] : workAreaMap)
for (auto [keyMonitor, zoneWindow] : zoneWindowMap)
{
workArea->MoveSizeUpdate(ptScreen, m_dragEnabled, m_ctrlKeyState.state());
zoneWindow->MoveSizeUpdate(ptScreen, m_dragEnabled, m_ctrlKeyState.state());
}
}
}
@ -191,21 +191,21 @@ void WindowMoveHandler::MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen,
else if (m_dragEnabled)
{
// We'll get here if the user presses/releases shift while dragging.
// Restart the drag on the WorkArea that m_draggedWindow is on
MoveSizeStart(m_draggedWindow, monitor, ptScreen, workAreaMap);
// Restart the drag on the WorkArea that m_windowMoveSize is on
MoveSizeStart(m_windowMoveSize, monitor, ptScreen, zoneWindowMap);
// m_dragEnabled could get set to false if we're moving an elevated window.
// In that case do not proceed.
if (m_dragEnabled)
{
MoveSizeUpdate(monitor, ptScreen, workAreaMap);
MoveSizeUpdate(monitor, ptScreen, zoneWindowMap);
}
}
}
void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept
void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& zoneWindowMap) noexcept
{
if (window != m_draggedWindow)
if (window != m_windowMoveSize)
{
return;
}
@ -214,16 +214,16 @@ void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const st
m_shiftKeyState.disable();
m_ctrlKeyState.disable();
if (m_draggedWindowWorkArea)
if (m_zoneWindowMoveSize)
{
auto workArea = std::move(m_draggedWindowWorkArea);
auto zoneWindow = std::move(m_zoneWindowMoveSize);
ResetWindowTransparency();
bool hasNoVisibleOwner = FancyZonesUtils::HasNoVisibleOwner(window);
bool isStandardWindow = FancyZonesUtils::IsStandardWindow(window);
if ((isStandardWindow == false && hasNoVisibleOwner == true &&
m_draggedWindowInfo.isStandardWindow == true && m_draggedWindowInfo.hasNoVisibleOwner == true) ||
m_moveSizeWindowInfo.isStandardWindow == true && m_moveSizeWindowInfo.hasNoVisibleOwner == true) ||
FancyZonesUtils::IsWindowMaximized(window))
{
// Abort the zoning, this is a Chromium based tab that is merged back with an existing window
@ -231,7 +231,7 @@ void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const st
}
else
{
workArea->MoveSizeEnd(m_draggedWindow, ptScreen);
zoneWindow->MoveSizeEnd(m_windowMoveSize, ptScreen);
}
}
else
@ -251,17 +251,17 @@ void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const st
auto monitor = MonitorFromWindow(window, MONITOR_DEFAULTTONULL);
if (monitor)
{
auto workArea = workAreaMap.find(monitor);
if (workArea != workAreaMap.end())
auto zoneWindow = zoneWindowMap.find(monitor);
if (zoneWindow != zoneWindowMap.end())
{
const auto workAreaPtr = workArea->second;
const auto zoneSet = workAreaPtr->ZoneSet();
if (zoneSet)
const auto zoneWindowPtr = zoneWindow->second;
const auto activeZoneSet = zoneWindowPtr->ActiveZoneSet();
if (activeZoneSet)
{
wil::unique_cotaskmem_string guidString;
if (SUCCEEDED_LOG(StringFromCLSID(zoneSet->Id(), &guidString)))
if (SUCCEEDED_LOG(StringFromCLSID(activeZoneSet->Id(), &guidString)))
{
FancyZonesDataInstance().RemoveAppLastZone(window, workAreaPtr->UniqueId(), guidString.get());
FancyZonesDataInstance().RemoveAppLastZone(window, zoneWindowPtr->UniqueId(), guidString.get());
}
}
}
@ -269,42 +269,42 @@ void WindowMoveHandler::MoveSizeEnd(HWND window, POINT const& ptScreen, const st
::RemoveProp(window, ZonedWindowProperties::PropertyMultipleZoneID);
}
m_inDragging = false;
m_inMoveSize = false;
m_dragEnabled = false;
m_mouseState = false;
m_draggedWindow = nullptr;
m_windowMoveSize = nullptr;
// Also, hide all windows (regardless of settings)
for (auto [keyMonitor, workArea] : workAreaMap)
for (auto [keyMonitor, zoneWindow] : zoneWindowMap)
{
if (workArea)
if (zoneWindow)
{
workArea->HideZonesOverlay();
zoneWindow->HideZoneWindow();
}
}
}
void WindowMoveHandler::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> workArea, bool suppressMove) noexcept
void WindowMoveHandler::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> zoneWindow, bool suppressMove) noexcept
{
if (window != m_draggedWindow)
if (window != m_windowMoveSize)
{
workArea->MoveWindowIntoZoneByIndexSet(window, indexSet, suppressMove);
zoneWindow->MoveWindowIntoZoneByIndexSet(window, indexSet, suppressMove);
}
}
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> zoneWindow) noexcept
{
return workArea && workArea->MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, cycle);
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirectionAndIndex(window, vkCode, cycle);
}
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept
bool WindowMoveHandler::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> zoneWindow) noexcept
{
return workArea && workArea->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle);
return zoneWindow && zoneWindow->MoveWindowIntoZoneByDirectionAndPosition(window, vkCode, cycle);
}
bool WindowMoveHandler::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IWorkArea> workArea) noexcept
bool WindowMoveHandler::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IWorkArea> zoneWindow) noexcept
{
return workArea && workArea->ExtendWindowByDirectionAndPosition(window, vkCode);
return zoneWindow && zoneWindow->ExtendWindowByDirectionAndPosition(window, vkCode);
}
void WindowMoveHandler::WarnIfElevationIsRequired(HWND window) noexcept

View file

@ -14,14 +14,14 @@ class WindowMoveHandler
public:
WindowMoveHandler(const winrt::com_ptr<IFancyZonesSettings>& settings, const std::function<void()>& keyUpdateCallback);
void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept;
void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept;
void MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& workAreaMap) noexcept;
void MoveSizeStart(HWND window, HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& zoneWindowMap) noexcept;
void MoveSizeUpdate(HMONITOR monitor, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& zoneWindowMap) noexcept;
void MoveSizeEnd(HWND window, POINT const& ptScreen, const std::unordered_map<HMONITOR, winrt::com_ptr<IWorkArea>>& zoneWindowMap) noexcept;
void MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> workArea, bool suppressMove = false) noexcept;
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept;
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> workArea) noexcept;
bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IWorkArea> workArea) noexcept;
void MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, winrt::com_ptr<IWorkArea> zoneWindow, bool suppressMove = false) noexcept;
bool MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> zoneWindow) noexcept;
bool MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle, winrt::com_ptr<IWorkArea> zoneWindow) noexcept;
bool ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode, winrt::com_ptr<IWorkArea> zoneWindow) noexcept;
inline void OnMouseDown() noexcept
{
@ -34,9 +34,9 @@ public:
return m_dragEnabled;
}
inline bool InDragging() const noexcept
inline bool InMoveSize() const noexcept
{
return m_inDragging;
return m_inMoveSize;
}
private:
@ -66,10 +66,10 @@ private:
winrt::com_ptr<IFancyZonesSettings> m_settings{};
bool m_inDragging{}; // Whether or not a move/size operation is currently active
HWND m_draggedWindow{}; // The window that is being moved/sized
MoveSizeWindowInfo m_draggedWindowInfo; // MoveSizeWindowInfo of the window at the moment when dragging started
winrt::com_ptr<IWorkArea> m_draggedWindowWorkArea; // "Active" WorkArea, where the move/size is happening. Will update as drag moves between monitors.
HWND m_windowMoveSize{}; // The window that is being moved/sized
bool m_inMoveSize{}; // Whether or not a move/size operation is currently active
MoveSizeWindowInfo m_moveSizeWindowInfo; // MoveSizeWindowInfo of the window at the moment when dragging started
winrt::com_ptr<IWorkArea> m_zoneWindowMoveSize; // "Active" WorkArea, where the move/size is happening. Will update as drag moves between monitors.
bool m_dragEnabled{}; // True if we should be showing zone hints while dragging
WindowTransparencyProperties m_windowTransparencyProperties;

View file

@ -1,16 +1,16 @@
#include "pch.h"
#include "WorkArea.h"
#include <common/logger/call_tracer.h>
#include <common/logger/logger.h>
#include "FancyZonesData.h"
#include "FancyZonesDataTypes.h"
#include "ZonesOverlay.h"
#include "ZoneWindowDrawing.h"
#include "trace.h"
#include "util.h"
#include "on_thread_executor.h"
#include "Settings.h"
#include "CallTracer.h"
#include <ShellScalingApi.h>
#include <mutex>
@ -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);
@ -129,13 +129,13 @@ public:
IFACEMETHODIMP_(void)
SaveWindowProcessToZoneIndex(HWND window) noexcept;
IFACEMETHODIMP_(IZoneSet*)
ZoneSet() const noexcept { return m_zoneSet.get(); }
ActiveZoneSet() const noexcept { return m_activeZoneSet.get(); }
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)
@ -164,12 +164,13 @@ private:
FancyZonesDataTypes::DeviceIdData m_uniqueId;
HWND m_window{}; // Hidden tool window used to represent current monitor desktop work area.
HWND m_windowMoveSize{};
winrt::com_ptr<IZoneSet> m_zoneSet;
winrt::com_ptr<IZoneSet> m_activeZoneSet;
std::vector<winrt::com_ptr<IZoneSet>> m_zoneSets;
ZoneIndexSet m_initialHighlightZone;
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 +188,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 +216,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,8 +233,7 @@ IFACEMETHODIMP WorkArea::MoveSizeEnter(HWND window) noexcept
m_windowMoveSize = window;
m_highlightZone = {};
m_initialHighlightZone = {};
ShowZonesOverlay();
Trace::WorkArea::MoveOrResizeStarted(m_zoneSet);
ShowZoneWindow();
return S_OK;
}
@ -256,7 +256,7 @@ IFACEMETHODIMP WorkArea::MoveSizeUpdate(POINT const& ptScreen, bool dragEnabled,
}
else
{
highlightZone = m_zoneSet->GetCombinedZoneRange(m_initialHighlightZone, highlightZone);
highlightZone = m_activeZoneSet->GetCombinedZoneRange(m_initialHighlightZone, highlightZone);
}
}
else
@ -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_activeZoneSet->GetZones(), m_highlightZone, m_zoneColors);
}
return S_OK;
@ -288,20 +288,20 @@ IFACEMETHODIMP WorkArea::MoveSizeEnd(HWND window, POINT const& ptScreen) noexcep
return E_INVALIDARG;
}
if (m_zoneSet)
if (m_activeZoneSet)
{
POINT ptClient = ptScreen;
MapWindowPoints(nullptr, m_window, &ptClient, 1);
m_zoneSet->MoveWindowIntoZoneByIndexSet(window, m_window, m_highlightZone);
m_activeZoneSet->MoveWindowIntoZoneByIndexSet(window, m_window, m_highlightZone);
if (FancyZonesUtils::HasNoVisibleOwner(window))
{
SaveWindowProcessToZoneIndex(window);
}
}
Trace::WorkArea::MoveOrResizeEnd(m_zoneSet);
Trace::WorkArea::MoveSizeEnd(m_activeZoneSet);
HideZonesOverlay();
HideZoneWindow();
m_windowMoveSize = nullptr;
return S_OK;
}
@ -315,18 +315,18 @@ WorkArea::MoveWindowIntoZoneByIndex(HWND window, ZoneIndex index) noexcept
IFACEMETHODIMP_(void)
WorkArea::MoveWindowIntoZoneByIndexSet(HWND window, const ZoneIndexSet& indexSet, bool suppressMove) noexcept
{
if (m_zoneSet)
if (m_activeZoneSet)
{
m_zoneSet->MoveWindowIntoZoneByIndexSet(window, m_window, indexSet, suppressMove);
m_activeZoneSet->MoveWindowIntoZoneByIndexSet(window, m_window, indexSet, suppressMove);
}
}
IFACEMETHODIMP_(bool)
WorkArea::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool cycle) noexcept
{
if (m_zoneSet)
if (m_activeZoneSet)
{
if (m_zoneSet->MoveWindowIntoZoneByDirectionAndIndex(window, m_window, vkCode, cycle))
if (m_activeZoneSet->MoveWindowIntoZoneByDirectionAndIndex(window, m_window, vkCode, cycle))
{
if (FancyZonesUtils::HasNoVisibleOwner(window))
{
@ -341,9 +341,9 @@ WorkArea::MoveWindowIntoZoneByDirectionAndIndex(HWND window, DWORD vkCode, bool
IFACEMETHODIMP_(bool)
WorkArea::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bool cycle) noexcept
{
if (m_zoneSet)
if (m_activeZoneSet)
{
if (m_zoneSet->MoveWindowIntoZoneByDirectionAndPosition(window, m_window, vkCode, cycle))
if (m_activeZoneSet->MoveWindowIntoZoneByDirectionAndPosition(window, m_window, vkCode, cycle))
{
SaveWindowProcessToZoneIndex(window);
return true;
@ -355,9 +355,9 @@ WorkArea::MoveWindowIntoZoneByDirectionAndPosition(HWND window, DWORD vkCode, bo
IFACEMETHODIMP_(bool)
WorkArea::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept
{
if (m_zoneSet)
if (m_activeZoneSet)
{
if (m_zoneSet->ExtendWindowByDirectionAndPosition(window, m_window, vkCode))
if (m_activeZoneSet->ExtendWindowByDirectionAndPosition(window, m_window, vkCode))
{
SaveWindowProcessToZoneIndex(window);
return true;
@ -369,13 +369,13 @@ WorkArea::ExtendWindowByDirectionAndPosition(HWND window, DWORD vkCode) noexcept
IFACEMETHODIMP_(void)
WorkArea::SaveWindowProcessToZoneIndex(HWND window) noexcept
{
if (m_zoneSet)
if (m_activeZoneSet)
{
auto zoneIndexSet = m_zoneSet->GetZoneIndexSetFromWindow(window);
auto zoneIndexSet = m_activeZoneSet->GetZoneIndexSetFromWindow(window);
if (zoneIndexSet.size())
{
OLECHAR* guidString;
if (StringFromCLSID(m_zoneSet->Id(), &guidString) == S_OK)
if (StringFromCLSID(m_activeZoneSet->Id(), &guidString) == S_OK)
{
FancyZonesDataInstance().SetAppLastZones(window, m_uniqueId, guidString, zoneIndexSet);
}
@ -388,10 +388,10 @@ WorkArea::SaveWindowProcessToZoneIndex(HWND window) noexcept
IFACEMETHODIMP_(ZoneIndexSet)
WorkArea::GetWindowZoneIndexes(HWND window) const noexcept
{
if (m_zoneSet)
if (m_activeZoneSet)
{
wil::unique_cotaskmem_string zoneSetId;
if (SUCCEEDED(StringFromCLSID(m_zoneSet->Id(), &zoneSetId)))
if (SUCCEEDED(StringFromCLSID(m_activeZoneSet->Id(), &zoneSetId)))
{
return FancyZonesDataInstance().GetAppLastZoneIndexSet(window, m_uniqueId, zoneSetId.get());
}
@ -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_activeZoneSet->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,16 +429,16 @@ WorkArea::UpdateActiveZoneSet() noexcept
if (m_window)
{
m_highlightZone.clear();
m_zonesOverlay->DrawActiveZoneSet(m_zoneSet->GetZones(), m_highlightZone, m_zoneColors);
m_zoneWindowDrawing->DrawActiveZoneSet(m_activeZoneSet->GetZones(), m_highlightZone, m_zoneColors);
}
}
IFACEMETHODIMP_(void)
WorkArea::CycleTabs(HWND window, bool reverse) noexcept
{
if (m_zoneSet)
if (m_activeZoneSet)
{
m_zoneSet->CycleTabs(window, reverse);
m_activeZoneSet->CycleTabs(window, reverse);
}
}
@ -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_activeZoneSet->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_activeZoneSet->GetZones(), {}, m_zoneColors);
m_zoneWindowDrawing->Flash();
}
}
@ -554,16 +554,16 @@ void WorkArea::CalculateZoneSet(OverlappingZonesAlgorithm overlappingAlgorithm)
void WorkArea::UpdateActiveZoneSet(_In_opt_ IZoneSet* zoneSet) noexcept
{
m_zoneSet.copy_from(zoneSet);
m_activeZoneSet.copy_from(zoneSet);
if (m_zoneSet)
if (m_activeZoneSet)
{
wil::unique_cotaskmem_string zoneSetId;
if (SUCCEEDED_LOG(StringFromCLSID(m_zoneSet->Id(), &zoneSetId)))
if (SUCCEEDED_LOG(StringFromCLSID(m_activeZoneSet->Id(), &zoneSetId)))
{
FancyZonesDataTypes::ZoneSetData data{
.uuid = zoneSetId.get(),
.type = m_zoneSet->LayoutType()
.type = m_activeZoneSet->LayoutType()
};
FancyZonesDataInstance().SetActiveZoneSet(m_uniqueId, data);
}
@ -594,9 +594,9 @@ LRESULT WorkArea::WndProc(UINT message, WPARAM wparam, LPARAM lparam) noexcept
ZoneIndexSet WorkArea::ZonesFromPoint(POINT pt) noexcept
{
if (m_zoneSet)
if (m_activeZoneSet)
{
return m_zoneSet->ZonesFromPoint(pt);
return m_activeZoneSet->ZonesFromPoint(pt);
}
return {};
}

View file

@ -103,19 +103,13 @@ interface __declspec(uuid("{7F017528-8110-4FB3-BE41-F472969C2560}")) IWorkArea :
/**
* @returns Active zone layout for this work area.
*/
IFACEMETHOD_(IZoneSet*, ZoneSet)() const = 0;
IFACEMETHOD_(IZoneSet*, ActiveZoneSet)() const = 0;
/*
* @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

@ -35,12 +35,46 @@ public:
IFACEMETHODIMP_(RECT) GetZoneRect() const noexcept { return m_zoneRect; }
IFACEMETHODIMP_(long) GetZoneArea() const noexcept { return max(m_zoneRect.bottom - m_zoneRect.top, 0) * max(m_zoneRect.right - m_zoneRect.left, 0); }
IFACEMETHODIMP_(ZoneIndex) Id() const noexcept { return m_id; }
IFACEMETHODIMP_(RECT) ComputeActualZoneRect(HWND window, HWND zoneWindow) const noexcept;
private:
RECT m_zoneRect{};
const ZoneIndex m_id{};
std::map<HWND, RECT> m_windows{};
};
RECT Zone::ComputeActualZoneRect(HWND window, HWND zoneWindow) const noexcept
{
// Take care of 1px border
RECT newWindowRect = m_zoneRect;
RECT windowRect{};
::GetWindowRect(window, &windowRect);
RECT frameRect{};
if (SUCCEEDED(DwmGetWindowAttribute(window, DWMWA_EXTENDED_FRAME_BOUNDS, &frameRect, sizeof(frameRect))))
{
LONG leftMargin = frameRect.left - windowRect.left;
LONG rightMargin = frameRect.right - windowRect.right;
LONG bottomMargin = frameRect.bottom - windowRect.bottom;
newWindowRect.left -= leftMargin;
newWindowRect.right -= rightMargin;
newWindowRect.bottom -= bottomMargin;
}
// Map to screen coords
MapWindowRect(zoneWindow, nullptr, &newWindowRect);
if ((::GetWindowLong(window, GWL_STYLE) & WS_SIZEBOX) == 0)
{
newWindowRect.right = newWindowRect.left + (windowRect.right - windowRect.left);
newWindowRect.bottom = newWindowRect.top + (windowRect.bottom - windowRect.top);
}
return newWindowRect;
}
winrt::com_ptr<IZone> MakeZone(const RECT& zoneRect, const ZoneIndex zoneId) noexcept
{
if (ValidateZoneRect(zoneRect) && zoneId >= 0)

View file

@ -26,6 +26,16 @@ interface __declspec(uuid("{8228E934-B6EF-402A-9892-15A1441BF8B0}")) IZone : pub
* @returns Zone identifier.
*/
IFACEMETHOD_(ZoneIndex, Id)() const = 0;
/**
* Compute the coordinates of the rectangle to which a window should be resized.
*
* @param window Handle of window which should be assigned to zone.
* @param zoneWindow The m_window of a WorkArea, it's a hidden window representing the
* current monitor desktop work area.
* @returns a RECT structure, describing global coordinates to which a window should be resized
*/
IFACEMETHOD_(RECT, ComputeActualZoneRect)(HWND window, HWND zoneWindow) const = 0;
};
winrt::com_ptr<IZone> MakeZone(const RECT& zoneRect, const ZoneIndex zoneId) noexcept;

View file

@ -323,7 +323,7 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const Zo
if (m_zones.contains(id))
{
const auto& zone = m_zones.at(id);
const RECT newSize = zone->GetZoneRect();
const RECT newSize = zone->ComputeActualZoneRect(window, workAreaWindow);
if (!sizeEmpty)
{
size.left = min(size.left, newSize.left);
@ -351,9 +351,7 @@ ZoneSet::MoveWindowIntoZoneByIndexSet(HWND window, HWND workAreaWindow, const Zo
if (!suppressMove)
{
SaveWindowSizeAndOrigin(window);
auto rect = AdjustRectForSizeWindowToRect(window, size, workAreaWindow);
SizeWindowToRect(window, rect);
SizeWindowToRect(window, size);
}
StampWindow(window, bitmask);
@ -434,14 +432,14 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND workAreaWind
}
}
RECT windowRect, workAreaRect;
if (GetWindowRect(window, &windowRect) && GetWindowRect(workAreaWindow, &workAreaRect))
RECT windowRect, windowZoneRect;
if (GetWindowRect(window, &windowRect) && GetWindowRect(workAreaWindow, &windowZoneRect))
{
// Move to coordinates relative to windowZone
windowRect.top -= workAreaRect.top;
windowRect.bottom -= workAreaRect.top;
windowRect.left -= workAreaRect.left;
windowRect.right -= workAreaRect.left;
windowRect.top -= windowZoneRect.top;
windowRect.bottom -= windowZoneRect.top;
windowRect.left -= windowZoneRect.left;
windowRect.right -= windowZoneRect.left;
auto result = FancyZonesUtils::ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
if (result < zoneRects.size())
@ -455,7 +453,7 @@ ZoneSet::MoveWindowIntoZoneByDirectionAndPosition(HWND window, HWND workAreaWind
// Consider all zones as available
zoneRects.resize(m_zones.size());
std::transform(m_zones.begin(), m_zones.end(), zoneRects.begin(), [](auto zone) { return zone.second->GetZoneRect(); });
windowRect = FancyZonesUtils::PrepareRectForCycling(windowRect, workAreaRect, vkCode);
windowRect = FancyZonesUtils::PrepareRectForCycling(windowRect, windowZoneRect, vkCode);
result = FancyZonesUtils::ChooseNextZoneByPosition(vkCode, windowRect, zoneRects);
if (result < zoneRects.size())
@ -594,17 +592,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,12 +1,13 @@
#include "pch.h"
#include "ZonesOverlay.h"
#include "ZoneWindowDrawing.h"
#include "CallTracer.h"
#include <algorithm>
#include <map>
#include <string>
#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

@ -14,11 +14,8 @@
#define EventEditorLaunchKey "FancyZones_EditorLaunch"
#define EventSettingsKey "FancyZones_Settings"
#define EventDesktopChangedKey "FancyZones_VirtualDesktopChanged"
#define EventWorkAreaKeyUpKey "FancyZones_ZoneWindowKeyUp"
#define EventSnapNewWindowIntoZone "FancyZones_SnapNewWindowIntoZone"
#define EventKeyboardSnapWindowToZone "FancyZones_KeyboardSnapWindowToZone"
#define EventMoveOrResizeStartedKey "FancyZones_MoveOrResizeStarted"
#define EventMoveOrResizeEndedKey "FancyZones_MoveOrResizeEnded"
#define EventZoneWindowKeyUpKey "FancyZones_ZoneWindowKeyUp"
#define EventMoveSizeEndKey "FancyZones_MoveSizeEnd"
#define EventCycleActiveZoneSetKey "FancyZones_CycleActiveZoneSet"
#define EventQuickLayoutSwitchKey "FancyZones_QuickLayoutSwitch"
@ -81,8 +78,7 @@ struct ZoneSetInfo
size_t NumberOfWindows = 0;
};
ZoneSetInfo GetZoneSetInfo(_In_opt_ IZoneSet* set) noexcept
ZoneSetInfo GetZoneSetInfo(_In_opt_ winrt::com_ptr<IZoneSet> set) noexcept
{
ZoneSetInfo info;
if (set)
@ -101,11 +97,6 @@ ZoneSetInfo GetZoneSetInfo(_In_opt_ IZoneSet* set) noexcept
return info;
}
ZoneSetInfo GetZoneSetInfo(_In_opt_ winrt::com_ptr<IZoneSet> set) noexcept
{
return GetZoneSetInfo(set.get());
}
void Trace::RegisterProvider() noexcept
{
TraceLoggingRegister(g_hProvider);
@ -256,32 +247,6 @@ void Trace::FancyZones::QuickLayoutSwitched(bool shortcutUsed) noexcept
TraceLoggingBoolean(shortcutUsed, QuickLayoutSwitchedWithShortcutUsed));
}
void Trace::FancyZones::SnapNewWindowIntoZone(IZoneSet* activeSet) noexcept
{
auto const zoneInfo = GetZoneSetInfo(activeSet);
TraceLoggingWrite(
g_hProvider,
EventSnapNewWindowIntoZone,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(reinterpret_cast<void*>(activeSet), ActiveSetKey),
TraceLoggingValue(zoneInfo.NumberOfZones, NumberOfZonesKey),
TraceLoggingValue(zoneInfo.NumberOfWindows, NumberOfWindowsKey));
}
void Trace::FancyZones::KeyboardSnapWindowToZone(IZoneSet* activeSet) noexcept
{
auto const zoneInfo = GetZoneSetInfo(activeSet);
TraceLoggingWrite(
g_hProvider,
EventKeyboardSnapWindowToZone,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(reinterpret_cast<void*>(activeSet), ActiveSetKey),
TraceLoggingValue(zoneInfo.NumberOfZones, NumberOfZonesKey),
TraceLoggingValue(zoneInfo.NumberOfWindows, NumberOfWindowsKey));
}
static std::wstring HotKeyToString(const PowerToysSettings::HotkeyObject& hotkey)
{
return L"alt:" + std::to_wstring(hotkey.alt_pressed())
@ -345,31 +310,18 @@ void Trace::WorkArea::KeyUp(WPARAM wParam) noexcept
{
TraceLoggingWrite(
g_hProvider,
EventWorkAreaKeyUpKey,
EventZoneWindowKeyUpKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(wParam, KeyboardValueKey));
}
void Trace::WorkArea::MoveOrResizeStarted(_In_opt_ winrt::com_ptr<IZoneSet> activeSet) noexcept
void Trace::WorkArea::MoveSizeEnd(_In_opt_ winrt::com_ptr<IZoneSet> activeSet) noexcept
{
auto const zoneInfo = GetZoneSetInfo(activeSet);
TraceLoggingWrite(
g_hProvider,
EventMoveOrResizeStartedKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(reinterpret_cast<void*>(activeSet.get()), ActiveSetKey),
TraceLoggingValue(zoneInfo.NumberOfZones, NumberOfZonesKey),
TraceLoggingValue(zoneInfo.NumberOfWindows, NumberOfWindowsKey));
}
void Trace::WorkArea::MoveOrResizeEnd(_In_opt_ winrt::com_ptr<IZoneSet> activeSet) noexcept
{
auto const zoneInfo = GetZoneSetInfo(activeSet);
TraceLoggingWrite(
g_hProvider,
EventMoveOrResizeEndedKey,
EventMoveSizeEndKey,
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE),
TraceLoggingValue(reinterpret_cast<void*>(activeSet.get()), ActiveSetKey),

View file

@ -18,8 +18,6 @@ public:
static void EditorLaunched(int value) noexcept;
static void Error(const DWORD errorCode, std::wstring errorMessage, std::wstring methodName) noexcept;
static void QuickLayoutSwitched(bool shortcutUsed) noexcept;
static void SnapNewWindowIntoZone(IZoneSet* activeSet) noexcept;
static void KeyboardSnapWindowToZone(IZoneSet* activeSet) noexcept;
};
static void SettingsTelemetry(const Settings& settings) noexcept;
@ -35,8 +33,7 @@ public:
};
static void KeyUp(WPARAM wparam) noexcept;
static void MoveOrResizeStarted(_In_opt_ winrt::com_ptr<IZoneSet> activeSet) noexcept;
static void MoveOrResizeEnd(_In_opt_ winrt::com_ptr<IZoneSet> activeSet) noexcept;
static void MoveSizeEnd(_In_opt_ winrt::com_ptr<IZoneSet> activeSet) noexcept;
static void CycleActiveZoneSet(_In_opt_ winrt::com_ptr<IZoneSet> activeSet, InputMode mode) noexcept;
};
};

View file

@ -300,38 +300,6 @@ namespace FancyZonesUtils
}
}
RECT AdjustRectForSizeWindowToRect(HWND window, RECT rect, HWND windowOfRect) noexcept
{
RECT newWindowRect = rect;
RECT windowRect{};
::GetWindowRect(window, &windowRect);
// Take care of borders
RECT frameRect{};
if (SUCCEEDED(DwmGetWindowAttribute(window, DWMWA_EXTENDED_FRAME_BOUNDS, &frameRect, sizeof(frameRect))))
{
LONG leftMargin = frameRect.left - windowRect.left;
LONG rightMargin = frameRect.right - windowRect.right;
LONG bottomMargin = frameRect.bottom - windowRect.bottom;
newWindowRect.left -= leftMargin;
newWindowRect.right -= rightMargin;
newWindowRect.bottom -= bottomMargin;
}
// Take care of windows that cannot be resized
if ((::GetWindowLong(window, GWL_STYLE) & WS_SIZEBOX) == 0)
{
newWindowRect.right = newWindowRect.left + (windowRect.right - windowRect.left);
newWindowRect.bottom = newWindowRect.top + (windowRect.bottom - windowRect.top);
}
// Convert to screen coordinates
MapWindowRect(windowOfRect, nullptr, &newWindowRect);
return newWindowRect;
}
void SizeWindowToRect(HWND window, RECT rect) noexcept
{
WINDOWPLACEMENT placement{};
@ -369,22 +337,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);
@ -708,22 +660,22 @@ namespace FancyZonesUtils
return closestIdx;
}
RECT PrepareRectForCycling(RECT windowRect, RECT workAreaRect, DWORD vkCode) noexcept
RECT PrepareRectForCycling(RECT windowRect, RECT zoneWindowRect, DWORD vkCode) noexcept
{
LONG deltaX = 0, deltaY = 0;
switch (vkCode)
{
case VK_UP:
deltaY = workAreaRect.bottom - workAreaRect.top;
deltaY = zoneWindowRect.bottom - zoneWindowRect.top;
break;
case VK_DOWN:
deltaY = workAreaRect.top - workAreaRect.bottom;
deltaY = zoneWindowRect.top - zoneWindowRect.bottom;
break;
case VK_LEFT:
deltaX = workAreaRect.right - workAreaRect.left;
deltaX = zoneWindowRect.right - zoneWindowRect.left;
break;
case VK_RIGHT:
deltaX = workAreaRect.left - workAreaRect.right;
deltaX = zoneWindowRect.left - zoneWindowRect.right;
}
windowRect.left += deltaX;

View file

@ -189,14 +189,9 @@ namespace FancyZonesUtils
UINT GetDpiForMonitor(HMONITOR monitor) noexcept;
void OrderMonitors(std::vector<std::pair<HMONITOR, RECT>>& monitorInfo);
// Parameter rect is in windowOfRect coordinates
RECT AdjustRectForSizeWindowToRect(HWND window, RECT rect, HWND windowOfRect) noexcept;
// 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;
@ -214,7 +209,7 @@ namespace FancyZonesUtils
std::wstring GenerateUniqueIdAllMonitorsArea(const std::wstring& virtualDesktopId);
std::wstring TrimDeviceId(const std::wstring& deviceId);
RECT PrepareRectForCycling(RECT windowRect, RECT workAreaRect, DWORD vkCode) noexcept;
RECT PrepareRectForCycling(RECT windowRect, RECT zoneWindowRect, DWORD vkCode) noexcept;
size_t ChooseNextZoneByPosition(DWORD vkCode, RECT windowRect, const std::vector<RECT>& zoneRects) noexcept;
// If HWND is already dead, we assume it wasn't elevated

View file

@ -56,9 +56,6 @@
<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>
<ProjectReference Include="..\FancyZonesLib\FancyZonesLib.vcxproj">
<Project>{f9c68edf-ac74-4b77-9af1-005d9c9f6a99}</Project>
</ProjectReference>

View file

@ -62,9 +62,6 @@
<ProjectReference Include="..\..\..\..\common\Display\Display.vcxproj">
<Project>{caba8dfb-823b-4bf2-93ac-3f31984150d9}</Project>
</ProjectReference>
<ProjectReference Include="..\..\..\..\common\SettingsAPI\SetttingsAPI.vcxproj">
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
</ProjectReference>
<ProjectReference Include="..\..\FancyZonesLib\FancyZonesLib.vcxproj">
<Project>{f9c68edf-ac74-4b77-9af1-005d9c9f6a99}</Project>
</ProjectReference>

View file

@ -81,10 +81,10 @@ namespace FancyZonesUnitTests
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
testWorkArea(workArea);
auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
auto* activeZoneSet{ workArea->ActiveZoneSet() };
Assert::IsNotNull(activeZoneSet);
Assert::AreEqual(static_cast<int>(activeZoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(activeZoneSet->GetZones().size(), static_cast<size_t>(3));
}
TEST_METHOD (CreateWorkAreaNoHinst)
@ -92,10 +92,10 @@ namespace FancyZonesUnitTests
auto workArea = MakeWorkArea({}, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
testWorkArea(workArea);
auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
auto* activeZoneSet{ workArea->ActiveZoneSet() };
Assert::IsNotNull(activeZoneSet);
Assert::AreEqual(static_cast<int>(activeZoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(activeZoneSet->GetZones().size(), static_cast<size_t>(3));
}
TEST_METHOD (CreateWorkAreaNoHinstFlashZones)
@ -103,10 +103,10 @@ namespace FancyZonesUnitTests
auto workArea = MakeWorkArea({}, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
testWorkArea(workArea);
auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
auto* activeZoneSet{ workArea->ActiveZoneSet() };
Assert::IsNotNull(activeZoneSet);
Assert::AreEqual(static_cast<int>(activeZoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(activeZoneSet->GetZones().size(), static_cast<size_t>(3));
}
TEST_METHOD (CreateWorkAreaNoMonitor)
@ -138,10 +138,10 @@ namespace FancyZonesUnitTests
Assert::IsNotNull(workArea.get());
Assert::IsTrue(expectedUniqueId == workArea->UniqueId());
auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
auto* activeZoneSet{ workArea->ActiveZoneSet() };
Assert::IsNotNull(activeZoneSet);
Assert::AreEqual(static_cast<int>(activeZoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(activeZoneSet->GetZones().size(), static_cast<size_t>(3));
}
TEST_METHOD (CreateWorkAreaNoDesktopId)
@ -164,10 +164,10 @@ namespace FancyZonesUnitTests
const std::wstring expectedWorkArea = std::to_wstring(m_monitorInfo.rcMonitor.right) + L"_" + std::to_wstring(m_monitorInfo.rcMonitor.bottom);
Assert::IsNotNull(workArea.get());
auto* zoneSet{ workArea->ZoneSet() };
Assert::IsNotNull(zoneSet);
Assert::AreEqual(static_cast<int>(zoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(zoneSet->GetZones().size(), static_cast<size_t>(3));
auto* activeZoneSet{ workArea->ActiveZoneSet() };
Assert::IsNotNull(activeZoneSet);
Assert::AreEqual(static_cast<int>(activeZoneSet->LayoutType()), static_cast<int>(FancyZonesDataTypes::ZoneSetLayoutType::PriorityGrid));
Assert::AreEqual(activeZoneSet->GetZones().size(), static_cast<size_t>(3));
}
TEST_METHOD (CreateWorkAreaClonedFromParent)
@ -187,7 +187,7 @@ namespace FancyZonesUnitTests
// newWorkArea = false - workArea won't be cloned from parent
auto actualWorkArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
Assert::IsNotNull(actualWorkArea->ZoneSet());
Assert::IsNotNull(actualWorkArea->ActiveZoneSet());
Assert::IsTrue(m_fancyZonesData.GetDeviceInfoMap().contains(m_uniqueId));
auto currentDeviceInfo = m_fancyZonesData.GetDeviceInfoMap().at(m_uniqueId);
@ -299,7 +299,7 @@ namespace FancyZonesUnitTests
const auto actual = workArea->MoveSizeEnd(window, POINT{ 0, 0 });
Assert::AreEqual(expected, actual);
const auto zoneSet = workArea->ZoneSet();
const auto zoneSet = workArea->ActiveZoneSet();
zoneSet->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0);
const auto actualZoneIndexSet = zoneSet->GetZoneIndexSetFromWindow(window);
Assert::IsFalse(std::vector<ZoneIndex>{} == actualZoneIndexSet);
@ -316,7 +316,7 @@ namespace FancyZonesUnitTests
const auto actual = workArea->MoveSizeEnd(window, POINT{ -100, -100 });
Assert::AreEqual(expected, actual);
const auto zoneSet = workArea->ZoneSet();
const auto zoneSet = workArea->ActiveZoneSet();
const auto actualZoneIndexSet = zoneSet->GetZoneIndexSetFromWindow(window);
Assert::IsTrue(std::vector<ZoneIndex>{} == actualZoneIndexSet);
}
@ -355,7 +355,7 @@ namespace FancyZonesUnitTests
const auto actual = workArea->MoveSizeEnd(window, POINT{ -1, -1 });
Assert::AreEqual(expected, actual);
const auto zoneSet = workArea->ZoneSet();
const auto zoneSet = workArea->ActiveZoneSet();
zoneSet->MoveWindowIntoZoneByIndex(window, Mocks::Window(), 0);
const auto actualZoneIndex = zoneSet->GetZoneIndexSetFromWindow(window);
Assert::IsFalse(std::vector<ZoneIndex>{} == actualZoneIndex); // with invalid point zone remains the same
@ -364,17 +364,17 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByIndex)
{
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
Assert::IsNotNull(workArea->ZoneSet());
Assert::IsNotNull(workArea->ActiveZoneSet());
workArea->MoveWindowIntoZoneByIndex(Mocks::Window(), 0);
const auto actual = workArea->ZoneSet();
const auto actual = workArea->ActiveZoneSet();
}
TEST_METHOD (MoveWindowIntoZoneByDirectionAndIndex)
{
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
Assert::IsNotNull(workArea->ZoneSet());
Assert::IsNotNull(workArea->ActiveZoneSet());
const auto window = Mocks::WindowCreate(m_hInst);
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true);
@ -389,7 +389,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByDirectionManyTimes)
{
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
Assert::IsNotNull(workArea->ZoneSet());
Assert::IsNotNull(workArea->ActiveZoneSet());
const auto window = Mocks::WindowCreate(m_hInst);
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_RIGHT, true);
@ -406,7 +406,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (SaveWindowProcessToZoneIndexNullptrWindow)
{
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
Assert::IsNotNull(workArea->ZoneSet());
Assert::IsNotNull(workArea->ActiveZoneSet());
workArea->SaveWindowProcessToZoneIndex(nullptr);
@ -417,11 +417,11 @@ namespace FancyZonesUnitTests
TEST_METHOD (SaveWindowProcessToZoneIndexNoWindowAdded)
{
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
Assert::IsNotNull(workArea->ZoneSet());
Assert::IsNotNull(workArea->ActiveZoneSet());
auto window = Mocks::WindowCreate(m_hInst);
auto zone = MakeZone(RECT{ 0, 0, 100, 100 }, 1);
workArea->ZoneSet()->AddZone(zone);
workArea->ActiveZoneSet()->AddZone(zone);
workArea->SaveWindowProcessToZoneIndex(window);
@ -432,12 +432,12 @@ namespace FancyZonesUnitTests
TEST_METHOD (SaveWindowProcessToZoneIndexNoWindowAddedWithFilledAppZoneHistory)
{
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
Assert::IsNotNull(workArea->ZoneSet());
Assert::IsNotNull(workArea->ActiveZoneSet());
const auto window = Mocks::WindowCreate(m_hInst);
const auto processPath = get_process_path(window);
const auto deviceId = workArea->UniqueId();
const auto zoneSetId = workArea->ZoneSet()->Id();
const auto zoneSetId = workArea->ActiveZoneSet()->Id();
// fill app zone history map
Assert::IsTrue(m_fancyZonesData.SetAppLastZones(window, deviceId, Helpers::GuidToString(zoneSetId), { 0 }));
@ -448,7 +448,7 @@ namespace FancyZonesUnitTests
// add zone without window
const auto zone = MakeZone(RECT{ 0, 0, 100, 100 }, 1);
workArea->ZoneSet()->AddZone(zone);
workArea->ActiveZoneSet()->AddZone(zone);
workArea->SaveWindowProcessToZoneIndex(window);
Assert::AreEqual((size_t)1, m_fancyZonesData.GetAppZoneHistoryMap().size());
@ -460,15 +460,15 @@ namespace FancyZonesUnitTests
TEST_METHOD (SaveWindowProcessToZoneIndexWindowAdded)
{
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
Assert::IsNotNull(workArea->ZoneSet());
Assert::IsNotNull(workArea->ActiveZoneSet());
auto window = Mocks::WindowCreate(m_hInst);
const auto processPath = get_process_path(window);
const auto deviceId = workArea->UniqueId();
const auto zoneSetId = workArea->ZoneSet()->Id();
const auto zoneSetId = workArea->ActiveZoneSet()->Id();
auto zone = MakeZone(RECT{ 0, 0, 100, 100 }, 1);
workArea->ZoneSet()->AddZone(zone);
workArea->ActiveZoneSet()->AddZone(zone);
workArea->MoveWindowIntoZoneByIndex(window, 0);
//fill app zone history map
@ -482,7 +482,7 @@ namespace FancyZonesUnitTests
const auto& actualAppZoneHistory = m_fancyZonesData.GetAppZoneHistoryMap();
Assert::AreEqual((size_t)1, actualAppZoneHistory.size());
const auto& expected = workArea->ZoneSet()->GetZoneIndexSetFromWindow(window);
const auto& expected = workArea->ActiveZoneSet()->GetZoneIndexSetFromWindow(window);
const auto& actual = appHistoryArray[0].zoneIndexSet;
Assert::IsTrue(expected == actual);
}
@ -490,7 +490,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (WhenWindowIsNotResizablePlacingItIntoTheZoneShouldNotResizeIt)
{
auto workArea = MakeWorkArea(m_hInst, m_monitor, m_uniqueId, {}, m_zoneColors, m_overlappingAlgorithm);
Assert::IsNotNull(workArea->ZoneSet());
Assert::IsNotNull(workArea->ActiveZoneSet());
auto window = Mocks::WindowCreate(m_hInst);
@ -501,7 +501,7 @@ namespace FancyZonesUnitTests
SetWindowLong(window, GWL_STYLE, GetWindowLong(window, GWL_STYLE) & ~WS_SIZEBOX);
auto zone = MakeZone(RECT{ 50, 50, 300, 300 }, 1);
workArea->ZoneSet()->AddZone(zone);
workArea->ActiveZoneSet()->AddZone(zone);
workArea->MoveWindowIntoZoneByDirectionAndIndex(window, VK_LEFT, true);

View file

@ -297,9 +297,9 @@ namespace FancyZonesUnitTests
{
winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 100, 100 }, 1);
HWND window = Mocks::Window();
HWND workArea = Mocks::Window();
HWND zoneWindow = Mocks::Window();
m_set->AddZone(zone);
m_set->MoveWindowIntoZoneByIndexSet(window, workArea, { 0 });
m_set->MoveWindowIntoZoneByIndexSet(window, zoneWindow, { 0 });
auto actual = m_set->GetZoneIndexSetFromWindow(Mocks::Window());
Assert::IsTrue(std::vector<ZoneIndex>{} == actual);
@ -309,9 +309,9 @@ namespace FancyZonesUnitTests
{
winrt::com_ptr<IZone> zone = MakeZone({ 0, 0, 100, 100 }, 1);
HWND window = Mocks::Window();
HWND workArea = Mocks::Window();
HWND zoneWindow = Mocks::Window();
m_set->AddZone(zone);
m_set->MoveWindowIntoZoneByIndexSet(window, workArea, { 0 });
m_set->MoveWindowIntoZoneByIndexSet(window, zoneWindow, { 0 });
auto actual = m_set->GetZoneIndexSetFromWindow(nullptr);
Assert::IsTrue(std::vector<ZoneIndex>{} == actual);
@ -432,7 +432,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByPointDropAddWindow)
{
const auto window = Mocks::Window();
const auto workArea = Mocks::Window();
const auto zoneWindow = Mocks::Window();
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
@ -450,7 +450,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByPointDropAddWindowToSameZone)
{
const auto window = Mocks::Window();
const auto workArea = Mocks::Window();
const auto zoneWindow = Mocks::Window();
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);
@ -468,7 +468,7 @@ namespace FancyZonesUnitTests
TEST_METHOD (MoveWindowIntoZoneByPointSeveralZonesWithSameWindow)
{
const auto window = Mocks::Window();
const auto workArea = Mocks::Window();
const auto zoneWindow = Mocks::Window();
winrt::com_ptr<IZone> zone1 = MakeZone({ 0, 0, 100, 100 }, 0);
winrt::com_ptr<IZone> zone2 = MakeZone({ 10, 10, 90, 90 }, 1);

View file

@ -486,41 +486,6 @@ namespace ImageResizer.Models
image => Assert.IsNull(((BitmapMetadata)image.Frames[0].Metadata).GetQuerySafe("System.Photo.Orientation")));
}
[TestMethod]
public void VerifyFileNameIsSanitized()
{
var operation = new ResizeOperation(
"Test.png",
_directory,
Settings(
s =>
{
s.FileName = @"Directory\%1:*?""<>|(%2)";
s.SelectedSize.Name = "Test\\/";
}));
operation.Execute();
Assert.IsTrue(File.Exists(_directory + @"\Directory\Test_______(Test__).png"));
}
[TestMethod]
public void VerifyNotRecommendedNameIsChanged()
{
var operation = new ResizeOperation(
"Test.png",
_directory,
Settings(
s =>
{
s.FileName = @"nul";
}));
operation.Execute();
Assert.IsTrue(File.Exists(_directory + @"\nul_.png"));
}
private static Settings Settings(Action<Settings> action = null)
{
var settings = new Settings()

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;
@ -27,14 +26,6 @@ namespace ImageResizer.Models
private readonly string _destinationDirectory;
private readonly Settings _settings;
// Filenames to avoid according to https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file#file-and-directory-names
private static readonly string[] _avoidFilenames =
{
"CON", "PRN", "AUX", "NUL",
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
};
public ResizeOperation(string file, string destinationDirectory, Settings settings)
{
_file = file;
@ -84,36 +75,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 +97,9 @@ namespace ImageResizer.Models
encoder.Frames.Add(
BitmapFrame.Create(
Transform(originalFrame),
originalFrame.Thumbnail,
thumbnail: null,
metadata,
originalFrame.ColorContexts));
colorContexts: null));
}
path = GetDestinationPath(encoder);
@ -239,39 +205,16 @@ namespace ImageResizer.Models
extension = supportedExtensions.FirstOrDefault();
}
// Remove directory characters from the size's name.
string sizeNameSanitized = _settings.SelectedSize.Name;
sizeNameSanitized = sizeNameSanitized
.Replace('\\', '_')
.Replace('/', '_');
// Using CurrentCulture since this is user facing
var fileName = string.Format(
CultureInfo.CurrentCulture,
_settings.FileNameFormat,
originalFileName,
sizeNameSanitized,
_settings.SelectedSize.Name,
_settings.SelectedSize.Width,
_settings.SelectedSize.Height,
encoder.Frames[0].PixelWidth,
encoder.Frames[0].PixelHeight);
// Remove invalid characters from the final file name.
fileName = fileName
.Replace(':', '_')
.Replace('*', '_')
.Replace('?', '_')
.Replace('"', '_')
.Replace('<', '_')
.Replace('>', '_')
.Replace('|', '_');
// Avoid creating not recommended filenames
if (_avoidFilenames.Contains(fileName.ToUpperInvariant()))
{
fileName = fileName + "_";
}
var path = _fileSystem.Path.Combine(directory, fileName + extension);
var uniquifier = 1;
while (_fileSystem.File.Exists(path))

View file

@ -71,9 +71,6 @@
<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>
<ItemGroup>
<None Include="packages.config" />

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

@ -44,9 +44,13 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces
var title = $"{a.FolderName}";
var typeWorkspace = a.WorkspaceTypeToString();
if (a.TypeWorkspace != TypeWorkspace.Local)
if (a.TypeWorkspace == TypeWorkspace.Codespaces)
{
title = $"{title}{(a.ExtraInfo != null ? $" - {a.ExtraInfo}" : string.Empty)} ({typeWorkspace})";
title += $" - {typeWorkspace}";
}
else if (a.TypeWorkspace != TypeWorkspace.Local)
{
title += $" - {(a.ExtraInfo != null ? $"{a.ExtraInfo} ({typeWorkspace})" : typeWorkspace)}";
}
var tooltip = new ToolTipData(title, $"{Resources.Workspace}{(a.TypeWorkspace != TypeWorkspace.Local ? $" {Resources.In} {typeWorkspace}" : string.Empty)}: {SystemPath.RealPath(a.RelativePath)}");

View file

@ -105,15 +105,6 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to Dev Container.
/// </summary>
internal static string TypeWorkspaceDevContainer {
get {
return ResourceManager.GetString("TypeWorkspaceDevContainer", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Local.
/// </summary>

View file

@ -142,8 +142,4 @@
<value>Workspace</value>
<comment>It refers to the "Visual Studio Code workspace"</comment>
</data>
<data name="TypeWorkspaceDevContainer" xml:space="preserve">
<value>Dev Container</value>
<comment>As in "Visual Studio Code Dev Container workspace "</comment>
</data>
</root>

View file

@ -16,8 +16,6 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper
private static readonly Regex CodespacesWorkspace = new Regex(@"^vscode-remote://vsonline\+(.+?(?=\/))(.+)$", RegexOptions.Compiled);
private static readonly Regex DevContainerWorkspace = new Regex(@"^vscode-remote://dev-container\+(.+?(?=\/))(.+)$", RegexOptions.Compiled);
public static (TypeWorkspace? TypeWorkspace, string MachineName, string Path) GetTypeWorkspace(string uri)
{
if (LocalWorkspace.IsMatch(uri))
@ -53,16 +51,7 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper
if (match.Groups.Count > 1)
{
return (TypeWorkspace.Codespaces, null, match.Groups[2].Value);
}
}
else if (DevContainerWorkspace.IsMatch(uri))
{
var match = DevContainerWorkspace.Match(uri);
if (match.Groups.Count > 1)
{
return (TypeWorkspace.DevContainer, null, match.Groups[2].Value);
return (TypeWorkspace.Codespaces, string.Empty, match.Groups[2].Value);
}
}

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