Compare commits
149 Commits
dev/snickl
...
feature/sh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d1ae0d191 | ||
|
|
3df4b45849 | ||
|
|
88357a5a99 | ||
|
|
b4773affa7 | ||
|
|
e82c2d20cb | ||
|
|
e3a1f97ef3 | ||
|
|
b26ded5370 | ||
|
|
2e8ad4827b | ||
|
|
877626ef45 | ||
|
|
e0f72df36c | ||
|
|
552b02d596 | ||
|
|
c184acbada | ||
|
|
55038c3c5e | ||
|
|
f537c43139 | ||
|
|
f867323677 | ||
|
|
d58145eb8c | ||
|
|
486bec0ebd | ||
|
|
e76506dffd | ||
|
|
841a5c5555 | ||
|
|
f646e0328e | ||
|
|
5054a776dd | ||
|
|
9d480c8e2c | ||
|
|
d652285a81 | ||
|
|
200afb5c4b | ||
|
|
e7582ebd6a | ||
|
|
b9c1181d9f | ||
|
|
4aff3418e4 | ||
|
|
e53e1b4376 | ||
|
|
73f718c233 | ||
|
|
0917a64e7d | ||
|
|
a764bf3e0c | ||
|
|
4853bd0345 | ||
|
|
dceb1d7730 | ||
|
|
72be09554e | ||
|
|
19f95066c3 | ||
|
|
bb16ae1709 | ||
|
|
dc0877ebe5 | ||
|
|
cd844e3889 | ||
|
|
ac789a7fbe | ||
|
|
3b7df37ac2 | ||
|
|
387b7e9795 | ||
|
|
b553addcdd | ||
|
|
5c11c751fe | ||
|
|
6d7d5f9cde | ||
|
|
4cb9c53809 | ||
|
|
84d4cbb16d | ||
|
|
97cba618da | ||
|
|
145247c4fb | ||
|
|
84ab12027b | ||
|
|
3458d01d4c | ||
|
|
2e6f80f944 | ||
|
|
f8cc513f9c | ||
|
|
b1d5233622 | ||
|
|
68b7b4183f | ||
|
|
68a10d0488 | ||
|
|
e70ca56e9d | ||
|
|
16c4a56ca1 | ||
|
|
0d5c85a00d | ||
|
|
509ad636fe | ||
|
|
26f76105d4 | ||
|
|
639b29eb8c | ||
|
|
bff3874b5f | ||
|
|
eff58e1df5 | ||
|
|
411f4df2c0 | ||
|
|
7dc8c1000b | ||
|
|
48d8e33375 | ||
|
|
afc27e873f | ||
|
|
3302e61d72 | ||
|
|
e6edca93e7 | ||
|
|
7acab452d5 | ||
|
|
0a07811233 | ||
|
|
9ecf82d2ea | ||
|
|
44d12c6e63 | ||
|
|
6b8a3e65f7 | ||
|
|
2b16068a7d | ||
|
|
440e75184a | ||
|
|
acf510dff5 | ||
|
|
ddd090cc81 | ||
|
|
2f4766df19 | ||
|
|
6558260c53 | ||
|
|
55b3e15f10 | ||
|
|
69c6475e15 | ||
|
|
8e7be164a9 | ||
|
|
f42b3922c7 | ||
|
|
d568d16560 | ||
|
|
0abae1d190 | ||
|
|
271e0c0533 | ||
|
|
6bd5c4c811 | ||
|
|
a41be807a4 | ||
|
|
e11626550e | ||
|
|
7266745124 | ||
|
|
77a5bc2ff5 | ||
|
|
0b6683eb34 | ||
|
|
3796fdb706 | ||
|
|
2d12932e44 | ||
|
|
1da76e55bb | ||
|
|
3c1a6a5b16 | ||
|
|
3b77feb879 | ||
|
|
7e7bb04d48 | ||
|
|
273b50cb16 | ||
|
|
498c8d534f | ||
|
|
0e2f466454 | ||
|
|
1982f2615d | ||
|
|
2f89281178 | ||
|
|
56f056e492 | ||
|
|
71dd8fe83f | ||
|
|
f9183af53d | ||
|
|
0f85f8bad6 | ||
|
|
e0e7bf4df2 | ||
|
|
b12fcf6699 | ||
|
|
2ee02c4bbe | ||
|
|
a306797d21 | ||
|
|
7e50caa04e | ||
|
|
e3b1ec356e | ||
|
|
fa54b49fca | ||
|
|
7e2fc4481d | ||
|
|
201a27d2bb | ||
|
|
fe3d481407 | ||
|
|
3475c92f32 | ||
|
|
82b0ca71fd | ||
|
|
3a8431ae9d | ||
|
|
eed6dc6f8d | ||
|
|
038cd23423 | ||
|
|
be799ddd82 | ||
|
|
e26bf2acd6 | ||
|
|
95e0a20444 | ||
|
|
3e75fb0c52 | ||
|
|
ba4098960c | ||
|
|
1580279be1 | ||
|
|
07760e4730 | ||
|
|
d73ab4f2d3 | ||
|
|
a6b761433e | ||
|
|
da77396da5 | ||
|
|
46df48684d | ||
|
|
7596e965ef | ||
|
|
0b823ea8bd | ||
|
|
54d176c4c4 | ||
|
|
569f07268b | ||
|
|
7ce5182695 | ||
|
|
b16b4579fa | ||
|
|
a292a92f4d | ||
|
|
6952deb4ae | ||
|
|
da7b789bfe | ||
|
|
a14c458f19 | ||
|
|
22dc870991 | ||
|
|
d5f5500347 | ||
|
|
c81a423880 | ||
|
|
7a6189ba3e | ||
|
|
03587ae800 |
5
.github/actions/spell-check/allow/code.txt
vendored
@@ -47,6 +47,7 @@ resw
|
||||
resx
|
||||
srt
|
||||
Stereolithography
|
||||
taskmgr
|
||||
terabyte
|
||||
UYVY
|
||||
xbf
|
||||
@@ -319,5 +320,9 @@ MRUCMPPROC
|
||||
MRUINFO
|
||||
REGSTR
|
||||
|
||||
#Xaml
|
||||
NVI
|
||||
Storyboards
|
||||
|
||||
# Misc Win32 APIs and PInvokes
|
||||
INVOKEIDLIST
|
||||
|
||||
6
.github/actions/spell-check/expect.txt
vendored
@@ -806,6 +806,8 @@ jpnime
|
||||
Jsons
|
||||
jsonval
|
||||
jxr
|
||||
KBSC
|
||||
kdc
|
||||
keybd
|
||||
KEYBDDATA
|
||||
KEYBDINPUT
|
||||
@@ -1199,6 +1201,7 @@ OUTOFCONTEXT
|
||||
Outptr
|
||||
outputtype
|
||||
outsettings
|
||||
outsourced
|
||||
OVERLAPPEDWINDOW
|
||||
Oversampling
|
||||
OVERWRITEPROMPT
|
||||
@@ -1262,6 +1265,7 @@ phwnd
|
||||
pici
|
||||
pidl
|
||||
PIDLIST
|
||||
pinboard
|
||||
pinfo
|
||||
pinvoke
|
||||
pipename
|
||||
@@ -1340,6 +1344,7 @@ projectname
|
||||
PROPERTYKEY
|
||||
Propset
|
||||
PROPVARIANT
|
||||
Prt
|
||||
PRTL
|
||||
prvpane
|
||||
psapi
|
||||
@@ -1992,6 +1997,7 @@ WNDCLASSW
|
||||
WNDPROC
|
||||
wnode
|
||||
wom
|
||||
workerw
|
||||
WORKSPACESEDITOR
|
||||
WORKSPACESLAUNCHER
|
||||
WORKSPACESSNAPSHOTTOOL
|
||||
|
||||
@@ -220,8 +220,12 @@
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.dll",
|
||||
"WinUI3Apps\\PowerToys.RegistryPreview.exe",
|
||||
|
||||
"PowerToys.ShortcutGuide.exe",
|
||||
"PowerToys.ShortcutGuideModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuide.exe",
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuide.dll",
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuideModuleInterface.dll",
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuide.IndexYmlGenerator.dll",
|
||||
"WinUI3Apps\\PowerToys.ShortcutGuide.IndexYmlGenerator.exe",
|
||||
"WinUI3Apps\\ShortcutGuide.CPPProject.dll",
|
||||
|
||||
"PowerToys.ZoomIt.exe",
|
||||
"PowerToys.ZoomItModuleInterface.dll",
|
||||
|
||||
@@ -113,6 +113,7 @@
|
||||
<PackageVersion Include="WinUIEx" Version="2.8.0" />
|
||||
<PackageVersion Include="WPF-UI" Version="3.0.5" />
|
||||
<PackageVersion Include="WyHash" Version="1.0.5" />
|
||||
<PackageVersion Include="YamlDotNet" Version="16.3.0" />
|
||||
<PackageVersion Include="WixToolset.Heat" Version="5.0.2" />
|
||||
<PackageVersion Include="WixToolset.Firewall.wixext" Version="5.0.2" />
|
||||
<PackageVersion Include="WixToolset.Util.wixext" Version="5.0.2" />
|
||||
|
||||
@@ -1537,4 +1537,5 @@ SOFTWARE.
|
||||
- UTF.Unknown
|
||||
- WinUIEx
|
||||
- WPF-UI
|
||||
- WyHash
|
||||
- WyHash
|
||||
- YamlDotNet
|
||||
@@ -42,7 +42,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "fancyzones", "fancyzones",
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZonesLib", "src\modules\fancyzones\FancyZonesLib\FancyZonesLib.vcxproj", "{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZones.UnitTests", "src\modules\fancyzones\FancyZonesTests\UnitTests\UnitTests.vcxproj", "{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests", "src\modules\fancyzones\FancyZonesTests\UnitTests\UnitTests.vcxproj", "{9C6A7905-72D4-4BF5-B256-ABFDAEF68AE9}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99} = {F9C68EDF-AC74-4B77-9AF1-005D9C9F6A99}
|
||||
EndProjectSection
|
||||
@@ -66,7 +66,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameLib", "src\modul
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameTest", "src\modules\powerrename\testapp\PowerRenameTest.vcxproj", "{A3935CF4-46C5-4A88-84D3-6B12E16E6BA2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.UnitTests", "src\modules\powerrename\unittests\PowerRenameLibUnitTests.vcxproj", "{2151F984-E006-4A9F-92EF-C6DDE3DC8413}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRenameLibUnitTests", "src\modules\powerrename\unittests\PowerRenameLibUnitTests.vcxproj", "{2151F984-E006-4A9F-92EF-C6DDE3DC8413}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{51920F1F-C28C-4ADF-8660-4238766796C2} = {51920F1F-C28C-4ADF-8660-4238766796C2}
|
||||
{B25AC7A5-FB9F-4789-B392-D5C85E948670} = {B25AC7A5-FB9F-4789-B392-D5C85E948670}
|
||||
@@ -316,13 +316,13 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEngine", "sr
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEngineLibrary", "src\modules\keyboardmanager\KeyboardManagerEngineLibrary\KeyboardManagerEngineLibrary.vcxproj", "{E496B7FC-1E99-4BAB-849B-0E8367040B02}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager.Engine.UnitTests", "src\modules\keyboardmanager\KeyboardManagerEngineTest\KeyboardManagerEngineTest.vcxproj", "{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEngineTest", "src\modules\keyboardmanager\KeyboardManagerEngineTest\KeyboardManagerEngineTest.vcxproj", "{7F4B3A60-BC27-45A7-8000-68B0B6EA7466}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditor", "src\modules\keyboardmanager\KeyboardManagerEditor\KeyboardManagerEditor.vcxproj", "{8DF78B53-200E-451F-9328-01EB907193AE}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditorLibrary", "src\modules\keyboardmanager\KeyboardManagerEditorLibrary\KeyboardManagerEditorLibrary.vcxproj", "{23D2070D-E4AD-4ADD-85A7-083D9C76AD49}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManager.Editor.UnitTests", "src\modules\keyboardmanager\KeyboardManagerEditorTest\KeyboardManagerEditorTest.vcxproj", "{62173D9A-6724-4C00-A1C8-FB646480A9EC}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KeyboardManagerEditorTest", "src\modules\keyboardmanager\KeyboardManagerEditorTest\KeyboardManagerEditorTest.vcxproj", "{62173D9A-6724-4C00-A1C8-FB646480A9EC}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "awake", "awake", "{127F38E0-40AA-4594-B955-5616BF206882}"
|
||||
EndProject
|
||||
@@ -334,12 +334,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plu
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Community.PowerToys.Run.Plugin.UnitConverter.UnitTest", "src\modules\launcher\Plugins\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest\Community.PowerToys.Run.Plugin.UnitConverter.UnitTest.csproj", "{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shortcutguide", "shortcutguide", "{106CBECA-0701-4FC3-838C-9DF816A19AE2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuideModuleInterface", "src\modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.vcxproj", "{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuide", "src\modules\ShortcutGuide\ShortcutGuide\ShortcutGuide.vcxproj", "{2EDB3EB4-FA92-4BFF-B2D8-566584837231}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZonesModuleInterface", "src\modules\fancyzones\FancyZonesModuleInterface\FancyZonesModuleInterface.vcxproj", "{48804216-2A0E-4168-A6D8-9CD068D14227}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FancyZones", "src\modules\fancyzones\FancyZones\FancyZones.vcxproj", "{FF1D7936-842A-4BBB-8BEA-E9FE796DE700}"
|
||||
@@ -451,7 +445,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithExt", "src\mod
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileLocksmithUI", "src\modules\FileLocksmith\FileLocksmithUI\FileLocksmithUI.csproj", "{E69B044A-2F8A-45AA-AD0B-256C59421807}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.FileLocksmithLib.Interop", "src\modules\FileLocksmith\FileLocksmithLibInterop\FileLocksmithLibInterop.vcxproj", "{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "FileLocksmithLibInterop", "src\modules\FileLocksmith\FileLocksmithLibInterop\FileLocksmithLibInterop.vcxproj", "{C604B37E-9D0E-4484-8778-E8B31B0E1B3A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GPOWrapper", "src\common\GPOWrapper\GPOWrapper.vcxproj", "{E599C30B-9DC8-4E5A-BF27-93D4CCEDE788}"
|
||||
EndProject
|
||||
@@ -459,7 +453,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GPOWrapperProjection", "src
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Peek", "Peek", "{17B4FA70-001E-4D33-BBBB-0D142DBC2E20}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Peek", "src\modules\peek\peek\peek.vcxproj", "{A1425B53-3D61-4679-8623-E64A0D3D0A48}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "peek", "src\modules\peek\peek\peek.vcxproj", "{A1425B53-3D61-4679-8623-E64A0D3D0A48}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Peek.UI", "src\modules\peek\Peek.UI\Peek.UI.csproj", "{9D7A6DE0-7D27-424D-ABAE-41B2161F9A03}"
|
||||
EndProject
|
||||
@@ -574,7 +568,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PowerToys.Settings.DSC.Sche
|
||||
{020A7474-3601-4160-A159-D7B70B77B15F} = {020A7474-3601-4160-A159-D7B70B77B15F}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewPlus.ShellExtension", "src\modules\NewPlus\NewShellExtensionContextMenu\NewShellExtensionContextMenu.vcxproj", "{8ACB33D9-C95B-47D4-8363-9731EE0930A0}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NewShellExtensionContextMenu", "src\modules\NewPlus\NewShellExtensionContextMenu\NewShellExtensionContextMenu.vcxproj", "{8ACB33D9-C95B-47D4-8363-9731EE0930A0}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "New+", "New+", "{CA716AE6-FE5C-40AC-BB8F-2C87912687AC}"
|
||||
EndProject
|
||||
@@ -703,7 +697,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.System
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CmdPalKeyboardService", "src\modules\cmdpal\CmdPalKeyboardService\CmdPalKeyboardService.vcxproj", "{5F63C743-F6CE-4DBA-A200-2B3F8A14E8C2}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzTests", "src\modules\powerrename\PowerRename.FuzzingTest\PowerRename.FuzzingTest.vcxproj", "{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}"
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerRename.FuzzingTest", "src\modules\powerrename\PowerRename.FuzzingTest\PowerRename.FuzzingTest.vcxproj", "{2694E2FB-DCD5-4BFF-A418-B6C3C7CE3B8E}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BgcodePreviewHandler", "src\modules\previewpane\BgcodePreviewHandler\BgcodePreviewHandler.csproj", "{9E0CBC06-F29A-4810-B93C-97D53863B95E}"
|
||||
EndProject
|
||||
@@ -830,6 +824,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.Ext.Clipbo
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.CmdPal.UI.ViewModels.UnitTests", "src\modules\cmdpal\Tests\Microsoft.CmdPal.UI.ViewModels.UnitTests\Microsoft.CmdPal.UI.ViewModels.UnitTests.csproj", "{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ShortcutGuide", "ShortcutGuide", "{17A43950-5FA1-47AC-A4E7-2E6E4A3C32D5}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuide.CPPProject", "src\modules\ShortcutGuide\ShortcutGuide.CPPProject\ShortcutGuide.CPPProject.vcxproj", "{C992FD2C-83B8-4941-9FC1-09730068D8EC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShortcutGuide.IndexYmlGenerator", "src\modules\ShortcutGuide\ShortcutGuide.IndexYmlGenerator\ShortcutGuide.IndexYmlGenerator.csproj", "{30F57201-9B54-5253-8033-8A28ECD3F1CE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShortcutGuide.Ui", "src\modules\ShortcutGuide\ShortcutGuide.Ui\ShortcutGuide.Ui.csproj", "{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuideModuleInterface", "src\modules\ShortcutGuide\ShortcutGuideModuleInterface\ShortcutGuideModuleInterface.vcxproj", "{E487304A-B1FB-4E6B-8E70-014051AF5B99}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
@@ -1470,22 +1474,6 @@ Global
|
||||
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.ActiveCfg = Release|x64
|
||||
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.Build.0 = Release|x64
|
||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.Build.0 = Debug|x64
|
||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.ActiveCfg = Release|x64
|
||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.Build.0 = Release|x64
|
||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.Build.0 = Debug|x64
|
||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.ActiveCfg = Release|x64
|
||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.Build.0 = Release|x64
|
||||
{48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{48804216-2A0E-4168-A6D8-9CD068D14227}.Debug|x64.ActiveCfg = Debug|x64
|
||||
@@ -3016,6 +3004,38 @@ Global
|
||||
{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|x64.ActiveCfg = Release|x64
|
||||
{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C}.Release|x64.Build.0 = Release|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Debug|x64.Build.0 = Debug|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|x64.ActiveCfg = Release|x64
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC}.Release|x64.Build.0 = Release|x64
|
||||
{30F57201-9B54-5253-8033-8A28ECD3F1CE}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{30F57201-9B54-5253-8033-8A28ECD3F1CE}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{30F57201-9B54-5253-8033-8A28ECD3F1CE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{30F57201-9B54-5253-8033-8A28ECD3F1CE}.Debug|x64.Build.0 = Debug|x64
|
||||
{30F57201-9B54-5253-8033-8A28ECD3F1CE}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{30F57201-9B54-5253-8033-8A28ECD3F1CE}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{30F57201-9B54-5253-8033-8A28ECD3F1CE}.Release|x64.ActiveCfg = Release|x64
|
||||
{30F57201-9B54-5253-8033-8A28ECD3F1CE}.Release|x64.Build.0 = Release|x64
|
||||
{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Debug|x64.Build.0 = Debug|x64
|
||||
{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Release|x64.ActiveCfg = Release|x64
|
||||
{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D}.Release|x64.Build.0 = Release|x64
|
||||
{E487304A-B1FB-4E6B-8E70-014051AF5B99}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{E487304A-B1FB-4E6B-8E70-014051AF5B99}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{E487304A-B1FB-4E6B-8E70-014051AF5B99}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{E487304A-B1FB-4E6B-8E70-014051AF5B99}.Debug|x64.Build.0 = Debug|x64
|
||||
{E487304A-B1FB-4E6B-8E70-014051AF5B99}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{E487304A-B1FB-4E6B-8E70-014051AF5B99}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{E487304A-B1FB-4E6B-8E70-014051AF5B99}.Release|x64.ActiveCfg = Release|x64
|
||||
{E487304A-B1FB-4E6B-8E70-014051AF5B99}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -3111,9 +3131,6 @@ Global
|
||||
{D940E07F-532C-4FF3-883F-790DA014F19A} = {127F38E0-40AA-4594-B955-5616BF206882}
|
||||
{BB23A474-5058-4F75-8FA3-5FE3DE53CDF4} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||
{3E424AD2-19E5-4AE6-B833-F53963EB5FC1} = {B9617A31-0F0A-4397-851D-BF2FBEE32D7F}
|
||||
{106CBECA-0701-4FC3-838C-9DF816A19AE2} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{2D604C07-51FC-46BB-9EB7-75AECC7F5E81} = {106CBECA-0701-4FC3-838C-9DF816A19AE2}
|
||||
{2EDB3EB4-FA92-4BFF-B2D8-566584837231} = {106CBECA-0701-4FC3-838C-9DF816A19AE2}
|
||||
{48804216-2A0E-4168-A6D8-9CD068D14227} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
||||
{FF1D7936-842A-4BBB-8BEA-E9FE796DE700} = {D1D6BC88-09AE-4FB4-AD24-5DED46A791DD}
|
||||
{5043CECE-E6A7-4867-9CBE-02D27D83747A} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
|
||||
@@ -3345,6 +3362,11 @@ Global
|
||||
{F5333ED7-06D8-4AB3-953A-36D63F08CB6F} = {3DCCD936-D085-4869-A1DE-CA6A64152C94}
|
||||
{4E0FCF69-B06B-D272-76BF-ED3A559B4EDA} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
|
||||
{A66E9270-5D93-EC9C-F06E-CE7295BB9A6C} = {8EF25507-2575-4ADE-BF7E-D23376903AB8}
|
||||
{17A43950-5FA1-47AC-A4E7-2E6E4A3C32D5} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC}
|
||||
{C992FD2C-83B8-4941-9FC1-09730068D8EC} = {17A43950-5FA1-47AC-A4E7-2E6E4A3C32D5}
|
||||
{30F57201-9B54-5253-8033-8A28ECD3F1CE} = {17A43950-5FA1-47AC-A4E7-2E6E4A3C32D5}
|
||||
{D5BD72DD-B461-FDD4-FD7D-AF0B620AE75D} = {17A43950-5FA1-47AC-A4E7-2E6E4A3C32D5}
|
||||
{E487304A-B1FB-4E6B-8E70-014051AF5B99} = {17A43950-5FA1-47AC-A4E7-2E6E4A3C32D5}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {C3A2F9D1-7930-4EF4-A6FC-7EE0A99821D0}
|
||||
|
||||
2
deps/cziplib
vendored
|
Before Width: | Height: | Size: 19 KiB |
@@ -9,12 +9,14 @@
|
||||
[Pull Requests](https://github.com/microsoft/PowerToys/pulls?q=is%3Apr+is%3Aopen+label%3A%22Product-Shortcut+Guide%22+)
|
||||
|
||||
## Overview
|
||||
Shortcut Guide is a PowerToy that displays an overlay of available keyboard shortcuts when the Windows key is pressed and held. It provides a visual reference for Windows key combinations, helping users discover and utilize built-in Windows shortcuts.
|
||||
Shortcut Guide is a PowerToy that displays an overlay of available keyboard shortcuts when a user-set keyboard shortcut is pressed. It helps users discover and remember keyboard shortcuts for Windows and apps.
|
||||
|
||||
> [!NOTE]
|
||||
> The spec for the manifest files is in development and will be linked here once available.
|
||||
|
||||
## Usage
|
||||
- Press and hold the Windows key to display the overlay of available shortcuts
|
||||
- Press the hotkey again to dismiss the overlay
|
||||
- The overlay displays Windows shortcuts with their corresponding actions
|
||||
- Press the user-defined hotkey to display the overlay
|
||||
- Press the hotkey again or press ESC to dismiss the overlay
|
||||
|
||||
## Build and Debug Instructions
|
||||
|
||||
@@ -25,67 +27,83 @@ Shortcut Guide is a PowerToy that displays an overlay of available keyboard shor
|
||||
4. The executable is named PowerToys.ShortcutGuide.exe
|
||||
|
||||
### Debug
|
||||
1. Right-click the ShortcutGuide project and select 'Set as Startup Project'
|
||||
1. Right-click the ShortcutGuide.Ui project and select 'Set as Startup Project'
|
||||
2. Right-click the project again and select 'Debug'
|
||||
|
||||
## Code Structure
|
||||
> [!NOTE]
|
||||
> When run in debug mode, the window behaves differently than in release mode. It will not automatically close when loosing focus, it will be displayed on top of all other windows, and it is not hidden from the taskbar.
|
||||
|
||||

|
||||
## Project Structure
|
||||
|
||||
### Core Files
|
||||
The Shortcut Guide module consists of the following 4 projects:
|
||||
|
||||
#### [`dllmain.cpp`](/src/modules/shortcut_guide/dllmain.cpp)
|
||||
Contains DLL boilerplate code. Implements the PowertoyModuleIface, including enable/disable functionality and GPO policy handling. Captures hotkey events and starts the PowerToys.ShortcutGuide.exe process to display the shortcut guide window.
|
||||
### [`ShortcutGuide.Ui`](/src/modules/ShortcutGuide/ShortcutGuide.Ui/ShortcutGuide.Ui.csproj
|
||||
|
||||
#### [`shortcut_guide.cpp`](/src/modules/shortcut_guide/shortcut_guide.cpp)
|
||||
Contains the module interface code. It initializes the settings values and the keyboard event listener. Defines the OverlayWindow class, which manages the overall logic and event handling for the PowerToys Shortcut Guide.
|
||||
This is the main UI project for the Shortcut Guide module. Upon startup it does the following tasks:
|
||||
|
||||
#### [`overlay_window.cpp`](/src/modules/shortcut_guide/overlay_window.cpp)
|
||||
Contains the code for loading the SVGs, creating and rendering of the overlay window. Manages and displays overlay windows with SVG graphics through two main classes:
|
||||
- D2DOverlaySVG: Handles loading, resizing, and manipulation of SVG graphics
|
||||
- D2DOverlayWindow: Manages the display and behavior of the overlay window
|
||||
1. Copies the built-in manifest files to the users manifest directory (overwriting existing files).
|
||||
2. Generate the `index.yml` manifest file.
|
||||
3. Populate the PowerToys shortcut manifest with the user-defined shortcuts.
|
||||
4. Starts the UI.
|
||||
|
||||
#### [`keyboard_state.cpp`](/src/modules/shortcut_guide/keyboard_state.cpp)
|
||||
Contains helper methods for checking the current state of the keyboard.
|
||||
### [`ShortcutGuide.CPPProject`](/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/ShortcutGuide.CPPProject.vcxproj)
|
||||
|
||||
#### [`target_state.cpp`](/src/modules/shortcut_guide/target_state.cpp)
|
||||
State machine that handles the keyboard events. It's responsible for deciding when to show the overlay, when to suppress the Start menu (if the overlay is displayed long enough), etc. Handles state transitions and synchronization to ensure the overlay is shown or hidden appropriately based on user interactions.
|
||||
This project exports certain functions to be used by the Shortcut Guide module, that were not able to be implemented in C#.
|
||||
|
||||
#### [`trace.cpp`](/src/modules/shortcut_guide/trace.cpp)
|
||||
Contains code for telemetry.
|
||||
#### [`excluded_app.cpp`](/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/excluded_app.cpp)
|
||||
|
||||
### Supporting Files
|
||||
This file contains one function with the following signature:
|
||||
|
||||
#### [`animation.cpp`](/src/modules/shortcut_guide/animation.cpp)
|
||||
Handles the timing and interpolation of animations. Calculates the current value of an animation based on elapsed time and a specified easing function.
|
||||
```cpp
|
||||
__declspec(dllexport) bool IsCurrentWindowExcludedFromShortcutGuide()
|
||||
```
|
||||
|
||||
#### [`d2d_svg.cpp`](/src/modules/shortcut_guide/d2d_svg.cpp)
|
||||
Provides functionality for loading, resizing, recoloring, rendering, and manipulating SVG images using Direct2D.
|
||||
This function checks if the current window is excluded from the Shortcut Guide overlay. It returns `true` if the current window is excluded otherwise it returns `false`.
|
||||
|
||||
#### [`d2d_text.cpp`](/src/modules/shortcut_guide/d2d_text.cpp)
|
||||
Handles creation, resizing, alignment, and rendering of text using Direct2D and DirectWrite.
|
||||
#### [`tasklist_positions.cpp`](/src/modules/ShortcutGuide/ShortcutGuide.CPPProject/tasklist_positions.cpp)
|
||||
|
||||
#### [`d2d_window.cpp`](/src/modules/shortcut_guide/d2d_window.cpp)
|
||||
Manages a window using Direct2D and Direct3D for rendering. Handles window creation, resizing, rendering, and destruction.
|
||||
This file contains helper functions to retrieve the positions of the taskbar buttons. It exports the following function:
|
||||
|
||||
#### [`native_event_waiter.cpp`](/src/modules/shortcut_guide/native_event_waiter.cpp)
|
||||
Waits for a named event and executes a specified action when the event is triggered. Uses a separate thread to handle event waiting and action execution.
|
||||
```cpp
|
||||
__declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size)
|
||||
```
|
||||
|
||||
#### [`tasklist_positions.cpp`](/src/modules/shortcut_guide/tasklist_positions.cpp)
|
||||
Handles retrieving and updating the positions and information of taskbar buttons in Windows.
|
||||
This function retrieves the positions of the taskbar buttons for a given monitor. It returns an array of `TasklistButton` structures (max 10), which contain the position and size of each button.
|
||||
|
||||
#### [`main.cpp`](/src/modules/shortcut_guide/main.cpp)
|
||||
The entry point for the PowerToys Shortcut Guide application. Handles initialization, ensures single instance execution, manages parent process termination, creates and displays the overlay window, and runs the main event loop.
|
||||
`monitor` must be the monitor handle of the monitor containing the taskbar instance of which the buttons should be retrieved.
|
||||
|
||||
`size` will contain the resulting array size.
|
||||
|
||||
It determines the positions through Windows `FindWindowEx` function.
|
||||
For the primary taskbar it searches for:
|
||||
* A window called "Shell_TrayWnd"
|
||||
* that contains a window called "ReBarWindow32"
|
||||
* that contains a window called "MSTaskSwWClass"
|
||||
* that contains a window called "MSTaskListWClass"
|
||||
|
||||
For any secondary taskbar it searches for:
|
||||
* A window called "Shell_SecondaryTrayWnd"
|
||||
* that contains a window called "WorkerW"
|
||||
* that contains a window called "MSTaskListWClass"
|
||||
|
||||
It then enumerates all the button elements inside "MSTaskListWClass" while skipping such with a same name (which implies the user does not use combining taskbar buttons)
|
||||
|
||||
### [`ShortcutGuide.IndexYmlGenerator`](/src/modules/ShortcutGuide/ShortcutGuide.IndexYmlGenerator/)
|
||||
|
||||
This application generates the `index.yml` manifest file.
|
||||
|
||||
It is a separate project so that its code can be easier ported to WinGet in the future.
|
||||
|
||||
### [`ShortcutGuideModuleInterface`](/src/modules/ShortcutGuide/ShortcutGuideModuleInterface/ShortcutGuideModuleInterface.vcxproj)
|
||||
|
||||
The module interface that handles opening and closing the user interface.
|
||||
|
||||
## Features and Limitations
|
||||
|
||||
- The overlay displays Windows shortcuts (Windows key combinations)
|
||||
- The module supports localization, but only for the Windows controls on the left side of the overlay
|
||||
- Currently the displayed shortcuts (Except the ones from PowerToys) are not localized.
|
||||
- It's currently rated as a P3 (lower priority) module
|
||||
|
||||
## Future Development
|
||||
|
||||
A community-contributed version 2 is in development that will support:
|
||||
- Application-specific shortcuts based on the active application
|
||||
- Additional shortcuts beyond Windows key combinations
|
||||
- PowerToys shortcuts
|
||||
- Implementing with WinGet to get new shortcut manifest files
|
||||
- Adding localization support for the built-in manifest files
|
||||
318
doc/specs/WinGet Manifest Keyboard Shortcuts schema.md
Normal file
@@ -0,0 +1,318 @@
|
||||
# WinGet Manifest Keyboard Shortcuts schema
|
||||
|
||||
## 1 What this spec is about
|
||||
|
||||
This spec provides an extension to the existing [WinGet manifest schema](https://github.com/microsoft/winget-pkgs/blob/master/doc/manifest/README.md) in form of an additional yaml file, that describes keyboard shortcuts the application provides.
|
||||
|
||||
These yaml files are saved on a per-user base and so called manifest interpreters can then display these manifests in a human-friendly version.
|
||||
|
||||
### 1.1 What this spec is not about
|
||||
|
||||
This spec does not provide a way to back up or save user-defined keyboard shortcuts.
|
||||
|
||||
## 2 Save location of manifests
|
||||
|
||||
### 2.1 WinGet
|
||||
|
||||
These files are saved online along with the other manifest files in the [WinGet Package repository](https://github.com/microsoft/winget-pkgs).
|
||||
|
||||
### 2.2 Locally
|
||||
|
||||
All manifests and one index file are saved locally under `%LocalAppData%/Microsoft/WinGet/KeyboardShortcuts`. All apps are allowed to add their manifest files there. In addition Package Managers (like WinGet) and manifest interpreters (like PowerToys Shortcut Guide) can control and add other manifests themselves.
|
||||
|
||||
#### 2.2.1 Downloading manifests
|
||||
|
||||
When WinGet or other package managers download a package, they should also download the corresponding keyboard shortcuts manifest file and save it in the local directory, given such a file exists in the WinGet repository.
|
||||
|
||||
The downloader is also responsible for updating the local `index.yaml` file, which contains all the information about the different manifest files that are saved in the same directory.
|
||||
|
||||
#### 2.2.2 Updating manifests
|
||||
|
||||
When a manifest interpreter starts, it should download the latest version of the manifests from the WinGet repository and save them in the local directory. If a manifest interpreter is not able to download the manifests or they do not exist, it should use the locally saved manifests.
|
||||
|
||||
The updater is also responsible for updating the local `index.yaml` file, which contains all the information about the different manifest files that are saved in the same directory.
|
||||
|
||||
> Note: WinGet must provide a way to update the keyboard shortcuts manifests given a package id.
|
||||
|
||||
### 2.3 File names
|
||||
|
||||
The file name of a keyboard shortcuts file is the WinGet package identifier, plus the locale of the strings of the file and at last the `.KBSC.yaml` file extension.
|
||||
|
||||
For example the package "test.bar" saves its manifest with `en-US` strings in `test.bar.en-US.KBSC.yaml`.
|
||||
|
||||
#### 2.3.1 No winget package available
|
||||
|
||||
If an application has no corresponding WinGet package its name starts with a plus (`+`) symbol.
|
||||
|
||||
### 2.4 Reserved namespaces
|
||||
|
||||
Every name starting with `+WindowsNT` is reserved for the Windows OS and its components.
|
||||
|
||||
## 3 File syntax
|
||||
|
||||
All relevant files are written in [YAML](https://yaml.org/spec).
|
||||
|
||||
> Note: A JSON schema will be provided as soon as the spec reaches a further step
|
||||
|
||||
### 3.1 Manifest Schema vNext Keyboard Shortcuts File
|
||||
|
||||
```
|
||||
PackageName: # The package unique identifier
|
||||
WindowFilter: # The filter of window processes to which the shortcuts apply to
|
||||
BackgroundProcess: # Optionally allows applying WindowFilter to background processes
|
||||
Shortcuts: # List of sections with keyboard shortcuts
|
||||
- SectionName: # Name of the category of shortcuts
|
||||
Properties: # List of shortcuts in the category
|
||||
- Name: # Name of the shortcut
|
||||
Description: # Optional description of the shortcut
|
||||
AdditionalInfo: # Optional additional information about the shortcut
|
||||
Recommended: # Optionally determines if the shortcut is displayed in a designated recommended area
|
||||
Shortcut: # An array of shortcuts that need to be pressed
|
||||
- Win: # Determines if the Windows Key is part of the shortcut
|
||||
Ctrl: # Determines if the Ctrl Key is part of the shortcut
|
||||
Shift: # Determines if the Shift Key is part of the shortcut
|
||||
Alt: # Determines if the Alt Key is part of the shortcut
|
||||
Keys: # Array of keys that need to be pressed
|
||||
```
|
||||
|
||||
Per Application/Package one or more Keyboard manifests can be declared. Every manifest must have a different locale and the same `PackageName`, `WindowFilter` and `BackgroundProcess` fields.
|
||||
|
||||
<details>
|
||||
<summary><b>PackageName</b> - The package unique identifier</summary>
|
||||
|
||||
Package identifier (see 2.1 for more information on the package identifier).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>WindowFilter</b> - The filter of window processes to which the shortcuts apply to</summary>
|
||||
|
||||
This field declares for which process name the shortcuts should be showed (To rephrase: For which processes the shortcut will have an effect if pressed). You can use an asterisk to leave out a certain part. For example `*.PowerToys.*.exe` targets all PowerToys processes and `*` apply to any process.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>BackgroundProcess</b> - Optionally allows applying WindowFilter to background processes.</summary>
|
||||
|
||||
**Optional field**
|
||||
|
||||
Defaults to `False`. Determines if WindowFilter should apply to background processes as well (Rephrased: When the process is running, the shortcuts will apply).
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Shortcuts</b> - List of sections with keyboard shortcuts</summary>
|
||||
|
||||
List of different section (also called categories) of shortcuts.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>SectionName</b> - Name of the category of shortcuts</summary>
|
||||
|
||||
Name of the section of shortcuts.
|
||||
|
||||
**Special sections**:
|
||||
|
||||
Special sections start with an identifier enclosed between `<` and `>`. This declares the category as a special display. If the interpreter of the manifest file can't understand the content this section should be left out.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Properties</b> - List of shortcuts in the category</summary>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Name</b> - Name of the shortcut</summary>
|
||||
|
||||
Name of the shortcut. This is the name that will be displayed in the interpreter.
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Description</b> - Optional description of the shortcut</summary>
|
||||
|
||||
Optional description of the shortcut. This is the description that will be displayed by the interpreter.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>AdditionalInfo</b> - Optional additional information about the shortcut</summary>
|
||||
|
||||
Array of additional information about the shortcut. This is the additional information that will be displayed by the interpreter and are not part of this manifest.
|
||||
|
||||
**Example**:
|
||||
|
||||
For example, if the shortcut is only available on a certain Windows version, this information could be added here.
|
||||
```yaml
|
||||
AdditionalInfo:
|
||||
- MinWindowsVersion: "10.0.19041.0"
|
||||
```
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Shortcut</b> - An array of shortcuts that need to be pressed</summary>
|
||||
|
||||
An array of shortcuts that need to be pressed. This allows defining sequential shortcuts that need to be pressed in order to trigger the action.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Win</b> - Determines if the Windows Key is part of the shortcut</summary>
|
||||
|
||||
Refers to the left Windows Key on the keyboard.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Ctrl</b> - Determines if the Ctrl Key is part of the shortcut</summary>
|
||||
|
||||
Refers to the left Ctrl Key on the keyboard.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Shift</b> - Determines if the Shift Key is part of the shortcut</summary>
|
||||
|
||||
Refers to the left Shift Key on the keyboard.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Alt</b> - Determines if the Alt Key is part of the shortcut</summary>
|
||||
|
||||
Refers to the left Alt Key on the keyboard.
|
||||
</details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary><b>Recommended</b> - Optionally determines if the shortcut is displayed in a designated recommended area</summary>
|
||||
|
||||
**Optional field**
|
||||
|
||||
Defaults to `False`. Determines if the shortcut should be displayed in a designated recommended area. This is a visual hint for the user that this shortcut is important.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Keys</b> - Array of keys that need to be pressed</summary>
|
||||
|
||||
A string array of all the keys that need to be pressed. If a number is supplied, it should be read as a [KeyCode](https://learn.microsoft.com/windows/win32/inputdev/virtual-key-codes) and displayed accordingly (based on the Keyboard Layout of the user).
|
||||
|
||||
**Special keys**:
|
||||
|
||||
Special keys are enclosed between `<` and `>` and correspond to a key that should be displayed in a certain way. If the interpreter of the manifest file can't understand the content, the brackets should be left out.
|
||||
|
||||
|Name|Description|
|
||||
|----|-----------|
|
||||
|`<Office>`| Corresponds to the Office key on some Windows keyboards |
|
||||
|`<Copilot>`| Corresponds to the Copilot key on some Windows keyboards |
|
||||
|`<Left>`| Corresponds to the left arrow key |
|
||||
|`<Right>`| Corresponds to the right arrow key |
|
||||
|`<Up>`| Corresponds to the up arrow key |
|
||||
|`<Down>`| Corresponds to the down arrow key |
|
||||
|`<Enter>`| Corresponds to the Enter key |
|
||||
|`<Space>`| Corresponds to the Space key |
|
||||
|`<Tab>`| Corresponds to the Tab key |
|
||||
|`<Backspace>`| Corresponds to the Backspace key |
|
||||
|`<Delete>`| Corresponds to the Delete key |
|
||||
|`<Insert>`| Corresponds to the Insert key |
|
||||
|`<Home>`| Corresponds to the Home key |
|
||||
|`<End>`| Corresponds to the End key |
|
||||
|`<PrtScr>`| Corresponds to the Print Screen key |
|
||||
|`<Pause>`| Corresponds to the pause key |
|
||||
|`<PageUp>`| Corresponds to the Page Up key |
|
||||
|`<PageDown>`| Corresponds to the Page Down key |
|
||||
|`<Escape>`| Corresponds to the Escape key |
|
||||
|`<Arrow>`| Corresponds to either the left, right, up or down arrow key |
|
||||
|`<ArrowLR>`| Corresponds to either the left or right arrow key |
|
||||
|`<ArrowUD>`| Corresponds to either the up or down arrow key |
|
||||
|`<Underlined letter>`| Corresponds to any letter that is _underlined_ in the UI |
|
||||
|
||||
</details>
|
||||
|
||||
#### 3.2.2 Example
|
||||
|
||||
```yaml
|
||||
PackageName: Microsoft.PowerToys
|
||||
WindowFilter: "*"
|
||||
BackgroundProcess: True
|
||||
Shortcuts:
|
||||
- SectionName: General
|
||||
Properties:
|
||||
- Name: Advanced Paste
|
||||
Shortcut:
|
||||
- Win: True
|
||||
Ctrl: False
|
||||
Alt: False
|
||||
Shift: False
|
||||
Keys:
|
||||
- 86
|
||||
Description: Open Advanced Paste window
|
||||
- Name: Advanced Paste
|
||||
Shortcut:
|
||||
- Win: True
|
||||
Ctrl: True
|
||||
Alt: True
|
||||
Shift: False
|
||||
Keys:
|
||||
- 86
|
||||
Description: Paste as plain text directly
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 3.2 `index.yaml` file
|
||||
|
||||
The `index.yaml` file is a file that contains all the information about the different manifest files that are saved in the same directory. This file is only available locally and is not saved in the WinGet repository as it is specific to the user.
|
||||
|
||||
```yaml
|
||||
DefaultShellName: # The package identifier of the default shell used in Windows
|
||||
Index: # List of all manifest files
|
||||
- WindowFilter: # The filter of window processes to which the shortcuts apply to
|
||||
BackgroundProcess: # Optionally allows applying WindowFilter to background processes
|
||||
Apps: # List of all manifest files for the filter
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary><b>DefaultShellName</b> - The package identifier of the default shell used in Windows</summary>
|
||||
|
||||
This declares the package identifier of the default shell used in Windows. Most commonly it is `+WindowsNT.Shell`. Although not enforced, only the shell declared in the registry key `HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\Shell` should be used here.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Index</b> - List of all manifest files</summary>
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>WindowFilter</b> - The filter of window processes to which the shortcuts apply to</summary>
|
||||
|
||||
See the `WindowFilter` field in the manifest file for more information.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>BackgroundProcess</b> - Optionally allows applying WindowFilter to background processes</summary>
|
||||
|
||||
**Optional field**
|
||||
|
||||
See the `BackgroundProcess` field in the manifest file for more information.
|
||||
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary><b>Apps</b> - List of all the package identifiers applying for the filter</summary>
|
||||
</details>
|
||||
|
||||
#### 3.2.1 Example
|
||||
|
||||
```yaml
|
||||
DefaultShellName: "+WindowsNT.Shell"
|
||||
Index:
|
||||
- Filter: "*"
|
||||
BackgroundProcess: True
|
||||
Apps: ["+WindowsNT.Shell", "Microsoft.PowerToys"]
|
||||
- Filter: "explorer.exe"
|
||||
Apps: ["+WindowsNT.WindowsExplorer"]
|
||||
- Filter: "taskmgr.exe"
|
||||
Apps: ["+WindowsNT.TaskManager"]
|
||||
- Filter: "msedge.exe"
|
||||
Apps: ["+WindowsNT.Edge"]
|
||||
```
|
||||
@@ -2,26 +2,25 @@
|
||||
|
||||
<?include $(sys.CURRENTDIR)\Common.wxi?>
|
||||
|
||||
<?define ShortcutGuideSvgFiles=?>
|
||||
<?define ShortcutGuideSvgFilesPath=$(var.BinDir)\Assets\ShortcutGuide\?>
|
||||
<?define ShortcutGuideAssetsFiles=?>
|
||||
<?define ShortcutGuideAssetsFilesPath=$(var.BinDir)WinUI3Apps\Assets\ShortcutGuide\?>
|
||||
|
||||
<Fragment>
|
||||
<!-- Shortcut guide files -->
|
||||
<DirectoryRef Id="BaseApplicationsAssetsFolder">
|
||||
<Directory Id="ShortcutGuideSvgsInstallFolder" Name="ShortcutGuide" />
|
||||
<DirectoryRef Id="WinUI3AppsAssetsFolder">
|
||||
<Directory Id="ShortcutGuideAssetsFolder" Name="ShortcutGuide" />
|
||||
</DirectoryRef>
|
||||
<DirectoryRef Id="ShortcutGuideSvgsInstallFolder" FileSource="$(var.ShortcutGuideSvgFilesPath)">
|
||||
<DirectoryRef Id="ShortcutGuideAssetsFolder" FileSource="$(var.ShortcutGuideAssetsFilesPath)">
|
||||
<!-- Generated by generateFileComponents.ps1 -->
|
||||
<!--ShortcutGuideSvgFiles_Component_Def-->
|
||||
<!--ShortcutGuideAssetsFiles_Component_Def-->
|
||||
</DirectoryRef>
|
||||
|
||||
<!-- Shortcut guide -->
|
||||
<ComponentGroup Id="ShortcutGuideComponentGroup">
|
||||
<Component Id="RemoveShortcutGuideFolder" Guid="AD1ABC55-B593-4A60-A86A-BA8C0ED493A5" Directory="ShortcutGuideSvgsInstallFolder">
|
||||
<ComponentGroup Id="ShortcutGuideComponentGroup" >
|
||||
<Component Id="RemoveShortcutGuideFolder" Guid="AD1ABC55-B593-4A60-A86A-BA8C0ED493A5" Directory="ShortcutGuideAssetsFolder" >
|
||||
<RegistryKey Root="$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
|
||||
<RegistryValue Type="string" Name="RemoveShortcutGuideFolder" Value="" KeyPath="yes" />
|
||||
<RegistryValue Type="string" Name="RemoveShortcutGuideFolder" Value="" KeyPath="yes"/>
|
||||
</RegistryKey>
|
||||
<RemoveFolder Id="RemoveFolderShortcutGuideSvgsInstallFolder" Directory="ShortcutGuideSvgsInstallFolder" On="uninstall" />
|
||||
<RemoveFolder Id="RemoveFolderShortcutGuideAssetsInstallFolder" Directory="ShortcutGuideAssetsFolder" On="uninstall"/>
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
|
||||
@@ -299,8 +299,8 @@ Generate-FileComponents -fileListName "ValueGeneratorImagesCmpFiles" -wxsFilePat
|
||||
## Plugins
|
||||
|
||||
#ShortcutGuide
|
||||
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideSvgFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\ShortcutGuide\"
|
||||
Generate-FileComponents -fileListName "ShortcutGuideSvgFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
|
||||
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideAssetsFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ShortcutGuide\"
|
||||
Generate-FileComponents -fileListName "ShortcutGuideAssetsFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -regroot $registryroot
|
||||
|
||||
#Settings
|
||||
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\"
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{2d604c07-51fc-46bb-9eb7-75aecc7f5e81}</ProjectGuid>
|
||||
<RootNamespace>ShortcutGuide.CPPProject</RootNamespace>
|
||||
<ProjectName>ShortcutGuide.CPPProject</ProjectName>
|
||||
<WindowsTargetPlatformVersion>10.0.26100.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>17.0</VCProjectVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<ProjectGuid>{c992fd2c-83b8-4941-9fc1-09730068d8ec}</ProjectGuid>
|
||||
<RootNamespace>ShortcutGuideCPPProject</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.22621.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<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|Win32'">
|
||||
<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)'=='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>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\utils;..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\utils;..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\utils;..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>..\..\..\common\utils;..\..\..;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="excluded_app.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">Create</PrecompiledHeader>
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tasklist_positions.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="excluded_app.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="tasklist_positions.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</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.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="tasklist_positions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="excluded_app.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="tasklist_positions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="excluded_app.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,39 @@
|
||||
#include "pch.h"
|
||||
#include "excluded_app.h"
|
||||
#include <string_utils.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
__declspec(dllexport) bool IsCurrentWindowExcludedFromShortcutGuide()
|
||||
{
|
||||
PowerToysSettings::PowerToyValues settings = PowerToysSettings::PowerToyValues::load_from_settings_file(L"Shortcut Guide");
|
||||
auto settingsObject = settings.get_raw_json();
|
||||
std::wstring apps = settingsObject.GetNamedObject(L"properties").GetNamedObject(L"disabled_apps").GetNamedString(L"value").c_str();
|
||||
auto excludedUppercase = apps;
|
||||
CharUpperBuffW(excludedUppercase.data(), static_cast<DWORD>(excludedUppercase.length()));
|
||||
std::wstring_view view(excludedUppercase);
|
||||
view = left_trim<wchar_t>(trim<wchar_t>(view));
|
||||
|
||||
while (!view.empty())
|
||||
{
|
||||
auto pos = (std::min)(view.find_first_of(L"\r\n"), view.length());
|
||||
m_excludedApps.emplace_back(view.substr(0, pos));
|
||||
view.remove_prefix(pos);
|
||||
view = left_trim<wchar_t>(trim<wchar_t>(view));
|
||||
}
|
||||
|
||||
if (m_excludedApps.empty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (HWND foregroundApp{ GetForegroundWindow() })
|
||||
{
|
||||
auto processPath = get_process_path(foregroundApp);
|
||||
CharUpperBuffW(processPath.data(), static_cast<DWORD>(processPath.length()));
|
||||
|
||||
return check_excluded_app(foregroundApp, processPath, m_excludedApps);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
extern "C"
|
||||
{
|
||||
std::vector<std::wstring> m_excludedApps;
|
||||
__declspec(dllexport) bool IsCurrentWindowExcludedFromShortcutGuide();
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
#pragma once
|
||||
#define NOMINMAX
|
||||
#include <vector>
|
||||
#include <winrt/base.h>
|
||||
#include <UIAutomation.h>
|
||||
#include <windows.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <Windows.h>
|
||||
#include <dxgi1_3.h>
|
||||
#include <d3d11_2.h>
|
||||
#include <d2d1_3.h>
|
||||
@@ -24,6 +26,7 @@
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/utils/excluded_apps.h>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <../SettingsAPI/settings_objects.h>
|
||||
@@ -0,0 +1,185 @@
|
||||
#include "pch.h"
|
||||
#include "tasklist_positions.h"
|
||||
|
||||
// Tried my hardest adapting this to C#, but FindWindowW didn't work properly in C#. ~Noraa Junker
|
||||
|
||||
extern "C"
|
||||
{
|
||||
HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor)
|
||||
{
|
||||
POINT pt;
|
||||
if (!GetCursorPos(&pt))
|
||||
return nullptr;
|
||||
|
||||
// Find the primary taskbar
|
||||
HWND primaryTaskbar = FindWindowW(L"Shell_TrayWnd", nullptr);
|
||||
if (primaryTaskbar)
|
||||
{
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
if (GetWindowRect(primaryTaskbar, &mi.rcMonitor))
|
||||
{
|
||||
HMONITOR primaryMonitor = MonitorFromRect(&mi.rcMonitor, MONITOR_DEFAULTTONEAREST);
|
||||
if (primaryMonitor == monitor)
|
||||
return primaryTaskbar;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the secondary taskbar(s)
|
||||
HWND secondaryTaskbar = nullptr;
|
||||
while ((secondaryTaskbar = FindWindowExW(nullptr, secondaryTaskbar, L"Shell_SecondaryTrayWnd", nullptr)) != nullptr)
|
||||
{
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
RECT rc;
|
||||
if (GetWindowRect(secondaryTaskbar, &rc))
|
||||
{
|
||||
HMONITOR taskbarMonitor = MonitorFromRect(&rc, MONITOR_DEFAULTTONEAREST);
|
||||
if (monitor == taskbarMonitor)
|
||||
return secondaryTaskbar;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void update(HMONITOR monitor)
|
||||
{
|
||||
// Get HWND of the tasklist for the monitor under the cursor
|
||||
auto taskbar_hwnd = GetTaskbarHwndForCursorMonitor(monitor);
|
||||
if (!taskbar_hwnd)
|
||||
return;
|
||||
|
||||
wchar_t class_name[64] = {};
|
||||
GetClassNameW(taskbar_hwnd, class_name, 64);
|
||||
|
||||
HWND tasklist_hwnd = nullptr;
|
||||
|
||||
if (wcscmp(class_name, L"Shell_TrayWnd") == 0)
|
||||
{
|
||||
// Primary taskbar structure
|
||||
tasklist_hwnd = FindWindowExW(taskbar_hwnd, 0, L"ReBarWindow32", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskSwWClass", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
tasklist_hwnd = FindWindowExW(tasklist_hwnd, 0, L"MSTaskListWClass", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
}
|
||||
else if (wcscmp(class_name, L"Shell_SecondaryTrayWnd") == 0)
|
||||
{
|
||||
// Secondary taskbar structure
|
||||
HWND worker_hwnd = FindWindowExW(taskbar_hwnd, 0, L"WorkerW", nullptr);
|
||||
if (!worker_hwnd)
|
||||
return;
|
||||
tasklist_hwnd = FindWindowExW(worker_hwnd, 0, L"MSTaskListWClass", nullptr);
|
||||
if (!tasklist_hwnd)
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unknown taskbar type
|
||||
return;
|
||||
}
|
||||
|
||||
if (!automation)
|
||||
{
|
||||
winrt::check_hresult(CoCreateInstance(CLSID_CUIAutomation,
|
||||
nullptr,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_IUIAutomation,
|
||||
automation.put_void()));
|
||||
winrt::check_hresult(automation->CreateTrueCondition(true_condition.put()));
|
||||
}
|
||||
element = nullptr;
|
||||
winrt::check_hresult(automation->ElementFromHandle(tasklist_hwnd, element.put()));
|
||||
}
|
||||
|
||||
bool update_buttons(std::vector<TasklistButton>& buttons)
|
||||
{
|
||||
if (!automation || !element)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
winrt::com_ptr<IUIAutomationElementArray> elements;
|
||||
if (element->FindAll(TreeScope_Children, true_condition.get(), elements.put()) < 0)
|
||||
return false;
|
||||
if (!elements)
|
||||
return false;
|
||||
int count;
|
||||
if (elements->get_Length(&count) < 0)
|
||||
return false;
|
||||
winrt::com_ptr<IUIAutomationElement> child;
|
||||
std::vector<TasklistButton> found_buttons;
|
||||
found_buttons.reserve(count);
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
child = nullptr;
|
||||
if (elements->GetElement(i, child.put()) < 0)
|
||||
return false;
|
||||
TasklistButton button = {};
|
||||
if (VARIANT var_rect; child->GetCurrentPropertyValue(UIA_BoundingRectanglePropertyId, &var_rect) >= 0)
|
||||
{
|
||||
if (var_rect.vt == (VT_R8 | VT_ARRAY))
|
||||
{
|
||||
LONG pos;
|
||||
double value;
|
||||
pos = 0;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.x = static_cast<long>(value);
|
||||
pos = 1;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.y = static_cast<long>(value);
|
||||
pos = 2;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.width = static_cast<long>(value);
|
||||
pos = 3;
|
||||
SafeArrayGetElement(var_rect.parray, &pos, &value);
|
||||
button.height = static_cast<long>(value);
|
||||
}
|
||||
VariantClear(&var_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (BSTR automation_id; child->get_CurrentAutomationId(&automation_id) >= 0)
|
||||
{
|
||||
wcsncpy_s(button.name, automation_id, _countof(button.name));
|
||||
SysFreeString(automation_id);
|
||||
}
|
||||
found_buttons.push_back(button);
|
||||
}
|
||||
// assign keynums
|
||||
buttons.clear();
|
||||
for (auto& button : found_buttons)
|
||||
{
|
||||
if (buttons.empty())
|
||||
{
|
||||
button.keynum = 1;
|
||||
buttons.push_back(std::move(button));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (button.x < buttons.back().x || button.y < buttons.back().y) // skip 2nd row
|
||||
break;
|
||||
if (wcsncmp(button.name, buttons.back().name, _countof(button.name)) == 0)
|
||||
continue; // skip buttons from the same app
|
||||
button.keynum = buttons.back().keynum + 1;
|
||||
buttons.push_back(std::move(button));
|
||||
if (buttons.back().keynum == 10)
|
||||
break; // no more than 10 buttons
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
__declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size)
|
||||
{
|
||||
update(monitor);
|
||||
static std::vector<TasklistButton> buttons;
|
||||
update_buttons(buttons);
|
||||
*size = static_cast<int>(buttons.size());
|
||||
return buttons.data();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
struct TasklistButton
|
||||
{
|
||||
wchar_t name[256];
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int keynum;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
winrt::com_ptr<IUIAutomation> automation;
|
||||
winrt::com_ptr<IUIAutomationElement> element;
|
||||
winrt::com_ptr<IUIAutomationCondition> true_condition;
|
||||
|
||||
// Helper to get the taskbar HWND for the monitor under the cursor
|
||||
HWND GetTaskbarHwndForCursorMonitor(HMONITOR monitor);
|
||||
bool update_buttons(std::vector<TasklistButton>& buttons);
|
||||
__declspec(dllexport) TasklistButton* get_buttons(HMONITOR monitor, int* size);
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using ShortcutGuide.Helpers;
|
||||
using ShortcutGuide.Models;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
// This class should be moved to WinGet in the future
|
||||
namespace ShortcutGuide.IndexYmlGenerator
|
||||
{
|
||||
public class IndexYmlGenerator
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
CreateIndexYmlFile();
|
||||
}
|
||||
|
||||
// Todo: Exception handling
|
||||
public static void CreateIndexYmlFile()
|
||||
{
|
||||
string path = ManifestInterpreter.PathOfManifestFiles;
|
||||
if (File.Exists(Path.Combine(path, "index.yml")))
|
||||
{
|
||||
File.Delete(Path.Combine(path, "index.yml"));
|
||||
}
|
||||
|
||||
IndexFile indexFile = new() { };
|
||||
Dictionary<(string WindowFilter, bool BackgroundProcess), List<string>> processes = [];
|
||||
|
||||
foreach (string file in Directory.EnumerateFiles(path, "*.yml"))
|
||||
{
|
||||
string content = File.ReadAllText(file);
|
||||
Deserializer deserializer = new();
|
||||
ShortcutFile shortcutFile = deserializer.Deserialize<ShortcutFile>(content);
|
||||
if (processes.TryGetValue((shortcutFile.WindowFilter, shortcutFile.BackgroundProcess), out List<string>? apps))
|
||||
{
|
||||
if (apps.Contains(shortcutFile.PackageName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
apps.Add(shortcutFile.PackageName);
|
||||
continue;
|
||||
}
|
||||
|
||||
processes[(shortcutFile.WindowFilter, shortcutFile.BackgroundProcess)] = [shortcutFile.PackageName];
|
||||
}
|
||||
|
||||
indexFile.Index = [];
|
||||
|
||||
foreach (var item in processes)
|
||||
{
|
||||
indexFile.Index =
|
||||
[
|
||||
.. indexFile.Index,
|
||||
new IndexFile.IndexItem
|
||||
{
|
||||
WindowFilter = item.Key.WindowFilter,
|
||||
BackgroundProcess = item.Key.BackgroundProcess,
|
||||
Apps = [.. item.Value],
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
// Todo: Take the default shell name from the settings or environment variable, default to "+WindowsNT.Shell"
|
||||
indexFile.DefaultShellName = "+WindowsNT.Shell";
|
||||
|
||||
Serializer serializer = new();
|
||||
string yamlContent = serializer.Serialize(indexFile);
|
||||
File.WriteAllText(Path.Combine(path, "index.yml"), yamlContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\..\..\Common.SelfContained.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>ShortcutGuide.IndexYmlGenerator</RootNamespace>
|
||||
<Nullable>enable</Nullable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
|
||||
<AssemblyName>PowerToys.ShortcutGuide.IndexYmlGenerator</AssemblyName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YamlDotNet" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\ShortcutGuide.Ui\ShortcutGuide.Ui.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,247 @@
|
||||
PackageName: +WindowsNT.Notepad
|
||||
Name: Notepad
|
||||
WindowFilter: "Notepad.exe"
|
||||
BackgroundProcess: false
|
||||
Shortcuts:
|
||||
- SectionName: File
|
||||
Properties:
|
||||
- Name: New tab
|
||||
Recommended: true
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- N
|
||||
- Name: New window
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- N
|
||||
- Name: Open
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- O
|
||||
- Name: Save
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- S
|
||||
- Name: Save As
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- S
|
||||
- Name: Save all
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- S
|
||||
- Name: Print
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- P
|
||||
- Name: Close tab
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- W
|
||||
- Name: Close window
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- W
|
||||
- SectionName: Edit
|
||||
Properties:
|
||||
- Name: Undo
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- Z
|
||||
- Name: Redo
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- Z
|
||||
- Name: Cut
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- X
|
||||
- Name: Copy
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- C
|
||||
- Name: Paste
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- V
|
||||
- Name: Search with Bing
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- E
|
||||
- Name: Find
|
||||
Recommended: true
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- F
|
||||
- Name: Find next
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- F3
|
||||
- Name: Find previous
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- F3
|
||||
- Name: Replace
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- H
|
||||
- Name: Go to
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- G
|
||||
- Name: Select all
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- A
|
||||
- Name: Time/Date
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- F5
|
||||
- SectionName: View
|
||||
Properties:
|
||||
- Name: Zoom in
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- Plus
|
||||
- Name: Zoom out
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- Minus
|
||||
- Name: Reset zoom
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- 0
|
||||
- SectionName: Formatting
|
||||
Properties:
|
||||
- Name: Bold
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- B
|
||||
- Name: Italic
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- I
|
||||
- Name: Insert link
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- K
|
||||
- Name: Clear formatting
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- Space
|
||||
@@ -0,0 +1,773 @@
|
||||
PackageName: +WindowsNT.Shell
|
||||
WindowFilter: "*"
|
||||
BackgroundProcess: true
|
||||
Shortcuts:
|
||||
- SectionName: Desktop Shortcuts
|
||||
Properties:
|
||||
- Name: Close active window
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- F4
|
||||
- Name: Open shutdown box
|
||||
Description: When no windows are open
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- F4
|
||||
- Name: Cycle through open Windows
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- Esc
|
||||
- Name: Reveal typed password
|
||||
Description: On sign-in screen
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- F8
|
||||
- Name: Go back
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "<Left>"
|
||||
- Name: Go forward
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "<Right>"
|
||||
- Name: Move up one screen
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "<Page Up>"
|
||||
- Name: Move down one screen
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "<Page Down>"
|
||||
- Name: Window context menu
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- Space
|
||||
- Name: Switch between open apps
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- Tab
|
||||
Description: While pressing Tab multiple times
|
||||
- Name: Run command
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "<Underlined letter>"
|
||||
Description: for the underlined letter in the app
|
||||
- Name: View open apps
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- Tab
|
||||
- Name: Change start menu size
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Arrow>"
|
||||
- Name: Move cursor
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<ArrowLR>"
|
||||
Description: To the beginning or end of a word
|
||||
- Name: Switch keyboard layout
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- ""
|
||||
- Name: Select block of text
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Arrow>"
|
||||
- Name: Open Task Manager
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- Esc
|
||||
- Name: Enable/Disable Chinese IME
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- Space
|
||||
- Name: Open context menu
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- F10
|
||||
Description: For the selected item
|
||||
- SectionName: Virtual desktop
|
||||
Properties:
|
||||
- Name: Open task view
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- Tab
|
||||
- Name: Add a virtual desktop
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- D
|
||||
- Name: Close current desktop
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- F4
|
||||
- Name: Switch desktop
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<ArrowLR>"
|
||||
Recommended: true
|
||||
- SectionName: "Windows key"
|
||||
Properties:
|
||||
- Name: Open start menu
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- ""
|
||||
- Name: Open Action Center
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "A"
|
||||
- Name: Open Date and Time
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "D"
|
||||
- Name: Focus on the notification area
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "B"
|
||||
- Name: Open narrator
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Enter"
|
||||
- Name: Open domain search
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "F"
|
||||
- Name: Open Quick Assist
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Q"
|
||||
- Name: Wake up device
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "B"
|
||||
Description: When black or a blank screen.
|
||||
- Name: Change input option
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Space"
|
||||
Description: To next option
|
||||
- Name: Change input option
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Space"
|
||||
Description: To previous option
|
||||
- Name: Display/Hide desktop
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "D"
|
||||
- Name: Minimize the active window
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Down"
|
||||
Recommended: true
|
||||
- Name: Open file Explorer
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "E"
|
||||
- Name: Close Magnifier
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Esc"
|
||||
- Name: Open Feedback Hub
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "F"
|
||||
Recommended: true
|
||||
- Name: Start IME reconversion
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "/"
|
||||
- Name: Open Game Bar
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "G"
|
||||
- Name: Open voice dictation
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "H"
|
||||
- Name: Minimize or restore all other windows
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Home>"
|
||||
- Name: Open Settings
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "I"
|
||||
- Name: Set focus to a Windows tip
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "J"
|
||||
- Name: Open Cast
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "K"
|
||||
- Name: Lock the device
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "L"
|
||||
- Name: Snap the window
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<ArrowLR>"
|
||||
- Name: Minimize all windows
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "M"
|
||||
- Name: Zoom out Magnifier
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "-"
|
||||
- Name: Zoom in Magnifier
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "="
|
||||
- Name: Open notification center
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "N"
|
||||
- Name: Lock the device orientation
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "O"
|
||||
- Name: Open project Settings
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "P"
|
||||
- Name: Open Settings about Page
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Pause>"
|
||||
- Name: Open the emoji panel
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "."
|
||||
- Name: Open the emoji panel
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- ";"
|
||||
- Name: Capture a screenshot
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<PrtScr>"
|
||||
Description: Save to the pictures folder
|
||||
- Name: Open search
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Q"
|
||||
- Name: Open search
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "S"
|
||||
- Name: Open Run dialog
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "R"
|
||||
- Name: Restore window
|
||||
Description: If a window is snapped or maximized
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Down>"
|
||||
- Name: Make UWP app full screen
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Up>"
|
||||
- Name: Move window to monitor
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Arrow>"
|
||||
- Name: Open Snipping Tool
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "S"
|
||||
- Name: Stretch window
|
||||
Description: To the top and bottom of the screen
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Up>"
|
||||
- Name: Open task view
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Tab"
|
||||
- Name: Open Accessibility Settings
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "U"
|
||||
- Name: Maximize the active window
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Up>"
|
||||
- Name: Open the clipboard history
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "V"
|
||||
- Name: Open widgets
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "W"
|
||||
- Name: Open Quick Link menu
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "X"
|
||||
- Name: Open snap layouts
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Z"
|
||||
- SectionName: Clipboard
|
||||
Properties:
|
||||
- Name: Copy
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "C"
|
||||
- Name: Cut
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "X"
|
||||
- Name: Paste
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "V"
|
||||
- Name: Paste
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Insert>"
|
||||
Description: Paste as plain text
|
||||
- SectionName: <TASKBAR1-9>Taskbar Shortcuts
|
||||
Properties:
|
||||
- Name: Open app in Taskbar
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<TASKBAR1-9>"
|
||||
- Name: Open jump list
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "<TASKBAR1-9>"
|
||||
- Name: Switch to last active window
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<TASKBAR1-9>"
|
||||
- Name: Open as administrator
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<TASKBAR1-9>"
|
||||
- SectionName: Copilot key
|
||||
Properties:
|
||||
- Name: Open Copilot
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- '<Copilot>'
|
||||
Description: When copilot is available
|
||||
- Name: Open Windows search
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- '<Copilot>'
|
||||
Description: When copilot is not available
|
||||
- SectionName: Office key
|
||||
Properties:
|
||||
- Name: Open Word
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Office>"
|
||||
- "W"
|
||||
- Name: Open Excel
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Office>"
|
||||
- "X"
|
||||
- Name: Open PowerPoint
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Office>"
|
||||
- "P"
|
||||
- Name: Open Outlook
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Office>"
|
||||
- "O"
|
||||
- Name: Open Microsoft Teams
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Office>"
|
||||
- "T"
|
||||
- Name: Open OneNote
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Office>"
|
||||
- "N"
|
||||
- Name: Open OneDrive
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Office>"
|
||||
- "D"
|
||||
- Name: Open Yammer
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Office>"
|
||||
- "Y"
|
||||
- Name: Open LinkedIn
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Office>"
|
||||
- "L"
|
||||
@@ -0,0 +1,266 @@
|
||||
PackageName: +WindowsNT.WindowsExplorer
|
||||
WindowFilter: "explorer.exe"
|
||||
Name: File Explorer
|
||||
Shortcuts:
|
||||
- SectionName: General
|
||||
Properties:
|
||||
- Name: Open File Explorer
|
||||
Shortcut:
|
||||
- Win: true
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "E"
|
||||
Recommended: true
|
||||
- Name: Select the address bar
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "D"
|
||||
- Name: Select the address bar
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "L"
|
||||
- Name: Select the address bar
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "F4"
|
||||
- Name: Select the search box
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "E"
|
||||
- Name: Select the search box
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "F3"
|
||||
- Name: Select the search box
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "F"
|
||||
- Name: Refresh the window
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "F5"
|
||||
- Name: Cycle through elements in the active window
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "F6"
|
||||
- Name: Maximize or restore the active window
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "F11"
|
||||
- SectionName: Navigation
|
||||
Properties:
|
||||
- Name: Navigate to the previous folder
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "<Left>"
|
||||
- Name: Navigate to the previous folder
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Backspace>"
|
||||
- Name: Navigate to the next folder
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "<Right>"
|
||||
- Name: Move up a level in the folder path
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "<Up>"
|
||||
- SectionName: "Window management"
|
||||
Properties:
|
||||
- Name: Open a new window
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "N"
|
||||
- Name: Open a new tab
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "T"
|
||||
Recommended: true
|
||||
- Name: Close the current active tab
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "W"
|
||||
- Name: Move to the next tab
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Tab"
|
||||
- Name: Move to the previous tab
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Tab"
|
||||
- Name: Move to that tab number
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "Number (1-9)"
|
||||
- Name: Show/Hide the preview pane
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "P"
|
||||
- Name: Show/Hide the details pane
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: true
|
||||
Alt: true
|
||||
Keys:
|
||||
- "P"
|
||||
- Name: Resize all columns to fit text
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "+"
|
||||
- Name: Expand all folders
|
||||
Description: In the navigation pane
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "E"
|
||||
- SectionName: "File management"
|
||||
Properties:
|
||||
- Name: Display properties for the selected item
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: true
|
||||
Keys:
|
||||
- "Enter"
|
||||
- Name: Delete the selected item
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Delete>"
|
||||
- Name: Delete the selected item
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "D"
|
||||
- Name: Delete the selected item permanently
|
||||
Description: "This removes the item without sending it to the Recycle Bin"
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "D"
|
||||
- Name: Create a new folder
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: true
|
||||
Alt: false
|
||||
Keys:
|
||||
- "N"
|
||||
Recommended: true
|
||||
- Name: Rename the selected item
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: false
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "F2"
|
||||
- Name: Select multiple items
|
||||
Shortcut:
|
||||
- Win: false
|
||||
Ctrl: true
|
||||
Shift: false
|
||||
Alt: false
|
||||
Keys:
|
||||
- "<Arrow>"
|
||||
|
||||
|
After Width: | Height: | Size: 412 B |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 53 KiB |
@@ -0,0 +1,9 @@
|
||||
PackageName: Microsoft.PowerToys
|
||||
Name: PowerToys
|
||||
BackgroundProcess: True
|
||||
WindowFilter: "powertoys.exe"
|
||||
Shortcuts:
|
||||
- SectionName: General
|
||||
Properties:
|
||||
# <Populate start>
|
||||
# <Populate end>
|
||||
|
After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,100 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Documents;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using ShortcutGuide.Models;
|
||||
using Windows.System;
|
||||
|
||||
namespace ShortcutGuide.Converters
|
||||
{
|
||||
public sealed partial class ShortcutDescriptionToKeysConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is ShortcutDescription description)
|
||||
{
|
||||
// Populate keysList with the keys from the ShortcutDescription
|
||||
return GetKeysList(description);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<object> keysList = [string.Empty];
|
||||
return keysList;
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
public List<object> GetKeysList(ShortcutDescription description)
|
||||
{
|
||||
List<object> shortcutList = [];
|
||||
|
||||
if (description.Win)
|
||||
{
|
||||
shortcutList.Add(92); // The Windows key or button.
|
||||
}
|
||||
|
||||
if (description.Ctrl)
|
||||
{
|
||||
shortcutList.Add("Ctrl");
|
||||
}
|
||||
|
||||
if (description.Alt)
|
||||
{
|
||||
shortcutList.Add("Alt");
|
||||
}
|
||||
|
||||
if (description.Shift)
|
||||
{
|
||||
shortcutList.Add(16); // The Shift key or button.
|
||||
}
|
||||
|
||||
foreach (var key in description.Keys)
|
||||
{
|
||||
// Try to parse a string key number to a VirtualKey
|
||||
if (int.TryParse(key, out int keyCode))
|
||||
{
|
||||
shortcutList.Add(keyCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
// https://learn.microsoft.com/uwp/api/windows.system.virtualkey?view=winrt-20348
|
||||
case "Up":
|
||||
shortcutList.Add(38); // The Up Arrow key or button.
|
||||
break;
|
||||
case "Down":
|
||||
shortcutList.Add(40); // The Down Arrow key or button.
|
||||
break;
|
||||
case "Left":
|
||||
shortcutList.Add(37); // The Left Arrow key or button.
|
||||
break;
|
||||
case "Right":
|
||||
shortcutList.Add(39); // The Right Arrow key or button.
|
||||
break;
|
||||
case "Back":
|
||||
shortcutList.Add(8); // The Back key or button.
|
||||
break;
|
||||
case "<TASKBAR1-9>":
|
||||
shortcutList.Add("Num");
|
||||
break;
|
||||
default:
|
||||
shortcutList.Add(key); // Add other keys as strings.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return shortcutList;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Windows.Foundation;
|
||||
using WinUIEx;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
public static class DisplayHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the display work area for the monitor that contains the specified window.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle</param>
|
||||
/// <returns>A <see cref="Rect"/> element containing the display area</returns>
|
||||
public static Rect GetWorkAreaForDisplayWithWindow(nint hwnd)
|
||||
{
|
||||
_foundMonitorIndex = -1;
|
||||
_monitorIndex = 0;
|
||||
var monitor = NativeMethods.MonitorFromWindow(hwnd, (int)NativeMethods.MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST);
|
||||
NativeMethods.EnumDisplayMonitors(nint.Zero, nint.Zero, MonitorEnumProc, new NativeMethods.LPARAM(monitor));
|
||||
return MonitorInfo.GetDisplayMonitors()[_foundMonitorIndex].RectWork;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The index of the monitor that contains the specified window. -1 indicates that no monitor was found (yet).
|
||||
/// </summary>
|
||||
private static int _foundMonitorIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the monitor in the enumeration. This is used to find the correct monitor in the list of monitors.
|
||||
/// </summary>
|
||||
private static int _monitorIndex;
|
||||
|
||||
private static bool MonitorEnumProc(nint hMonitor, nint hdcMonitor, ref NativeMethods.RECT lprcMonitor, nint dwData)
|
||||
{
|
||||
nint targetMonitor = dwData;
|
||||
|
||||
if (hMonitor == targetMonitor)
|
||||
{
|
||||
_foundMonitorIndex = _monitorIndex;
|
||||
return false;
|
||||
}
|
||||
|
||||
_monitorIndex++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
// This class is rewritten from C++ to C# from the measure tool project
|
||||
internal static class DpiHelper
|
||||
{
|
||||
#pragma warning disable SA1310 // Field names should not contain underscore
|
||||
private const int DEFAULT_DPI = 96;
|
||||
private const int MONITOR_DEFAULTTONEAREST = 2;
|
||||
private const int MDT_EFFECTIVE_DPI = 0;
|
||||
#pragma warning restore SA1310 // Field names should not contain underscore
|
||||
|
||||
public static float GetDPIScaleForWindow(int hwnd)
|
||||
{
|
||||
int dpi = DEFAULT_DPI;
|
||||
GetScreenDPIForWindow(hwnd, ref dpi);
|
||||
return (float)dpi / DEFAULT_DPI;
|
||||
}
|
||||
|
||||
private static long GetScreenDPIForWindow(int hwnd, ref int dpi)
|
||||
{
|
||||
var targetMonitor = NativeMethods.MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
return GetScreenDPIForMonitor(targetMonitor.ToInt32(), ref dpi);
|
||||
}
|
||||
|
||||
private static long GetScreenDPIForMonitor(int targetMonitor, ref int dpi)
|
||||
{
|
||||
if (targetMonitor != 0)
|
||||
{
|
||||
int dummy = 0;
|
||||
return NativeMethods.GetDpiForMonitor(targetMonitor, MDT_EFFECTIVE_DPI, ref dpi, ref dummy);
|
||||
}
|
||||
else
|
||||
{
|
||||
dpi = DEFAULT_DPI;
|
||||
return 0x80004005L;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using ShortcutGuide.Models;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Helps to interpret the manifest files for the Shortcut Guide.
|
||||
/// </summary>
|
||||
public class ManifestInterpreter
|
||||
{
|
||||
// Todo: Get language from settings or environment variable, default to "en-US"
|
||||
|
||||
/// <summary>
|
||||
/// Gets the language used for the manifest files.
|
||||
/// </summary>
|
||||
public static string Language => "en-US";
|
||||
|
||||
/// <summary>
|
||||
/// Returns the shortcuts for a specific application.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The method should only be called if the application is known to have a shortcuts file.
|
||||
/// </remarks>
|
||||
/// <param name="applicationName">The manifest id.</param>
|
||||
/// <returns>The deserialized shortcuts file.</returns>
|
||||
/// <exception cref="FileNotFoundException">The requested file was not found.</exception>
|
||||
public static ShortcutFile GetShortcutsOfApplication(string applicationName)
|
||||
{
|
||||
string path = PathOfManifestFiles;
|
||||
IEnumerable<string> files = Directory.EnumerateFiles(path, applicationName + ".*.yml") ??
|
||||
throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}'.");
|
||||
|
||||
IEnumerable<string> filesEnumerable = files as string[] ?? [.. files];
|
||||
return filesEnumerable.Any(f => f.EndsWith($".{Language}.yml", StringComparison.InvariantCulture))
|
||||
? YamlToShortcutList(File.ReadAllText(Path.Combine(path, applicationName + $".{Language}.yml")))
|
||||
: filesEnumerable.Any(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture))
|
||||
? YamlToShortcutList(File.ReadAllText(filesEnumerable.First(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture))))
|
||||
: throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}' with the language '{Language}' or 'en-US'.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the content of a YAML file to a <see cref="ShortcutFile"/>.
|
||||
/// </summary>
|
||||
/// <param name="content">The content of the YAML file.</param>
|
||||
/// <returns>A deserialized <see cref="ShortcutFile"/> object.</returns>
|
||||
private static ShortcutFile YamlToShortcutList(string content)
|
||||
{
|
||||
Deserializer deserializer = new();
|
||||
return deserializer.Deserialize<ShortcutFile>(content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path to the directory where the manifest files are stored.
|
||||
/// </summary>
|
||||
public static string PathOfManifestFiles => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "WinGet", "KeyboardShortcuts");
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the index YAML file that contains the list of all applications and their shortcuts.
|
||||
/// </summary>
|
||||
/// <returns>A deserialized <see cref="IndexFile"/> object.</returns>
|
||||
public static IndexFile GetIndexYamlFile()
|
||||
{
|
||||
string path = PathOfManifestFiles;
|
||||
string content = File.ReadAllText(Path.Combine(path, "index.yml"));
|
||||
Deserializer deserializer = new();
|
||||
return deserializer.Deserialize<IndexFile>(content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all application IDs that should be displayed, based on the foreground window and background processes.
|
||||
/// </summary>
|
||||
/// <returns>An array of all application IDs.</returns>
|
||||
public static string[] GetAllCurrentApplicationIds()
|
||||
{
|
||||
nint handle = NativeMethods.GetForegroundWindow();
|
||||
|
||||
List<string> applicationIds = [];
|
||||
|
||||
Process[] processes = Process.GetProcesses();
|
||||
|
||||
if (NativeMethods.GetWindowThreadProcessId(handle, out uint processId) > 0)
|
||||
{
|
||||
string? name = Process.GetProcessById((int)processId).MainModule?.ModuleName;
|
||||
|
||||
if (name is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var item in GetIndexYamlFile().Index.First((s) => !s.BackgroundProcess && IsMatch(name, s.WindowFilter)).Apps)
|
||||
{
|
||||
applicationIds.Add(item);
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var item in GetIndexYamlFile().Index.Where((s) => s.BackgroundProcess))
|
||||
{
|
||||
try
|
||||
{
|
||||
if (processes.Any((p) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return IsMatch(p.MainModule!.ModuleName, item.WindowFilter);
|
||||
}
|
||||
catch (Win32Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}))
|
||||
{
|
||||
foreach (var app in item.Apps)
|
||||
{
|
||||
applicationIds.Add(app);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
return [.. applicationIds];
|
||||
|
||||
static bool IsMatch(string input, string filter)
|
||||
{
|
||||
input = input.ToLower(CultureInfo.InvariantCulture);
|
||||
filter = filter.ToLower(CultureInfo.InvariantCulture);
|
||||
string regexPattern = "^" + Regex.Escape(filter).Replace("\\*", ".*") + "$";
|
||||
return Regex.IsMatch(input, regexPattern);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
namespace ShortcutGuide.Helpers;
|
||||
|
||||
internal static class NavItemIconHelper
|
||||
{
|
||||
public static object GetSelectedIcon(DependencyObject obj)
|
||||
{
|
||||
return obj.GetValue(SelectedIconProperty);
|
||||
}
|
||||
|
||||
public static void SetSelectedIcon(DependencyObject obj, object value)
|
||||
{
|
||||
obj.SetValue(SelectedIconProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SelectedIconProperty =
|
||||
DependencyProperty.RegisterAttached("SelectedIcon", typeof(object), typeof(NavItemIconHelper), new PropertyMetadata(null));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of <see cref="ShowNotificationDotProperty" /> for a <see cref="DependencyObject" />
|
||||
/// </summary>
|
||||
/// <returns>Returns a boolean indicating whether the notification dot should be shown.</returns>
|
||||
public static bool GetShowNotificationDot(DependencyObject obj)
|
||||
{
|
||||
return (bool)obj.GetValue(ShowNotificationDotProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets <see cref="ShowNotificationDotProperty" /> on a <see cref="DependencyObject" />
|
||||
/// </summary>
|
||||
public static void SetShowNotificationDot(DependencyObject obj, bool value)
|
||||
{
|
||||
obj.SetValue(ShowNotificationDotProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An attached property that sets whether or not a notification dot should be shown on an associated <see cref="Microsoft.UI.Xaml.Controls.NavigationViewItem" />
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty ShowNotificationDotProperty =
|
||||
DependencyProperty.RegisterAttached("ShowNotificationDot", typeof(bool), typeof(NavItemIconHelper), new PropertyMetadata(false));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of <see cref="UnselectedIconProperty"/> for a <see cref="DependencyObject"/>
|
||||
/// </summary>
|
||||
/// <returns>Returns the unselected icon as an object.</returns>
|
||||
public static object GetUnselectedIcon(DependencyObject obj)
|
||||
{
|
||||
return (object)obj.GetValue(UnselectedIconProperty);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the value of <see cref="UnselectedIconProperty"/> for a <see cref="DependencyObject"/>
|
||||
/// </summary>
|
||||
public static void SetUnselectedIcon(DependencyObject obj, object value)
|
||||
{
|
||||
obj.SetValue(UnselectedIconProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An attached property that sets the unselected icon on an associated <see cref="Microsoft.UI.Xaml.Controls.NavigationViewItem" />
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty UnselectedIconProperty =
|
||||
DependencyProperty.RegisterAttached("UnselectedIcon", typeof(object), typeof(NavItemIconHelper), new PropertyMetadata(null));
|
||||
|
||||
public static Visibility GetStaticIconVisibility(DependencyObject obj)
|
||||
{
|
||||
return (Visibility)obj.GetValue(StaticIconVisibilityProperty);
|
||||
}
|
||||
|
||||
public static void SetStaticIconVisibility(DependencyObject obj, Visibility value)
|
||||
{
|
||||
obj.SetValue(StaticIconVisibilityProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An attached property that sets the visibility of the static icon in the associated <see cref="Microsoft.UI.Xaml.Controls.NavigationViewItem"/>.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty StaticIconVisibilityProperty =
|
||||
DependencyProperty.RegisterAttached("StaticIconVisibility", typeof(Visibility), typeof(NavItemIconHelper), new PropertyMetadata(Visibility.Collapsed));
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using ShortcutGuide.Models;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
public static class PinnedShortcutsHelper
|
||||
{
|
||||
public static void UpdatePinnedShortcuts(string appName, ShortcutEntry shortcutEntry)
|
||||
{
|
||||
if (!App.PinnedShortcuts[appName].Remove(shortcutEntry))
|
||||
{
|
||||
App.PinnedShortcuts[appName].Add(shortcutEntry);
|
||||
}
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
public static void Save()
|
||||
{
|
||||
string serialized = JsonSerializer.Serialize(App.PinnedShortcuts);
|
||||
|
||||
SettingsUtils settingsUtils = new();
|
||||
string pinnedPath = settingsUtils.GetSettingsFilePath(ShortcutGuideSettings.ModuleName, "Pinned.json");
|
||||
File.WriteAllText(pinnedPath, serialized);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using static ShortcutGuide.Helpers.ResourceLoaderInstance;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Populates the PowerToys shortcuts in the manifest files.
|
||||
/// </summary>
|
||||
internal sealed partial class PowerToysShortcutsPopulator
|
||||
{
|
||||
/// <summary>
|
||||
/// Populates the PowerToys shortcuts in the manifest files.
|
||||
/// </summary>
|
||||
public static void Populate()
|
||||
{
|
||||
string path = Path.Combine(ManifestInterpreter.PathOfManifestFiles, $"Microsoft.PowerToys.{ManifestInterpreter.Language}.yml");
|
||||
|
||||
StringBuilder content = new(File.ReadAllText(path));
|
||||
|
||||
const string populateStartString = "# <Populate start>";
|
||||
const string populateEndString = "# <Populate end>";
|
||||
|
||||
content = new(PopulateRegex().Replace(content.ToString(), populateStartString + Environment.NewLine));
|
||||
|
||||
ISettingsUtils settingsUtils = new SettingsUtils();
|
||||
EnabledModules enabledModules = SettingsRepository<GeneralSettings>.GetInstance(settingsUtils).SettingsConfig.Enabled;
|
||||
if (enabledModules.AdvancedPaste)
|
||||
{
|
||||
AdvancedPasteProperties advancedPasteProperties = SettingsRepository<AdvancedPasteSettings>.GetInstance(settingsUtils).SettingsConfig.Properties;
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdvancedPasteUIShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("AdvancedPasteUI_Shortcut/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.PasteAsPlainTextShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsPlainText_Shortcut/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.PasteAsMarkdownShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsMarkdown_Shortcut/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.PasteAsJsonShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsJson_Shortcut/Header")));
|
||||
if (advancedPasteProperties.AdditionalActions.ImageToText.IsShown)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.ImageToText.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("ImageToText/Header")));
|
||||
}
|
||||
|
||||
if (advancedPasteProperties.AdditionalActions.PasteAsFile.IsShown)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsTxtFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsTxtFile/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsPngFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsPngFile/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsHtmlFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsHtmlFile/Header")));
|
||||
}
|
||||
|
||||
if (advancedPasteProperties.AdditionalActions.Transcode.IsShown)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp3.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("TranscodeToMp3/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp4.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("TranscodeToMp4/Header")));
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledModules.AlwaysOnTop)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<AlwaysOnTopSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("AlwaysOnTop/ModuleTitle"), SettingsResourceLoader.GetString("AlwaysOnTop_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.ColorPicker)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ColorPickerSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("ColorPicker/ModuleTitle"), SettingsResourceLoader.GetString("ColorPicker_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.CmdPal)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(new CmdPalProperties().Hotkey, SettingsResourceLoader.GetString("CmdPal/ModuleTitle")));
|
||||
}
|
||||
|
||||
if (enabledModules.CropAndLock)
|
||||
{
|
||||
CropAndLockProperties cropAndLockProperties = SettingsRepository<CropAndLockSettings>.GetInstance(settingsUtils).SettingsConfig.Properties;
|
||||
content.Append(HotkeySettingsToYaml(cropAndLockProperties.ThumbnailHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), SettingsResourceLoader.GetString("CropAndLock_Thumbnail")));
|
||||
content.Append(HotkeySettingsToYaml(cropAndLockProperties.ReparentHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), SettingsResourceLoader.GetString("CropAndLock_Reparent")));
|
||||
}
|
||||
|
||||
if (enabledModules.FancyZones)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<FancyZonesSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.FancyzonesEditorHotkey, SettingsResourceLoader.GetString("FancyZones/ModuleTitle"), SettingsResourceLoader.GetString("FancyZones_OpenEditor")));
|
||||
}
|
||||
|
||||
if (enabledModules.MouseHighlighter)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<MouseHighlighterSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseHighlighter/Header"), SettingsResourceLoader.GetString("MouseHighlighter_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.MouseJump)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<MouseJumpSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseJump/Header"), SettingsResourceLoader.GetString("MouseJump_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.MousePointerCrosshairs)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<MousePointerCrosshairsSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MousePointerCrosshairs/Header"), SettingsResourceLoader.GetString("MouseCrosshairs_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.Peek)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<PeekSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("Peek/ModuleTitle")));
|
||||
}
|
||||
|
||||
if (enabledModules.PowerLauncher)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<PowerLauncherSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.OpenPowerLauncher, SettingsResourceLoader.GetString("PowerLauncher/ModuleTitle")));
|
||||
}
|
||||
|
||||
if (enabledModules.MeasureTool)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<MeasureToolSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MeasureTool/ModuleTitle"), SettingsResourceLoader.GetString("ScreenRuler_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.ShortcutGuide)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ShortcutGuideSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.DefaultOpenShortcutGuide, SettingsResourceLoader.GetString("ShortcutGuide/ModuleTitle"), SettingsResourceLoader.GetString("ShortcutGuide_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.PowerOcr)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<PowerOcrSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("TextExtractor/ModuleTitle"), SettingsResourceLoader.GetString("PowerOcr_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.Workspaces)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<WorkspacesSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("Workspaces/ModuleTitle"), SettingsResourceLoader.GetString("Workspaces_ShortDescription")));
|
||||
}
|
||||
|
||||
// Todo: ZoomIt hotkeys currently not supported, because ZoomIt does save their settings in the view model instead of the settings properties, which is weird.
|
||||
/*
|
||||
if (enabledModules.ZoomIt)
|
||||
{
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ZoomItSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ToggleKey, SettingsResourceLoader.GetString("ZoomIt/ModuleTitle"), SettingsResourceLoader.GetString("ZoomIt_ZoomGroup/Header")));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ZoomItSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.LiveZoomToggleKey, SettingsResourceLoader.GetString("ZoomIt/ModuleTitle"), SettingsResourceLoader.GetString("ZoomIt_LiveZoomGroup/Header")));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ZoomItSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.DrawToggleKey, SettingsResourceLoader.GetString("ZoomIt/ModuleTitle"), SettingsResourceLoader.GetString("ZoomIt_DrawGroup/Header")));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ZoomItSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.DemoTypeToggleKey, SettingsResourceLoader.GetString("ZoomIt/ModuleTitle"), SettingsResourceLoader.GetString("ZoomIt_DemoTypeGroup/Header")));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ZoomItSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.BreakTimerKey, SettingsResourceLoader.GetString("ZoomIt/ModuleTitle"), SettingsResourceLoader.GetString("ZoomIt_BreakGroup/Header")));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ZoomItSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.RecordToggleKey, SettingsResourceLoader.GetString("ZoomIt/ModuleTitle"), SettingsResourceLoader.GetString("ZoomIt_RecordGroup/Header")));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ZoomItSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.SnipToggleKey, SettingsResourceLoader.GetString("ZoomIt/ModuleTitle"), SettingsResourceLoader.GetString("ZoomIt_SnipGroup/Header")));
|
||||
}*/
|
||||
|
||||
content.Append(populateEndString);
|
||||
|
||||
File.WriteAllText(path, content.ToString());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts the hotkey settings to a YAML format string for the manifest file.
|
||||
/// </summary>
|
||||
/// <param name="hotkeySettings">Object containing a hotkey from the settings.</param>
|
||||
/// <param name="moduleName">The name of the PowerToys module.</param>
|
||||
/// <param name="description">Description of the action.</param>
|
||||
/// <returns>Yaml code for the manifest file.</returns>
|
||||
private static string HotkeySettingsToYaml(HotkeySettings hotkeySettings, string moduleName, string? description = null)
|
||||
{
|
||||
string content = string.Empty;
|
||||
content += " - Name: " + moduleName + Environment.NewLine;
|
||||
content += " Shortcut: " + Environment.NewLine;
|
||||
content += " - Win: " + hotkeySettings.Win.ToString() + Environment.NewLine;
|
||||
content += " Ctrl: " + hotkeySettings.Ctrl.ToString() + Environment.NewLine;
|
||||
content += " Alt: " + hotkeySettings.Alt.ToString() + Environment.NewLine;
|
||||
content += " Shift: " + hotkeySettings.Shift.ToString() + Environment.NewLine;
|
||||
content += " Keys:" + Environment.NewLine;
|
||||
content += " - " + hotkeySettings.Code.ToString(CultureInfo.InvariantCulture) + Environment.NewLine;
|
||||
if (description != null)
|
||||
{
|
||||
content += " Description: " + description + Environment.NewLine;
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="HotkeySettingsToYaml(HotkeySettings, string, string?)"/>
|
||||
private static string HotkeySettingsToYaml(KeyboardKeysProperty hotkeySettings, string moduleName, string? description = null)
|
||||
{
|
||||
return HotkeySettingsToYaml(hotkeySettings.Value, moduleName, description);
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"# <Populate start>[\s\S\n\r]*# <Populate end>")]
|
||||
private static partial Regex PopulateRegex();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
internal static class ResourceLoaderInstance
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the resource loader for the Shortcut Guide module.
|
||||
/// </summary>
|
||||
internal static ResourceLoader ResourceLoader { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the resource loader for the Settings module.
|
||||
/// </summary>
|
||||
internal static ResourceLoader SettingsResourceLoader { get; private set; }
|
||||
|
||||
static ResourceLoaderInstance()
|
||||
{
|
||||
ResourceLoader = new ResourceLoader("PowerToys.ShortcutGuide.pri");
|
||||
SettingsResourceLoader = new ResourceLoader("PowerToys.Settings.pri");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
[MarkupExtensionReturnType(ReturnType = typeof(string))]
|
||||
public partial class StringResourceExtension : MarkupExtension
|
||||
{
|
||||
public enum SpecialTreatment
|
||||
{
|
||||
None,
|
||||
FirstCharOnly,
|
||||
EverythingExceptFirstChar,
|
||||
}
|
||||
|
||||
public string Key { get; set; } = string.Empty;
|
||||
|
||||
public SpecialTreatment Treatment { get; set; } = SpecialTreatment.None;
|
||||
|
||||
protected override object ProvideValue() => Treatment switch
|
||||
{
|
||||
SpecialTreatment.FirstCharOnly => ResourceLoaderInstance.ResourceLoader.GetString(Key)[0].ToString(),
|
||||
SpecialTreatment.EverythingExceptFirstChar => ResourceLoaderInstance.ResourceLoader.GetString(Key)[1..],
|
||||
_ => ResourceLoaderInstance.ResourceLoader.GetString(Key),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using WinRT.Interop;
|
||||
using TasklistButton = ShortcutGuide.NativeMethods.TasklistButton;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides methods to retrieve the positions of taskbar buttons on the current monitor.
|
||||
/// </summary>
|
||||
internal static class TasklistPositions
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the taskbar buttons for the current monitor.
|
||||
/// </summary>
|
||||
/// <returns>An array of the taskbar buttons.</returns>
|
||||
public static TasklistButton[] GetButtons()
|
||||
{
|
||||
var monitor = NativeMethods.MonitorFromWindow(WindowNative.GetWindowHandle(App.MainWindow), 0);
|
||||
nint ptr = NativeMethods.GetTasklistButtons(monitor, out int size);
|
||||
if (ptr == nint.Zero)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
if (size <= 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
TasklistButton[] buttons = new TasklistButton[size];
|
||||
nint currentPtr = ptr;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
buttons[i] = Marshal.PtrToStructure<TasklistButton>(currentPtr);
|
||||
currentPtr += Marshal.SizeOf<TasklistButton>();
|
||||
}
|
||||
|
||||
return buttons;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace ShortcutGuide.Models
|
||||
{
|
||||
public struct IndexFile
|
||||
{
|
||||
public struct IndexItem
|
||||
{
|
||||
public string WindowFilter { get; set; }
|
||||
|
||||
public bool BackgroundProcess { get; set; }
|
||||
|
||||
public string[] Apps { get; set; }
|
||||
}
|
||||
|
||||
public string DefaultShellName { get; set; }
|
||||
|
||||
public IndexItem[] Index { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace ShortcutGuide.Models
|
||||
{
|
||||
public struct ShortcutCategory
|
||||
{
|
||||
public string SectionName { get; set; }
|
||||
|
||||
public ShortcutEntry[] Properties { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShortcutGuide.Models
|
||||
{
|
||||
public class ShortcutDescription(bool ctrl, bool shift, bool alt, bool win, string[] keys)
|
||||
{
|
||||
public ShortcutDescription()
|
||||
: this(false, false, false, false, [])
|
||||
{
|
||||
}
|
||||
|
||||
[JsonPropertyName(nameof(Ctrl))]
|
||||
public bool Ctrl { get; set; } = ctrl;
|
||||
|
||||
[JsonPropertyName(nameof(Shift))]
|
||||
public bool Shift { get; set; } = shift;
|
||||
|
||||
[JsonPropertyName(nameof(Alt))]
|
||||
public bool Alt { get; set; } = alt;
|
||||
|
||||
[JsonPropertyName(nameof(Win))]
|
||||
public bool Win { get; set; } = win;
|
||||
|
||||
[JsonPropertyName(nameof(Keys))]
|
||||
public string[] Keys { get; set; } = keys;
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is ShortcutDescription other && Ctrl == other.Ctrl &&
|
||||
Shift == other.Shift &&
|
||||
Alt == other.Alt &&
|
||||
Win == other.Win &&
|
||||
Keys.SequenceEqual(other.Keys);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator ==(ShortcutDescription? left, ShortcutDescription? right)
|
||||
{
|
||||
return (left is null && right is null) || (left is not null && right is not null && left.Equals(right));
|
||||
}
|
||||
|
||||
public static bool operator !=(ShortcutDescription? left, ShortcutDescription? right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
using Windows.UI.Text;
|
||||
using static ShortcutGuide.Models.ShortcutEntry;
|
||||
using Orientation = Microsoft.UI.Xaml.Controls.Orientation;
|
||||
|
||||
namespace ShortcutGuide.Models
|
||||
{
|
||||
public class ShortcutEntry(string name, string? description, bool recommended, ShortcutDescription[] shortcutDescriptions)
|
||||
{
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is ShortcutEntry other && Name == other.Name &&
|
||||
Description == other.Description &&
|
||||
Shortcut.Length == other.Shortcut.Length &&
|
||||
Shortcut.SequenceEqual(other.Shortcut);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return base.GetHashCode();
|
||||
}
|
||||
|
||||
public static bool operator ==(ShortcutEntry? left, ShortcutEntry? right)
|
||||
{
|
||||
return (left is null && right is null) || (left is not null && right is not null && left.Equals(right));
|
||||
}
|
||||
|
||||
public static bool operator !=(ShortcutEntry? left, ShortcutEntry? right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
public ShortcutEntry()
|
||||
: this(string.Empty, string.Empty, false, [])
|
||||
{
|
||||
}
|
||||
|
||||
[JsonPropertyName(nameof(Name))]
|
||||
public string Name { get; set; } = name;
|
||||
|
||||
[JsonPropertyName(nameof(Description))]
|
||||
public string? Description { get; set; } = description;
|
||||
|
||||
[JsonPropertyName(nameof(Recommended))]
|
||||
public bool Recommended { get; set; } = recommended;
|
||||
|
||||
[JsonPropertyName(nameof(Shortcut))]
|
||||
public ShortcutDescription[] Shortcut { get; set; } = shortcutDescriptions;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace ShortcutGuide.Models
|
||||
{
|
||||
public struct ShortcutFile
|
||||
{
|
||||
public string PackageName { get; set; }
|
||||
|
||||
public ShortcutCategory[] Shortcuts { get; set; }
|
||||
|
||||
public string WindowFilter { get; set; }
|
||||
|
||||
public bool BackgroundProcess { get; set; }
|
||||
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ShortcutGuide.Models
|
||||
{
|
||||
internal sealed class ShortcutPageNavParam
|
||||
{
|
||||
public string AppName { get; set; } = string.Empty;
|
||||
|
||||
public ShortcutFile ShortcutFile { get; set; }
|
||||
|
||||
public int PageIndex { get; set; }
|
||||
}
|
||||
}
|
||||
127
src/modules/ShortcutGuide/ShortcutGuide.Ui/NativeMethods.cs
Normal file
@@ -0,0 +1,127 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Graphics;
|
||||
|
||||
namespace ShortcutGuide;
|
||||
|
||||
internal static partial class NativeMethods
|
||||
{
|
||||
internal const int GWL_STYLE = -16;
|
||||
internal const int WS_CAPTION = 0x00C00000;
|
||||
|
||||
[LibraryImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
internal static partial int GetWindowLongW(IntPtr hWnd, int nIndex);
|
||||
|
||||
[LibraryImport("user32.dll")]
|
||||
internal static partial int SetWindowLongW(IntPtr hWnd, int nIndex, int dwNewLong);
|
||||
|
||||
[LibraryImport("user32.dll", StringMarshalling = StringMarshalling.Utf16)]
|
||||
internal static partial IntPtr FindWindowA(in string lpClassName, in string? lpWindowName);
|
||||
|
||||
[LibraryImport("User32.dll")]
|
||||
internal static partial IntPtr MonitorFromWindow(IntPtr hwnd, int dwFlags);
|
||||
|
||||
[LibraryImport("Shcore.dll")]
|
||||
internal static partial long GetDpiForMonitor(IntPtr hmonitor, int dpiType, ref int dpiX, ref int dpiY);
|
||||
|
||||
[LibraryImport("user32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool GetCursorPos(out POINT lpPoint);
|
||||
|
||||
[LibraryImport("user32.dll")]
|
||||
internal static partial IntPtr GetForegroundWindow();
|
||||
|
||||
[LibraryImport("user32.dll", SetLastError = true)]
|
||||
internal static partial uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
|
||||
|
||||
[LibraryImport("user32.dll")]
|
||||
internal static partial short GetAsyncKeyState(int vKey);
|
||||
|
||||
[LibraryImport("ShortcutGuide.CPPProject.dll", EntryPoint = "get_buttons")]
|
||||
internal static partial IntPtr GetTasklistButtons(IntPtr monitor, out int size);
|
||||
|
||||
[LibraryImport("ShortcutGuide.CPPProject.dll", EntryPoint = "IsCurrentWindowExcludedFromShortcutGuide")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool IsCurrentWindowExcludedFromShortcutGuide();
|
||||
|
||||
[LibraryImport("User32.dll")]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
internal static partial bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData);
|
||||
|
||||
internal delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData);
|
||||
|
||||
internal struct LPARAM(IntPtr value)
|
||||
{
|
||||
internal IntPtr Value = value;
|
||||
|
||||
public static implicit operator IntPtr(LPARAM lParam)
|
||||
{
|
||||
return lParam.Value;
|
||||
}
|
||||
|
||||
public static implicit operator LPARAM(IntPtr value)
|
||||
{
|
||||
return new LPARAM(value);
|
||||
}
|
||||
|
||||
public static implicit operator LPARAM(int value)
|
||||
{
|
||||
return new LPARAM(new IntPtr(value));
|
||||
}
|
||||
|
||||
public static implicit operator int(LPARAM lParam)
|
||||
{
|
||||
return lParam.Value.ToInt32();
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct RECT
|
||||
{
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
}
|
||||
|
||||
internal struct POINT
|
||||
{
|
||||
internal int X;
|
||||
internal int Y;
|
||||
|
||||
public static implicit operator PointInt32(POINT point)
|
||||
{
|
||||
return new PointInt32(point.X, point.Y);
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||
public struct TasklistButton
|
||||
{
|
||||
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
|
||||
public string Name;
|
||||
|
||||
public int X;
|
||||
|
||||
public int Y;
|
||||
|
||||
public int Width;
|
||||
|
||||
public int Height;
|
||||
|
||||
public int Keynum;
|
||||
}
|
||||
|
||||
public enum MonitorFromWindowDwFlags
|
||||
{
|
||||
MONITOR_DEFAULTTONEAREST = 2,
|
||||
}
|
||||
}
|
||||
84
src/modules/ShortcutGuide/ShortcutGuide.Ui/Program.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using ShortcutGuide.Helpers;
|
||||
using Application = Microsoft.UI.Xaml.Application;
|
||||
|
||||
namespace ShortcutGuide
|
||||
{
|
||||
public sealed class Program
|
||||
{
|
||||
private static readonly string[] InbuiltManifestFiles = [
|
||||
"+WindowsNT.Shell.en-US.yml",
|
||||
"+WindowsNT.WindowsExplorer.en-US.yml",
|
||||
"+WindowsNT.Notepad.en-US.yml",
|
||||
"Microsoft.PowerToys.en-US.yml",
|
||||
];
|
||||
|
||||
[STAThread]
|
||||
public static void Main()
|
||||
{
|
||||
if (PowerToys.GPOWrapper.GPOWrapper.GetConfiguredShortcutGuideEnabledValue() == PowerToys.GPOWrapper.GpoRuleConfigured.Disabled)
|
||||
{
|
||||
Logger.LogWarning("Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
|
||||
return;
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(ManifestInterpreter.PathOfManifestFiles);
|
||||
|
||||
if (NativeMethods.IsCurrentWindowExcludedFromShortcutGuide())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Todo: Only copy files after an update.
|
||||
// Todo: Handle error
|
||||
foreach (var file in InbuiltManifestFiles)
|
||||
{
|
||||
File.Copy(Path.GetDirectoryName(Environment.ProcessPath) + "\\Assets\\ShortcutGuide\\" + file, ManifestInterpreter.PathOfManifestFiles + "\\" + file, true);
|
||||
}
|
||||
|
||||
Process indexGeneration = Process.Start(Path.GetDirectoryName(Environment.ProcessPath) + "\\PowerToys.ShortcutGuide.IndexYmlGenerator.exe");
|
||||
indexGeneration.WaitForExit();
|
||||
if (indexGeneration.ExitCode != 0)
|
||||
{
|
||||
Logger.LogError("Index generation failed with exit code: " + indexGeneration.ExitCode);
|
||||
MessageBox.Show($"Shortcut Guide encountered an error while generating the index file. There is likely a corrupt shortcuts file in \"{ManifestInterpreter.PathOfManifestFiles}\". Try deleting this directory.", "Error displaying shortcuts", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
PowerToysShortcutsPopulator.Populate();
|
||||
|
||||
Logger.InitializeLogger("\\ShortcutGuide\\Logs");
|
||||
WinRT.ComWrappersSupport.InitializeComWrappers();
|
||||
|
||||
var instanceKey = AppInstance.FindOrRegisterForKey("PowerToys_ShortcutGuide_Instance");
|
||||
|
||||
if (instanceKey.IsCurrent)
|
||||
{
|
||||
Application.Start((p) =>
|
||||
{
|
||||
var context = new DispatcherQueueSynchronizationContext(DispatcherQueue.GetForCurrentThread());
|
||||
SynchronizationContext.SetSynchronizationContext(context);
|
||||
_ = new App();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning("Another instance of ShortcutGuide is running. Exiting ShortcutGuide");
|
||||
}
|
||||
|
||||
// Something prevents the process from exiting, so we need to kill it manually.
|
||||
Process.GetCurrentProcess().Kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Look at Directory.Build.props in root for common stuff as well -->
|
||||
<Import Project="..\..\..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\..\..\Common.SelfContained.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>ShortcutGuide</RootNamespace>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
<WindowsPackageType>None</WindowsPackageType>
|
||||
<Nullable>enable</Nullable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
|
||||
<OutputPath>..\..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
|
||||
<AssemblyName>PowerToys.ShortcutGuide</AssemblyName>
|
||||
<DefineConstants>DISABLE_XAML_GENERATED_MAIN,TRACE</DefineConstants>
|
||||
<ApplicationIcon>Assets\ShortcutGuide\ShortcutGuide.ico</ApplicationIcon>
|
||||
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
|
||||
<ProjectPriFileName>PowerToys.ShortcutGuide.pri</ProjectPriFileName>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Remove="Assets\CopilotKey.png" />
|
||||
<Content Remove="Assets\ShortcutGuide\+WindowsNT.Shell.en-US.yml" />
|
||||
<Content Remove="Assets\ShortcutGuide\+WindowsNT.WindowsExplorer.en-US.yml" />
|
||||
<Content Remove="Assets\ShortcutGuide\HeroImage.png" />
|
||||
<Content Remove="Assets\ShortcutGuide\Microsoft.PowerToys.en-US.yml" />
|
||||
<Content Remove="Assets\ShortcutGuide\OfficeKey.png" />
|
||||
<Content Remove="Assets\ShortcutGuide\ShortcutGuide.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="ShortcutGuideXAML\CustomNavigationViewStyle.xaml" />
|
||||
<None Remove="ShortcutGuideXAML\Pages\ShortcutsPage.xaml" />
|
||||
<None Remove="ShortcutGuideXAML\TaskbarIndicator.xaml" />
|
||||
<None Remove="ShortcutGuideXAML\TaskbarWindow.xaml" />
|
||||
<None Include="Assets\ShortcutGuide\*">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyPRIFileToOutputDir" AfterTargets="Build">
|
||||
<Message Text="Executing CopyPRIFileToOutputDir task" Importance="High" />
|
||||
|
||||
<ItemGroup>
|
||||
<PRIFile Include="$(OutDir)**\PowerToys.ShortcutGuide.pri" />
|
||||
</ItemGroup>
|
||||
|
||||
<Copy SourceFiles="@(PRIFile)" DestinationFolder="$(OutDir)" />
|
||||
|
||||
<Message Text="Copied CopyPRIFileToOutputDir files" Importance="High" />
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Remove="ShortcutGuideXAML\App.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="ShortcutGuideXAML\App.xaml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<COMReference Include="UIAutomationClient">
|
||||
<WrapperTool>tlbimp</WrapperTool>
|
||||
<VersionMinor>0</VersionMinor>
|
||||
<VersionMajor>1</VersionMajor>
|
||||
<Guid>944de083-8fb8-45cf-bcb7-c477acb2f897</Guid>
|
||||
<Lcid>0</Lcid>
|
||||
<Isolated>false</Isolated>
|
||||
<EmbedInteropTypes>true</EmbedInteropTypes>
|
||||
</COMReference>
|
||||
</ItemGroup>
|
||||
|
||||
<!-- See https://learn.microsoft.com/windows/apps/develop/platform/csharp-winrt/net-projection-from-cppwinrt-component for more info -->
|
||||
<PropertyGroup>
|
||||
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
|
||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
<!-- HACK: To make sure the version pulled in by Microsoft.Extensions.Hosting is current. -->
|
||||
<PackageReference Include="System.Text.Json" />
|
||||
<PackageReference Include="YamlDotNet" />
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
|
||||
<!--
|
||||
Defining the "Msix" ProjectCapability here allows the Single-project MSIX Packaging
|
||||
Tools extension to be activated for this project even if the Windows App SDK Nuget
|
||||
package has not yet been restored.
|
||||
-->
|
||||
<ItemGroup Condition="'$(DisableMsixProjectCapabilityAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
|
||||
<ProjectCapability Include="Msix" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
|
||||
<ProjectReference Include="..\..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
|
||||
<ProjectReference Include="..\..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
<ProjectReference Include="..\ShortcutGuide.CPPProject\ShortcutGuide.CPPProject.vcxproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="ShortcutGuideXAML\Pages\OverviewPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="ShortcutGuideXAML\CustomNavigationViewStyle.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="ShortcutGuideXAML\TaskbarWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="ShortcutGuideXAML\TaskbarIndicator.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Update="ShortcutGuideXAML\Pages\ShortcutsPage.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="ShortcutGuideXAML\Styles\" />
|
||||
</ItemGroup>
|
||||
<!--
|
||||
Defining the "HasPackageAndPublishMenuAddedByProject" property here allows the Solution
|
||||
Explorer "Package and Publish" context menu entry to be enabled for this project even if
|
||||
the Windows App SDK Nuget package has not yet been restored.
|
||||
-->
|
||||
<PropertyGroup Condition="'$(DisableHasPackageAndPublishMenuAddedByProject)'!='true' and '$(EnableMsixTooling)'=='true'">
|
||||
<HasPackageAndPublishMenu>true</HasPackageAndPublishMenu>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Application
|
||||
x:Class="ShortcutGuide.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="using:ShortcutGuide.Converters"
|
||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<ResourceDictionary Source="/ShortcutGuideXAML/Styles/CustomNavigationViewStyle.xaml" />
|
||||
<ResourceDictionary Source="/ShortcutGuideXAML/Controls/KeyCharPresenter.xaml" />
|
||||
<ResourceDictionary Source="/ShortcutGuideXAML/Controls/KeyVisual.xaml" />
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<!-- Other app resources here -->
|
||||
|
||||
<tkconverters:DoubleToVisibilityConverter
|
||||
x:Name="DoubleToVisibilityConverter"
|
||||
FalseValue="Collapsed"
|
||||
GreaterThan="0"
|
||||
TrueValue="Visible" />
|
||||
<tkconverters:DoubleToVisibilityConverter
|
||||
x:Name="DoubleToInvertedVisibilityConverter"
|
||||
FalseValue="Visible"
|
||||
GreaterThan="0"
|
||||
TrueValue="Collapsed" />
|
||||
<tkconverters:StringVisibilityConverter x:Name="StringVisibilityConverter" />
|
||||
<converters:ShortcutDescriptionToKeysConverter x:Name="ShortcutDescriptionToKeysConverter" />
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml;
|
||||
using ShortcutGuide.Models;
|
||||
using ShortcutGuide.ShortcutGuideXAML;
|
||||
|
||||
namespace ShortcutGuide
|
||||
{
|
||||
public partial class App
|
||||
{
|
||||
internal static Dictionary<string, List<ShortcutEntry>> PinnedShortcuts { get; private set; } = null!;
|
||||
|
||||
internal static ShortcutGuideSettings ShortcutGuideSettings { get; private set; } = null!;
|
||||
|
||||
internal static ShortcutGuideProperties ShortcutGuideProperties { get; private set; } = null!;
|
||||
|
||||
internal static MainWindow MainWindow { get; private set; } = null!;
|
||||
|
||||
internal static TaskbarWindow TaskBarWindow { get; private set; } = null!;
|
||||
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
LoadData();
|
||||
MainWindow = new MainWindow();
|
||||
TaskBarWindow = new TaskbarWindow();
|
||||
MainWindow.Activate();
|
||||
MainWindow.Closed += (_, _) =>
|
||||
{
|
||||
Current.Exit();
|
||||
};
|
||||
}
|
||||
|
||||
private void LoadData()
|
||||
{
|
||||
SettingsUtils settingsUtils = new();
|
||||
|
||||
if (settingsUtils.SettingsExists(ShortcutGuideSettings.ModuleName, "Pinned.json"))
|
||||
{
|
||||
string pinnedPath = settingsUtils.GetSettingsFilePath(ShortcutGuideSettings.ModuleName, "Pinned.json");
|
||||
PinnedShortcuts = JsonSerializer.Deserialize<Dictionary<string, List<ShortcutEntry>>>(File.ReadAllText(pinnedPath))!;
|
||||
}
|
||||
|
||||
ShortcutGuideSettings = SettingsRepository<ShortcutGuideSettings>.GetInstance(settingsUtils).SettingsConfig;
|
||||
ShortcutGuideProperties = ShortcutGuideSettings.Properties;
|
||||
|
||||
#pragma warning disable CA1869 // Cache and reuse 'JsonSerializerOptions' instances
|
||||
settingsUtils.SaveSettings(JsonSerializer.Serialize(App.ShortcutGuideSettings, new JsonSerializerOptions { WriteIndented = true }), "Shortcut Guide");
|
||||
#pragma warning restore CA1869 // Cache and reuse 'JsonSerializerOptions' instances
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:helpers="using:ShortcutGuide.Helpers"
|
||||
xmlns:local="using:ShortcutGuide.Controls"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI">
|
||||
|
||||
<Style BasedOn="{StaticResource DefaultKeyCharPresenterStyle}" TargetType="local:KeyCharPresenter" />
|
||||
|
||||
|
||||
<Style x:Key="DefaultKeyCharPresenterStyle" TargetType="local:KeyCharPresenter">
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="AutomationProperties.AccessibilityView" Value="Raw" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid Height="{TemplateBinding FontSize}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Text="{TemplateBinding Content}"
|
||||
TextLineBounds="Tight" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="UnderlinedLetterKeyCharPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultKeyCharPresenterStyle}"
|
||||
TargetType="local:KeyCharPresenter">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid Height="{TemplateBinding FontSize}">
|
||||
<TextBlock
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
FontFamily="{TemplateBinding FontFamily}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
TextLineBounds="Tight">
|
||||
<Run Text="{helpers:StringResourceExtension Key='UnderlinedKeyChar/Text', Treatment=FirstCharOnly}" TextDecorations="Underline" /><Run Text="{helpers:StringResourceExtension Key='UnderlinedKeyChar/Text', Treatment=EverythingExceptFirstChar}" />
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="WindowsKeyCharPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultKeyCharPresenterStyle}"
|
||||
TargetType="local:KeyCharPresenter">
|
||||
<!-- Scale to visually align the height of the Windows logo and text -->
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid Height="{TemplateBinding FontSize}">
|
||||
<Viewbox>
|
||||
<PathIcon Data="M9 20H0V11H9V20ZM20 20H11V11H20V20ZM9 9H0V0H9V9ZM20 9H11V0H20V9Z" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="OfficeKeyCharPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultKeyCharPresenterStyle}"
|
||||
TargetType="local:KeyCharPresenter">
|
||||
<!-- Scale to visually align the height of the Office logo and text -->
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid Height="{TemplateBinding FontSize}">
|
||||
<Viewbox>
|
||||
<PathIcon Data="M1792 405v1238q0 33-10 62t-28 54-44 41-57 27l-555 159q-23 6-47 6-31 0-58-8t-53-24l-363-205q-20-11-31-29t-12-42q0-35 24-59t60-25h470V458L735 584q-43 15-69 53t-26 83v651q0 41-20 73t-55 53l-167 91q-23 12-46 12-40 0-68-28t-28-68V587q0-51 26-96t71-71L949 81q41-23 89-23 17 0 30 2t30 8l555 153q31 9 56 27t44 42 29 54 10 61zm-128 1238V405q0-22-13-38t-34-23l-273-75-64-18-64-18v1586l401-115q21-6 34-22t13-39z" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="CopilotKeyCharPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultKeyCharPresenterStyle}"
|
||||
TargetType="local:KeyCharPresenter">
|
||||
<!-- Scale to visually align the height of the Copilot logo and text -->
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid Height="{TemplateBinding FontSize}">
|
||||
<Viewbox>
|
||||
<PathIcon Data="M0 1213q0-60 10-124t27-130 35-129 38-121q18-55 41-119t54-129 70-125 87-106 106-74 129-28h661q59 0 114 17t96 64q30 34 46 72t33 81l22 58q11 29 34 52 23 25 56 31t65 9h4q157 0 238 83t82 240q0 60-10 125t-27 130-35 128-38 121q-18 55-41 119t-54 129-70 125-87 106-106 74-129 28H790q-61 0-107-15t-82-44-61-72-46-98q-11-29-24-60t-35-55q-23-25-51-31t-60-9h-4q-157 0-238-83T0 1213zm598-957q-50 0-93 25t-79 68-67 94-54 108-42 106-31 91q-17 51-35 110t-33 119-26 121-10 114q0 102 43 149t147 47h163q39 0 74-12t64-35 50-53 34-67q19-58 35-115t35-117q35-117 70-232t72-233q23-73 47-147t63-141H598zm452 285q69-29 143-29h281q-18-29-29-59t-21-58-21-54-30-44-46-30-69-11q-32 0-60 9t-48 35q-17 23-31 53t-27 63-23 65-19 60zm-296 867h101q39 0 74-12t66-34 52-52 33-68l58-191 42-140q21-70 43-140 11-36 28-69t43-62h-101q-39 0-74 12t-66 34-52 52-33 68q-15 48-29 96t-29 96q-21 70-41 140t-44 140q-11 36-28 68t-43 62zm814-768q-39 0-74 12t-64 35-50 53-34 68q-56 174-107 347t-106 349q-23 74-47 147t-63 141h427q50 0 93-25t79-68 67-94 54-108 42-106 31-91q16-51 34-110t34-119 26-121 10-114q0-102-43-149t-147-47h-162zm-570 867q-69 29-143 29H564q17 28 29 58t22 58 24 54 32 45 48 30 71 11q31 0 60-8t49-35q15-19 29-50t28-65 24-69 18-58z" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="GlyphKeyCharPresenterStyle"
|
||||
BasedOn="{StaticResource DefaultKeyCharPresenterStyle}"
|
||||
TargetType="local:KeyCharPresenter">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyCharPresenter">
|
||||
<Grid>
|
||||
<Viewbox>
|
||||
<FontIcon
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Glyph="{TemplateBinding Content}" />
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Windows.Markup;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
using Microsoft.UI.Xaml.Documents;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using ShortcutGuide.Helpers;
|
||||
|
||||
namespace ShortcutGuide.Controls;
|
||||
|
||||
public sealed partial class KeyCharPresenter : Control
|
||||
{
|
||||
public KeyCharPresenter()
|
||||
{
|
||||
DefaultStyleKey = typeof(KeyCharPresenter);
|
||||
}
|
||||
|
||||
public object Content
|
||||
{
|
||||
get => (object)GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(object), typeof(KeyCharPresenter), new PropertyMetadata(default(string)));
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:ShortcutGuide.Controls">
|
||||
|
||||
<Style BasedOn="{StaticResource DefaultKeyVisualStyle}" TargetType="local:KeyVisual" />
|
||||
|
||||
<Style x:Key="DefaultKeyVisualStyle" TargetType="local:KeyVisual">
|
||||
<Setter Property="MinWidth" Value="16" />
|
||||
<Setter Property="AutomationProperties.AccessibilityView" Value="Raw" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="MinHeight" Value="16" />
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleFillColorTransparentBrush}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextFillColorPrimaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource ControlStrokeColorDefaultBrush}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="Padding" Value="4,4,4,4" />
|
||||
<Setter Property="FontWeight" Value="Normal" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="CornerRadius" Value="2" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyVisual">
|
||||
<Grid
|
||||
x:Name="KeyHolder"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<local:KeyCharPresenter
|
||||
x:Name="KeyPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding Content}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource SubtleFillColorTransparentBrush}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource CardStrokeColorDefaultSolidBrush}" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource ControlStrokeColorDefaultBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Invalid">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource SystemFillColorCriticalBackgroundBrush}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
<Setter Target="KeyHolder.BorderThickness" Value="2" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="SubtleKeyVisualStyle"
|
||||
BasedOn="{StaticResource DefaultKeyVisualStyle}"
|
||||
TargetType="local:KeyVisual">
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleFillColorTransparentBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SubtleFillColorTransparentBrush}" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyVisual">
|
||||
<Grid
|
||||
x:Name="KeyHolder"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<local:KeyCharPresenter
|
||||
x:Name="KeyPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Content="{TemplateBinding Content}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Invalid">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style
|
||||
x:Key="AccentKeyVisualStyle"
|
||||
BasedOn="{StaticResource DefaultKeyVisualStyle}"
|
||||
TargetType="local:KeyVisual">
|
||||
|
||||
<Setter Property="Background" Value="{ThemeResource AccentFillColorDefaultBrush}" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource TextOnAccentFillColorPrimaryBrush}" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource AccentControlElevationBorderBrush}" />
|
||||
<Setter Property="BackgroundSizing" Value="OuterBorderEdge" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="local:KeyVisual">
|
||||
<Grid
|
||||
x:Name="KeyHolder"
|
||||
MinWidth="{TemplateBinding MinWidth}"
|
||||
MinHeight="{TemplateBinding MinHeight}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalAlignment}"
|
||||
AutomationProperties.AccessibilityView="Raw"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
<Grid.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</Grid.BackgroundTransition>
|
||||
<local:KeyCharPresenter
|
||||
x:Name="KeyPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
FontSize="{TemplateBinding FontSize}"
|
||||
FontWeight="{TemplateBinding FontWeight}"
|
||||
Foreground="{TemplateBinding Foreground}" />
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
<VisualState x:Name="Disabled">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource AccentButtonBackgroundDisabled}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource AccentButtonBorderBrushDisabled}" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource AccentButtonForegroundDisabled}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
<VisualState x:Name="Invalid">
|
||||
<VisualState.Setters>
|
||||
<Setter Target="KeyHolder.Background" Value="{ThemeResource SystemFillColorCriticalBackgroundBrush}" />
|
||||
<Setter Target="KeyHolder.BorderBrush" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
<Setter Target="KeyHolder.BorderThickness" Value="2" />
|
||||
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource SystemFillColorCriticalBrush}" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
</VisualStateGroup>
|
||||
</VisualStateManager.VisualStateGroups>
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,194 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.System;
|
||||
|
||||
namespace ShortcutGuide.Controls
|
||||
{
|
||||
[TemplatePart(Name = KeyPresenter, Type = typeof(KeyCharPresenter))]
|
||||
[TemplateVisualState(Name = NormalState, GroupName = "CommonStates")]
|
||||
[TemplateVisualState(Name = DisabledState, GroupName = "CommonStates")]
|
||||
[TemplateVisualState(Name = InvalidState, GroupName = "CommonStates")]
|
||||
public sealed partial class KeyVisual : Control
|
||||
{
|
||||
private const string KeyPresenter = "KeyPresenter";
|
||||
private const string NormalState = "Normal";
|
||||
private const string DisabledState = "Disabled";
|
||||
private const string InvalidState = "Invalid";
|
||||
private KeyCharPresenter _keyPresenter = null!;
|
||||
|
||||
public object Content
|
||||
{
|
||||
get => (object)GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(object), typeof(KeyVisual), new PropertyMetadata(default(string), OnContentChanged));
|
||||
|
||||
public bool IsInvalid
|
||||
{
|
||||
get => (bool)GetValue(IsInvalidProperty);
|
||||
set => SetValue(IsInvalidProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsInvalidProperty = DependencyProperty.Register(nameof(IsInvalid), typeof(bool), typeof(KeyVisual), new PropertyMetadata(false, OnIsInvalidChanged));
|
||||
|
||||
public bool RenderKeyAsGlyph
|
||||
{
|
||||
get => (bool)GetValue(RenderKeyAsGlyphProperty);
|
||||
set => SetValue(RenderKeyAsGlyphProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RenderKeyAsGlyphProperty = DependencyProperty.Register(nameof(RenderKeyAsGlyph), typeof(bool), typeof(KeyVisual), new PropertyMetadata(false, OnContentChanged));
|
||||
|
||||
public KeyVisual()
|
||||
{
|
||||
this.DefaultStyleKey = typeof(KeyVisual);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate()
|
||||
{
|
||||
IsEnabledChanged -= KeyVisual_IsEnabledChanged;
|
||||
_keyPresenter = (KeyCharPresenter)this.GetTemplateChild(KeyPresenter);
|
||||
Update();
|
||||
SetVisualStates();
|
||||
IsEnabledChanged += KeyVisual_IsEnabledChanged;
|
||||
base.OnApplyTemplate();
|
||||
}
|
||||
|
||||
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((KeyVisual)d).SetVisualStates();
|
||||
}
|
||||
|
||||
private static void OnIsInvalidChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
((KeyVisual)d).SetVisualStates();
|
||||
}
|
||||
|
||||
private void SetVisualStates()
|
||||
{
|
||||
if (this != null)
|
||||
{
|
||||
if (IsInvalid)
|
||||
{
|
||||
VisualStateManager.GoToState(this, InvalidState, true);
|
||||
}
|
||||
else if (!IsEnabled)
|
||||
{
|
||||
VisualStateManager.GoToState(this, DisabledState, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
VisualStateManager.GoToState(this, NormalState, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Content == null)
|
||||
{
|
||||
Visibility = Visibility.Collapsed;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Content is string key)
|
||||
{
|
||||
SetGlyphOrText(key switch
|
||||
{
|
||||
"<TASKBAR1-9>" => "Num",
|
||||
"<Left>" => "\uE0E2",
|
||||
"<Right>" => "\uE0E3",
|
||||
"<Up>" => "\uE0E4",
|
||||
"<Down>" => "\uE0E5",
|
||||
"<ArrowUD>" => "\uE0E4\uE0E5",
|
||||
"<ArrowLR>" => "\uE0E2\uE0E3",
|
||||
"<Arrow>" => "\uE0E2\uE0E3\uE0E4\uE0E5",
|
||||
"<Enter>" => "\uE751",
|
||||
"<Backspace>" => "\uE750",
|
||||
"<Escape>" => "Esc",
|
||||
string s when s.StartsWith('<') => s.Trim('<', '>'),
|
||||
_ => key,
|
||||
});
|
||||
|
||||
_keyPresenter.Style = key switch
|
||||
{
|
||||
"<Copilot>" => (Style)Application.Current.Resources["CopilotKeyCharPresenterStyle"],
|
||||
"<Office>" => (Style)Application.Current.Resources["OfficeKeyCharPresenterStyle"],
|
||||
"<Underlined letter>" => (Style)Application.Current.Resources["UnderlinedLetterKeyCharPresenterStyle"],
|
||||
_ => _keyPresenter.Style,
|
||||
};
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Content is int keyCode)
|
||||
{
|
||||
VirtualKey virtualKey = (VirtualKey)keyCode;
|
||||
switch (virtualKey)
|
||||
{
|
||||
case VirtualKey.Enter:
|
||||
SetGlyphOrText("\uE751");
|
||||
break;
|
||||
|
||||
case VirtualKey.Back:
|
||||
SetGlyphOrText("\uE750");
|
||||
break;
|
||||
|
||||
case VirtualKey.Shift:
|
||||
case (VirtualKey)160: // Left Shift
|
||||
case (VirtualKey)161: // Right Shift
|
||||
SetGlyphOrText("\uE752");
|
||||
break;
|
||||
|
||||
case VirtualKey.Up:
|
||||
SetGlyphOrText("\uE0E4");
|
||||
break;
|
||||
|
||||
case VirtualKey.Down:
|
||||
SetGlyphOrText("\uE0E5");
|
||||
break;
|
||||
|
||||
case VirtualKey.Left:
|
||||
SetGlyphOrText("\uE0E2");
|
||||
break;
|
||||
|
||||
case VirtualKey.Right:
|
||||
SetGlyphOrText("\uE0E3");
|
||||
break;
|
||||
|
||||
case VirtualKey.LeftWindows:
|
||||
case VirtualKey.RightWindows:
|
||||
_keyPresenter.Style = (Style)Application.Current.Resources["WindowsKeyCharPresenterStyle"];
|
||||
break;
|
||||
default: // For all other keys, we will use the key name.
|
||||
SetGlyphOrText(virtualKey.ToString());
|
||||
break;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void SetGlyphOrText(string glyphOrText)
|
||||
{
|
||||
RenderKeyAsGlyph = ((glyphOrText[0] >> 12) & 0xF) is 0xE or 0xF;
|
||||
_keyPresenter.Content = glyphOrText;
|
||||
|
||||
_keyPresenter.Style = RenderKeyAsGlyph
|
||||
? (Style)Application.Current.Resources["GlyphKeyCharPresenterStyle"]
|
||||
: (Style)Application.Current.Resources["DefaultKeyCharPresenterStyle"];
|
||||
}
|
||||
|
||||
private void KeyVisual_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
SetVisualStates();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<UserControl
|
||||
x:Class="ShortcutGuide.Controls.TaskbarIndicator"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:ShortcutGuide"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d">
|
||||
<Grid HorizontalAlignment="Stretch">
|
||||
<Border
|
||||
x:Name="IndicatorRectangle"
|
||||
Width="36"
|
||||
Height="36"
|
||||
Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource ControlElevationBorderBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}">
|
||||
<TextBlock
|
||||
x:Name="IndicatorText"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
Style="{ThemeResource BodyStrongTextBlockStyle}"
|
||||
Text="{x:Bind Label, Mode=OneWay}"
|
||||
TextAlignment="Center" />
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
</UserControl>
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Globalization;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace ShortcutGuide.Controls;
|
||||
|
||||
public sealed partial class TaskbarIndicator : UserControl
|
||||
{
|
||||
public string Label
|
||||
{
|
||||
get => (string)GetValue(LabelProperty);
|
||||
set => SetValue(LabelProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LabelProperty = DependencyProperty.Register(nameof(Label), typeof(string), typeof(TaskbarIndicator), new PropertyMetadata(default(string)));
|
||||
|
||||
public TaskbarIndicator()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<winuiex:WindowEx
|
||||
x:Class="ShortcutGuide.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:models="using:ShortcutGuide.Models"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
Width="586"
|
||||
IsMaximizable="False"
|
||||
IsMinimizable="False"
|
||||
IsResizable="False"
|
||||
IsShownInSwitchers="False"
|
||||
mc:Ignorable="d">
|
||||
<winuiex:WindowEx.SystemBackdrop>
|
||||
<DesktopAcrylicBackdrop />
|
||||
</winuiex:WindowEx.SystemBackdrop>
|
||||
<Page x:Name="MainPage">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="48" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TitleBar x:Uid="TitleBar">
|
||||
<!--<TitleBar.Content>
|
||||
|
||||
<AutoSuggestBox
|
||||
x:Name="SearchBox"
|
||||
x:Uid="SearchBox"
|
||||
Width="300"
|
||||
VerticalAlignment="Center"
|
||||
QueryIcon="Find"
|
||||
TextChanged="SearchBox_TextChanged">
|
||||
<AutoSuggestBox.KeyboardAccelerators>
|
||||
<KeyboardAccelerator
|
||||
Key="F"
|
||||
Invoked="SearchBox_KeyboardAcceleratorInvoked"
|
||||
Modifiers="Control" />
|
||||
</AutoSuggestBox.KeyboardAccelerators>
|
||||
<AutoSuggestBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:ShortcutEntry">
|
||||
<Grid>
|
||||
<TextBlock Text="{x:Bind Name}" />
|
||||
TO DO: Add shortcuts / description
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</AutoSuggestBox.ItemTemplate>
|
||||
</AutoSuggestBox>
|
||||
</TitleBar.Content>-->
|
||||
</TitleBar>
|
||||
|
||||
<NavigationView
|
||||
x:Name="WindowSelector"
|
||||
Grid.Row="1"
|
||||
IsBackButtonVisible="Collapsed"
|
||||
IsPaneToggleButtonVisible="False"
|
||||
IsSettingsVisible="False"
|
||||
SelectionChanged="WindowSelector_SelectionChanged"
|
||||
Style="{StaticResource RailNavigationViewStyle}">
|
||||
<NavigationView.MenuItems />
|
||||
<NavigationView.FooterMenuItems>
|
||||
<!-- If footer only has one item, a visual bug can occur. This fake settings button will have set height to zero as soon as the content is loaded -->
|
||||
<NavigationViewItem
|
||||
x:Name="FakeSettingsButton"
|
||||
Icon="Setting"
|
||||
SelectsOnInvoked="False"
|
||||
Tag="Settings"
|
||||
Tapped="Settings_Tapped" />
|
||||
<NavigationViewItem
|
||||
x:Uid="SettingsButton"
|
||||
Icon="Setting"
|
||||
SelectsOnInvoked="False"
|
||||
Tag="Settings"
|
||||
Tapped="Settings_Tapped" />
|
||||
</NavigationView.FooterMenuItems>
|
||||
<NavigationView.Content>
|
||||
<NavigationView
|
||||
x:Name="SubNav"
|
||||
IsBackButtonVisible="Collapsed"
|
||||
IsSettingsVisible="False"
|
||||
PaneDisplayMode="Top"
|
||||
SelectionChanged="SubNav_SelectionChanged">
|
||||
<Frame
|
||||
x:Name="ContentFrame"
|
||||
Margin="4,8,0,0"
|
||||
Background="{ThemeResource AcrylicBackgroundFillColorDefaultBrush}"
|
||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||
BorderThickness="1"
|
||||
CornerRadius="8,0,0,0" />
|
||||
</NavigationView>
|
||||
</NavigationView.Content>
|
||||
<NavigationView.Resources>
|
||||
<SolidColorBrush x:Key="NavigationViewContentBackground" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="NavigationViewContentGridBorderBrush" Color="Transparent" />
|
||||
</NavigationView.Resources>
|
||||
</NavigationView>
|
||||
</Grid>
|
||||
</Page>
|
||||
</winuiex:WindowEx>
|
||||
@@ -0,0 +1,307 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Common.UI;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using ShortcutGuide.Helpers;
|
||||
using ShortcutGuide.Models;
|
||||
using ShortcutGuide.Pages;
|
||||
using Windows.Foundation;
|
||||
using Windows.Graphics;
|
||||
using Windows.System;
|
||||
using Windows.UI.WindowManagement;
|
||||
using WinRT.Interop;
|
||||
using WinUIEx;
|
||||
using WinUIEx.Messaging;
|
||||
|
||||
namespace ShortcutGuide
|
||||
{
|
||||
public sealed partial class MainWindow : WindowEx
|
||||
{
|
||||
private readonly string[] _currentApplicationIds;
|
||||
private ShortcutFile? _shortcutFile;
|
||||
private string _selectedAppName = null!;
|
||||
|
||||
private bool _setPosition;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
_currentApplicationIds = ManifestInterpreter.GetAllCurrentApplicationIds();
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
Title = ResourceLoaderInstance.ResourceLoader.GetString("Title")!;
|
||||
ExtendsContentIntoTitleBar = true;
|
||||
|
||||
#if !DEBUG
|
||||
this.SetIsAlwaysOnTop(true);
|
||||
this.SetIsShownInSwitchers(false);
|
||||
#endif
|
||||
WindowMessageMonitor msgMonitor = new(this);
|
||||
msgMonitor.WindowMessageReceived += (_, e) =>
|
||||
{
|
||||
const int WM_NCLBUTTONDBLCLK = 0x00A3;
|
||||
if (e.Message.MessageId == WM_NCLBUTTONDBLCLK)
|
||||
{
|
||||
// Disable double click on title bar to maximize window
|
||||
e.Result = 0;
|
||||
e.Handled = true;
|
||||
}
|
||||
};
|
||||
|
||||
Activated += Window_Activated;
|
||||
|
||||
Content.KeyUp += (_, e) =>
|
||||
{
|
||||
if (e.Key == VirtualKey.Escape)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
|
||||
switch (App.ShortcutGuideProperties.Theme.Value)
|
||||
{
|
||||
case "dark":
|
||||
((FrameworkElement)Content).RequestedTheme = ElementTheme.Dark;
|
||||
MainPage.RequestedTheme = ElementTheme.Dark;
|
||||
break;
|
||||
case "light":
|
||||
((FrameworkElement)Content).RequestedTheme = ElementTheme.Light;
|
||||
MainPage.RequestedTheme = ElementTheme.Light;
|
||||
break;
|
||||
case "system":
|
||||
// Ignore, as the theme will be set by the system.
|
||||
break;
|
||||
default:
|
||||
Logger.LogError("Invalid theme value in settings: " + App.ShortcutGuideProperties.Theme.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnStateChanged(WindowState state)
|
||||
{
|
||||
if (state == WindowState.Maximized)
|
||||
{
|
||||
SetWindowPosition();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPositionChanged(PointInt32 position)
|
||||
{
|
||||
SetWindowPosition();
|
||||
}
|
||||
|
||||
private void Window_Activated(object sender, WindowActivatedEventArgs e)
|
||||
{
|
||||
if (e.WindowActivationState == WindowActivationState.Deactivated && !_taskBarWindowActivated)
|
||||
{
|
||||
#if !DEBUG
|
||||
Close();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (_taskBarWindowActivated)
|
||||
{
|
||||
_taskBarWindowActivated = false;
|
||||
this.BringToFront();
|
||||
}
|
||||
|
||||
// The code below sets the position of the window to the center of the monitor, but only if it hasn't been set before.
|
||||
if (!_setPosition)
|
||||
{
|
||||
Content.GettingFocus += (_, _) =>
|
||||
{
|
||||
FakeSettingsButton.Height = 10;
|
||||
FakeSettingsButton.Height = 0;
|
||||
};
|
||||
|
||||
SetWindowPosition();
|
||||
_setPosition = true;
|
||||
|
||||
AppWindow.Changed += (_, a) =>
|
||||
{
|
||||
if (!a.DidPresenterChange)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SetWindowPosition();
|
||||
};
|
||||
}
|
||||
|
||||
SetNavItems();
|
||||
}
|
||||
|
||||
private void SetNavItems()
|
||||
{
|
||||
// Populate the window selector with the current application IDs if it is empty.
|
||||
// TO DO: Check if Settings button is considered an item too.
|
||||
if (WindowSelector.MenuItems.Count == 0)
|
||||
{
|
||||
foreach (var item in _currentApplicationIds)
|
||||
{
|
||||
if (item == ManifestInterpreter.GetIndexYamlFile().DefaultShellName)
|
||||
{
|
||||
WindowSelector.MenuItems.Add(new NavigationViewItem { Name = item, Content = "Windows", Icon = new FontIcon() { Glyph = "\xE770" } });
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
WindowSelector.MenuItems.Add(new NavigationViewItem { Name = item, Content = ManifestInterpreter.GetShortcutsOfApplication(item).Name, Icon = new FontIcon { Glyph = "\uEB91" } });
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WindowSelector.SelectedItem = WindowSelector.MenuItems[0];
|
||||
}
|
||||
}
|
||||
|
||||
private bool _hasMovedToRightMonitor;
|
||||
|
||||
private void SetWindowPosition()
|
||||
{
|
||||
if (!_hasMovedToRightMonitor)
|
||||
{
|
||||
NativeMethods.GetCursorPos(out NativeMethods.POINT lpPoint);
|
||||
AppWindow.Move(new NativeMethods.POINT { Y = lpPoint.Y - ((int)Height / 2), X = lpPoint.X - ((int)Width / 2) });
|
||||
_hasMovedToRightMonitor = true;
|
||||
}
|
||||
|
||||
var hwnd = WindowNative.GetWindowHandle(this);
|
||||
float dpi = DpiHelper.GetDPIScaleForWindow(hwnd.ToInt32());
|
||||
Rect monitorRect = DisplayHelper.GetWorkAreaForDisplayWithWindow(hwnd);
|
||||
if (App.TaskBarWindow.AppWindow.IsVisible && App.TaskBarWindow.AppWindow.Position.X < AppWindow.Position.X + Width)
|
||||
{
|
||||
MaxHeight = (monitorRect.Height / dpi) - App.TaskBarWindow.AppWindow.Size.Height;
|
||||
MinHeight = MaxHeight;
|
||||
Height = MaxHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
MaxHeight = monitorRect.Height / DpiHelper.GetDPIScaleForWindow(hwnd.ToInt32());
|
||||
MinHeight = MaxHeight;
|
||||
Height = MaxHeight;
|
||||
}
|
||||
|
||||
this.MoveAndResize((int)monitorRect.X, (int)monitorRect.Y, Width, Height);
|
||||
}
|
||||
|
||||
/*private void SearchBox_TextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
|
||||
{
|
||||
// TO DO: should the results of this be shown on a separate results page? Or as part of the suggested items of the search box?
|
||||
// The current UX is a bit weird as search is about the content that is selected on the page, vs. global search (which a search box in the title bar communicates).
|
||||
// Also, the results indicate that they can be clicked - but they cannot, so this needs more UX thinking on having the right model.
|
||||
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput && !string.IsNullOrWhiteSpace(SearchBox.Text))
|
||||
{
|
||||
ObservableCollection<ShortcutEntry> searchResults = new ObservableCollection<ShortcutEntry>();
|
||||
|
||||
if (_shortcutFile is ShortcutFile file)
|
||||
{
|
||||
foreach (var shortcut in file.Shortcuts.SelectMany(list => list.Properties.Where(s => s.Name.Contains(SearchBox.Text, StringComparison.InvariantCultureIgnoreCase))))
|
||||
{
|
||||
searchResults.Add(shortcut);
|
||||
}
|
||||
|
||||
SearchBox.ItemsSource = searchResults;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SearchBox_KeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
||||
{
|
||||
SearchBox.Focus(FocusState.Programmatic);
|
||||
}*/
|
||||
|
||||
private void WindowSelector_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
|
||||
{
|
||||
if (args.SelectedItem is NavigationViewItem selectedItem)
|
||||
{
|
||||
_selectedAppName = selectedItem.Name;
|
||||
_shortcutFile = ManifestInterpreter.GetShortcutsOfApplication(_selectedAppName);
|
||||
PopulateCategorySelector();
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateCategorySelector()
|
||||
{
|
||||
SubNav.MenuItems.Clear();
|
||||
SubNav.MenuItems.Add(new NavigationViewItem()
|
||||
{
|
||||
Content = ResourceLoaderInstance.ResourceLoader.GetString("Overview"),
|
||||
Tag = -1,
|
||||
});
|
||||
|
||||
int i = 0;
|
||||
|
||||
if (_shortcutFile is ShortcutFile file)
|
||||
{
|
||||
foreach (var category in file.Shortcuts)
|
||||
{
|
||||
switch (category.SectionName)
|
||||
{
|
||||
case { } name when name.StartsWith("<TASKBAR1-9>", StringComparison.Ordinal):
|
||||
break;
|
||||
case { } name when name.StartsWith('<') && name.EndsWith('>'):
|
||||
break;
|
||||
default:
|
||||
SubNav.MenuItems.Add(new NavigationViewItem() { Content = category.SectionName, Tag = i });
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (SubNav.MenuItems.Count > 0)
|
||||
{
|
||||
SubNav.SelectedItem = SubNav.MenuItems[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tracks whether the taskbar window was activated. So that the main window does not close.
|
||||
/// </summary>
|
||||
private bool _taskBarWindowActivated;
|
||||
|
||||
private void SubNav_SelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
|
||||
{
|
||||
if (args.SelectedItem is NavigationViewItem selectedItem && selectedItem.Tag is int param && _shortcutFile is ShortcutFile file)
|
||||
{
|
||||
Type selectedPage = typeof(ShortcutsPage);
|
||||
App.TaskBarWindow.Hide();
|
||||
if (param == -1)
|
||||
{
|
||||
selectedPage = typeof(OverviewPage);
|
||||
|
||||
// We only show the taskbar button window when the overview page of Windows is selected.
|
||||
if (_shortcutFile is not null && _shortcutFile.Value.Shortcuts.Any(c => c.SectionName.Contains("<TASKBAR1-9>")))
|
||||
{
|
||||
_taskBarWindowActivated = true;
|
||||
App.TaskBarWindow.Activate();
|
||||
}
|
||||
}
|
||||
|
||||
// Set window position so that the taskbar window does not potentially clip into the main window
|
||||
SetWindowPosition();
|
||||
ContentFrame.Navigate(selectedPage, new ShortcutPageNavParam() { ShortcutFile = file, PageIndex = param, AppName = _selectedAppName });
|
||||
}
|
||||
}
|
||||
|
||||
private void Settings_Tapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
SettingsDeepLink.OpenSettings(SettingsDeepLink.SettingsWindow.ShortcutGuide, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Page
|
||||
x:Class="ShortcutGuide.Pages.OverviewPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:ShortcutGuide.Controls"
|
||||
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:ShortcutGuide"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:models="using:ShortcutGuide.Models"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<DataTemplate x:Key="ShortcutItemTemplate" x:DataType="models:ShortcutEntry">
|
||||
<Grid
|
||||
Padding="16,8,16,8"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Tag="{x:Bind}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="160" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.ContextFlyout>
|
||||
<MenuFlyout Opening="PinFlyout_Opening">
|
||||
<MenuFlyoutItem
|
||||
Click="Pin_Click"
|
||||
CommandParameter="{x:Bind}"
|
||||
Text="Pin" />
|
||||
</MenuFlyout>
|
||||
</Grid.ContextFlyout>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Vertical">
|
||||
<TextBlock Text="{x:Bind Name}" TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Description}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{x:Bind Description, Converter={StaticResource StringVisibilityConverter}}" />
|
||||
</StackPanel>
|
||||
<ItemsControl
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:ShortcutDescription">
|
||||
<Grid>
|
||||
<ItemsControl Grid.Column="1" ItemsSource="{Binding Converter={StaticResource ShortcutDescriptionToKeysConverter}}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:KeyVisual
|
||||
Padding="4"
|
||||
Background="{ThemeResource ControlFillColorInputActiveBrush}"
|
||||
BorderBrush="{ThemeResource ControlElevationBorderBrush}"
|
||||
Content="{Binding}"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource DefaultKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</Page.Resources>
|
||||
<Grid>
|
||||
<ScrollViewer>
|
||||
<StackPanel
|
||||
Margin="0,16,0,0"
|
||||
Orientation="Vertical"
|
||||
Spacing="8">
|
||||
<TextBlock
|
||||
x:Name="RecommendedHeaderTxt"
|
||||
x:Uid="RecommendedHeaderTxt"
|
||||
Margin="16,0,16,8"
|
||||
FontWeight="SemiBold" />
|
||||
<ItemsRepeater
|
||||
ItemTemplate="{StaticResource ShortcutItemTemplate}"
|
||||
ItemsSource="{x:Bind _recommendedShortcuts, Mode=OneWay}"
|
||||
Visibility="{x:Bind _recommendedShortcuts.Count, Mode=OneWay, Converter={StaticResource DoubleToVisibilityConverter}}" />
|
||||
|
||||
<TextBlock
|
||||
x:Uid="NoRecommendedShortcuts"
|
||||
Margin="16,0,16,0"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Visibility="{x:Bind _recommendedShortcuts.Count, Mode=OneWay, Converter={StaticResource DoubleToInvertedVisibilityConverter}}" />
|
||||
|
||||
<TextBlock
|
||||
x:Name="PinnedHeaderTxt"
|
||||
x:Uid="PinnedHeaderTxt"
|
||||
Margin="16,24,16,0"
|
||||
FontWeight="SemiBold" />
|
||||
|
||||
<ItemsRepeater
|
||||
x:Name="PinnedShortcutsListView"
|
||||
ItemTemplate="{StaticResource ShortcutItemTemplate}"
|
||||
ItemsSource="{x:Bind _pinnedShortcuts, Mode=OneWay}"
|
||||
Visibility="{x:Bind PinnedShortcutsCount, Mode=OneWay, Converter={StaticResource DoubleToVisibilityConverter}}" />
|
||||
|
||||
<TextBlock
|
||||
x:Uid="PinnedEmptyText"
|
||||
Margin="16,0,16,8"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Visibility="{x:Bind PinnedShortcutsCount, Mode=OneWay, Converter={StaticResource DoubleToInvertedVisibilityConverter}}" />
|
||||
|
||||
<StackPanel
|
||||
x:Name="TaskbarShortcutsPanel"
|
||||
Orientation="Vertical"
|
||||
Visibility="Collapsed">
|
||||
<TextBlock
|
||||
x:Name="TaskbarHeaderTxt"
|
||||
x:Uid="TaskbarHeaderTxt"
|
||||
Margin="16,24,16,2"
|
||||
FontWeight="SemiBold" />
|
||||
<TextBlock x:Uid="TaskbarDescriptionTxt" Margin="16,2,16,12" />
|
||||
<ItemsRepeater
|
||||
x:Name="TaskbarShortcutsListView"
|
||||
ItemTemplate="{StaticResource ShortcutItemTemplate}"
|
||||
ItemsSource="{x:Bind _taskbarShortcuts, Mode=OneWay}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,86 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using ShortcutGuide.Helpers;
|
||||
using ShortcutGuide.Models;
|
||||
|
||||
namespace ShortcutGuide.Pages
|
||||
{
|
||||
public sealed partial class OverviewPage : Page, INotifyPropertyChanged
|
||||
{
|
||||
private ObservableCollection<ShortcutEntry>? _recommendedShortcuts;
|
||||
private ObservableCollection<ShortcutEntry>? _pinnedShortcuts;
|
||||
private ObservableCollection<ShortcutEntry>? _taskbarShortcuts;
|
||||
|
||||
private int PinnedShortcutsCount => _pinnedShortcuts?.Count ?? 0;
|
||||
|
||||
private string _appName = string.Empty;
|
||||
private ShortcutFile _shortcutFile;
|
||||
|
||||
public OverviewPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnPropertyChanged(string propertyName)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is ShortcutPageNavParam param)
|
||||
{
|
||||
_appName = param.AppName;
|
||||
_shortcutFile = param.ShortcutFile;
|
||||
_recommendedShortcuts = [.. _shortcutFile.Shortcuts.SelectMany(list => list.Properties.Where(s => s.Recommended))];
|
||||
if (App.PinnedShortcuts.TryGetValue(_appName, out var shortcuts))
|
||||
{
|
||||
_pinnedShortcuts = [.. shortcuts];
|
||||
}
|
||||
|
||||
if (_appName == ManifestInterpreter.GetIndexYamlFile().DefaultShellName)
|
||||
{
|
||||
TaskbarShortcutsPanel.Visibility = Visibility.Visible;
|
||||
_taskbarShortcuts =
|
||||
[
|
||||
.. _shortcutFile.Shortcuts.First(x => x.SectionName.StartsWith("<TASKBAR1-9>", StringComparison.InvariantCulture)).Properties,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void PinFlyout_Opening(object sender, object e)
|
||||
{
|
||||
if (sender is MenuFlyout fl && fl.Target is Grid g && g.Tag is ShortcutEntry dataObject && fl.Items[0] is MenuFlyoutItem pinItem)
|
||||
{
|
||||
bool isItemPinned = App.PinnedShortcuts[_appName].Any(x => x.Equals(dataObject));
|
||||
pinItem.Text = isItemPinned ? ResourceLoaderInstance.ResourceLoader.GetString("UnpinShortcut") : ResourceLoaderInstance.ResourceLoader.GetString("PinShortcut");
|
||||
pinItem.Icon = new SymbolIcon(isItemPinned ? Symbol.UnPin : Symbol.Pin);
|
||||
}
|
||||
}
|
||||
|
||||
private void Pin_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is MenuFlyoutItem { CommandParameter: ShortcutEntry shortcutEntry })
|
||||
{
|
||||
PinnedShortcutsHelper.UpdatePinnedShortcuts(_appName, shortcutEntry);
|
||||
|
||||
// Update ListView to reflect changes
|
||||
_pinnedShortcuts = [.. App.PinnedShortcuts[_appName]];
|
||||
PinnedShortcutsListView.ItemsSource = _pinnedShortcuts;
|
||||
OnPropertyChanged(nameof(PinnedShortcutsCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Page
|
||||
x:Class="ShortcutGuide.Pages.ShortcutsPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:ShortcutGuide.Controls"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:ShortcutGuide.Pages"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:models="using:ShortcutGuide.Models"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<DataTemplate x:Key="ShortcutItemTemplate" x:DataType="models:ShortcutEntry">
|
||||
<Grid
|
||||
Padding="16,8,16,8"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="0,0,0,1"
|
||||
Tag="{x:Bind}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="160" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.ContextFlyout>
|
||||
<MenuFlyout Opening="PinFlyout_Opening">
|
||||
<MenuFlyoutItem
|
||||
x:Uid="PinShortcut"
|
||||
Click="Pin_Click"
|
||||
CommandParameter="{x:Bind}" />
|
||||
</MenuFlyout>
|
||||
</Grid.ContextFlyout>
|
||||
<StackPanel
|
||||
Grid.Column="1"
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Vertical">
|
||||
<TextBlock Text="{x:Bind Name}" TextWrapping="Wrap" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Description}"
|
||||
TextWrapping="Wrap"
|
||||
Visibility="{x:Bind Description, Converter={StaticResource StringVisibilityConverter}}" />
|
||||
</StackPanel>
|
||||
<ItemsControl
|
||||
Grid.Column="0"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{x:Bind Shortcut}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Vertical" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="models:ShortcutDescription">
|
||||
<Grid>
|
||||
<ItemsControl Grid.Column="1" ItemsSource="{Binding Converter={StaticResource ShortcutDescriptionToKeysConverter}}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal" Spacing="4" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<controls:KeyVisual
|
||||
Padding="4"
|
||||
Background="{ThemeResource ControlFillColorInputActiveBrush}"
|
||||
BorderBrush="{ThemeResource ControlElevationBorderBrush}"
|
||||
Content="{Binding}"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}"
|
||||
FontSize="12"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource DefaultKeyVisualStyle}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</Page.Resources>
|
||||
<Grid>
|
||||
<ScrollViewer>
|
||||
<StackPanel
|
||||
Margin="0,16,0,0"
|
||||
Orientation="Vertical"
|
||||
Spacing="8">
|
||||
<ItemsRepeater
|
||||
ItemTemplate="{StaticResource ShortcutItemTemplate}"
|
||||
ItemsSource="{x:Bind _shortcuts, Mode=OneWay}"
|
||||
Visibility="{x:Bind _shortcuts.Count, Mode=OneWay, Converter={StaticResource DoubleToVisibilityConverter}}" />
|
||||
<TextBlock
|
||||
x:Uid="NoShortcuts"
|
||||
Margin="16,0,16,8"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Visibility="{x:Bind _shortcuts.Count, Mode=OneWay, Converter={StaticResource DoubleToInvertedVisibilityConverter}}" />
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,61 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using ShortcutGuide.Helpers;
|
||||
using ShortcutGuide.Models;
|
||||
using Windows.ApplicationModel.VoiceCommands;
|
||||
|
||||
namespace ShortcutGuide.Pages
|
||||
{
|
||||
public sealed partial class ShortcutsPage : Page
|
||||
{
|
||||
private ObservableCollection<ShortcutEntry>? _shortcuts;
|
||||
private string _appName = string.Empty;
|
||||
private ShortcutFile _shortcutFile;
|
||||
private int _pageIndex;
|
||||
|
||||
public ShortcutsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
if (e.Parameter is ShortcutPageNavParam param)
|
||||
{
|
||||
_appName = param.AppName;
|
||||
_shortcutFile = param.ShortcutFile;
|
||||
_pageIndex = param.PageIndex;
|
||||
_shortcuts = [.. _shortcutFile.Shortcuts[_pageIndex].Properties ?? Enumerable.Empty<ShortcutEntry>()];
|
||||
}
|
||||
}
|
||||
|
||||
private void PinFlyout_Opening(object sender, object e)
|
||||
{
|
||||
if (sender is MenuFlyout fl && fl.Target is Grid g && g.Tag is ShortcutEntry dataObject && fl.Items[0] is MenuFlyoutItem pinItem)
|
||||
{
|
||||
bool isItemPinned = App.PinnedShortcuts[_appName].Any(x => x.Equals(dataObject));
|
||||
pinItem.Text = isItemPinned ? ResourceLoaderInstance.ResourceLoader.GetString("UnpinShortcut") : ResourceLoaderInstance.ResourceLoader.GetString("PinShortcut");
|
||||
pinItem.Icon = new SymbolIcon(isItemPinned ? Symbol.UnPin : Symbol.Pin);
|
||||
}
|
||||
}
|
||||
|
||||
private void Pin_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is MenuFlyoutItem { CommandParameter: ShortcutEntry shortcutEntry })
|
||||
{
|
||||
PinnedShortcutsHelper.UpdatePinnedShortcuts(_appName, shortcutEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<winuiex:WindowEx
|
||||
x:Class="ShortcutGuide.ShortcutGuideXAML.TaskbarWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:ShortcutGuide"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
Title="TaskbarWindow"
|
||||
Width="600"
|
||||
Height="200"
|
||||
IsAlwaysOnTop="True"
|
||||
IsMaximizable="False"
|
||||
IsMinimizable="False"
|
||||
IsResizable="False"
|
||||
IsShownInSwitchers="False"
|
||||
IsTitleBarVisible="False"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Window.SystemBackdrop>
|
||||
<DesktopAcrylicBackdrop />
|
||||
</Window.SystemBackdrop>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition x:Name="WindowsLogoColumnWidth" Width="68" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Canvas x:Name="KeyHolder" Grid.Column="1" />
|
||||
<StackPanel
|
||||
Margin="8"
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<Border
|
||||
Width="34"
|
||||
Height="34"
|
||||
Padding="8"
|
||||
BorderBrush="{ThemeResource ControlElevationBorderBrush}"
|
||||
BorderThickness="0"
|
||||
CornerRadius="{StaticResource ControlCornerRadius}">
|
||||
<Viewbox>
|
||||
<PathIcon Data="M9 20H0V11H9V20ZM20 20H11V11H20V20ZM9 9H0V0H9V9ZM20 9H11V0H20V9Z" />
|
||||
</Viewbox>
|
||||
</Border>
|
||||
<TextBlock
|
||||
Margin="0,-3,0,0"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
FontWeight="SemiBold"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="+" />
|
||||
</StackPanel>
|
||||
|
||||
</Grid>
|
||||
</winuiex:WindowEx>
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Globalization;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Microsoft.UI.Xaml.Shapes;
|
||||
using ShortcutGuide.Controls;
|
||||
using ShortcutGuide.Helpers;
|
||||
using Windows.Foundation;
|
||||
using WinRT.Interop;
|
||||
using WinUIEx;
|
||||
using static ShortcutGuide.NativeMethods;
|
||||
|
||||
namespace ShortcutGuide.ShortcutGuideXAML
|
||||
{
|
||||
public sealed partial class TaskbarWindow : WindowEx
|
||||
{
|
||||
private float DPI => DpiHelper.GetDPIScaleForWindow(WindowNative.GetWindowHandle(this).ToInt32());
|
||||
|
||||
private Rect WorkArea => DisplayHelper.GetWorkAreaForDisplayWithWindow(WindowNative.GetWindowHandle(this));
|
||||
|
||||
public TaskbarWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
UpdateTasklistButtons();
|
||||
this.Activated += (_, _) => UpdateTasklistButtons();
|
||||
}
|
||||
|
||||
public void UpdateTasklistButtons()
|
||||
{
|
||||
// This move ensures the window spawns on the same monitor as the main window
|
||||
AppWindow.MoveInZOrderAtBottom();
|
||||
AppWindow.Move(App.MainWindow.AppWindow.Position);
|
||||
|
||||
TasklistButton[] buttons = TasklistPositions.GetButtons();
|
||||
double windowsLogoColumnWidth = WindowsLogoColumnWidth.Width.Value;
|
||||
double windowHeight = 58;
|
||||
double windowMargin = 8 * DPI;
|
||||
double windowWidth = windowsLogoColumnWidth;
|
||||
double xPosition = buttons[0].X - (windowsLogoColumnWidth * DPI);
|
||||
double yPosition = WorkArea.Bottom - (windowHeight * DPI);
|
||||
|
||||
KeyHolder.Children.Clear();
|
||||
|
||||
foreach (TasklistButton b in buttons)
|
||||
{
|
||||
TaskbarIndicator indicator = new()
|
||||
{
|
||||
Label = b.Keynum >= 10 ? "0" : b.Keynum.ToString(CultureInfo.InvariantCulture),
|
||||
Height = b.Height / DPI,
|
||||
Width = b.Width / DPI,
|
||||
};
|
||||
|
||||
windowWidth += indicator.Width;
|
||||
|
||||
KeyHolder.Children.Add(indicator);
|
||||
|
||||
double indicatorPos = (b.X - xPosition) / DPI;
|
||||
Canvas.SetLeft(indicator, indicatorPos - windowsLogoColumnWidth);
|
||||
}
|
||||
|
||||
this.MoveAndResize(xPosition - windowMargin, yPosition, windowWidth + (2 * windowMargin), windowHeight);
|
||||
AppWindow.MoveInZOrderAtTop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
@@ -117,55 +117,94 @@
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Setting_Description_Overlay_Opacity" xml:space="preserve">
|
||||
<value>Opacity of the Shortcut Guide's overlay background (%)</value>
|
||||
<data name="CloseButton.ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Close</value>
|
||||
</data>
|
||||
<data name="Setting_Description_Theme" xml:space="preserve">
|
||||
<value>Choose Shortcut Guide overlay color</value>
|
||||
<data name="ErrorInAppParsing" xml:space="preserve">
|
||||
<value>Error displaying the application's shortcuts</value>
|
||||
<comment>Shortcuts refers to keyboard shortcuts; Application refers to a PC application</comment>
|
||||
</data>
|
||||
<data name="Setting_Description_Theme_Light" xml:space="preserve">
|
||||
<value>Light</value>
|
||||
<data name="ErrorInCategoryParsing" xml:space="preserve">
|
||||
<value>There has been an error displaying this category</value>
|
||||
</data>
|
||||
<data name="Setting_Description_Theme_Dark" xml:space="preserve">
|
||||
<value>Dark</value>
|
||||
<data name="InformationButton.ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Open additional information</value>
|
||||
</data>
|
||||
<data name="Setting_Description_Theme_System" xml:space="preserve">
|
||||
<value>System default app mode</value>
|
||||
<data name="InformationTip.Title" xml:space="preserve">
|
||||
<value>Additional information</value>
|
||||
</data>
|
||||
<data name="Settings_Description" xml:space="preserve">
|
||||
<value>Shows a help overlay with Windows shortcuts when the Windows key is pressed.</value>
|
||||
<data name="InformationTip1.Text" xml:space="preserve">
|
||||
<value>This app may display content provided by third-party sources. Microsoft does not endorse or assume responsibility for the accuracy, reliability, or legality of such content.</value>
|
||||
</data>
|
||||
<data name="Shortcut_Guide" xml:space="preserve">
|
||||
<data name="InformationTip2.Text" xml:space="preserve">
|
||||
<value>The content related to Windows is always based on the latest release build of Windows.</value>
|
||||
</data>
|
||||
<data name="Overview" xml:space="preserve">
|
||||
<value>Overview</value>
|
||||
<comment>Category title</comment>
|
||||
</data>
|
||||
<data name="PinnedHeaderTxt.Text" xml:space="preserve">
|
||||
<value>Pinned Shortcuts</value>
|
||||
<comment>Shortcuts refers to keyboard shortcuts</comment>
|
||||
</data>
|
||||
<data name="PinShortcut" xml:space="preserve">
|
||||
<value>Pin</value>
|
||||
<comment>Refers to the action of pinning something on a pin board</comment>
|
||||
</data>
|
||||
<data name="RecommendedHeaderText.Text" xml:space="preserve">
|
||||
<value>Recommended Shortcuts</value>
|
||||
<comment>Shortcuts refers to keyboard shortcuts</comment>
|
||||
</data>
|
||||
<data name="SearchBlank" xml:space="preserve">
|
||||
<value>No results found</value>
|
||||
<comment>Results refers to search results</comment>
|
||||
</data>
|
||||
<data name="SearchBox.PlaceholderText" xml:space="preserve">
|
||||
<value>Search shortcuts</value>
|
||||
</data>
|
||||
<data name="SettingsButton.ToolTipService.ToolTip" xml:space="preserve">
|
||||
<value>Open settings</value>
|
||||
</data>
|
||||
<data name="TaskbarLaunchShortcutsDescription.Text" xml:space="preserve">
|
||||
<value>Use these keys together with a number displayed below</value>
|
||||
<comment>keys refers to keyboard keys</comment>
|
||||
</data>
|
||||
<data name="TaskbarHeaderTxt.Text" xml:space="preserve">
|
||||
<value>Taskbar Shortcuts</value>
|
||||
<comment>Shortcuts refers to keyboard shortcuts</comment>
|
||||
</data>
|
||||
<data name="Title" xml:space="preserve">
|
||||
<value>Shortcut Guide</value>
|
||||
<comment>Shortcut refers to a keyboard shortcut</comment>
|
||||
</data>
|
||||
<data name="No_Action" xml:space="preserve">
|
||||
<value>No action</value>
|
||||
<data name="UnpinShortcut" xml:space="preserve">
|
||||
<value>Unpin</value>
|
||||
<comment>Refers to the action of unpinning something from a pin board</comment>
|
||||
</data>
|
||||
<data name="Restore" xml:space="preserve">
|
||||
<value>Restore</value>
|
||||
<data name="Welcome" xml:space="preserve">
|
||||
<value>Welcome</value>
|
||||
</data>
|
||||
<data name="Snap_Right" xml:space="preserve">
|
||||
<value>Snap right</value>
|
||||
<data name="PinnedEmptyText.Text" xml:space="preserve">
|
||||
<value>No pinned shortcuts</value>
|
||||
</data>
|
||||
<data name="Snap_Left" xml:space="preserve">
|
||||
<value>Snap left</value>
|
||||
<data name="NoShortcuts.Text" xml:space="preserve">
|
||||
<value>No shortcuts available</value>
|
||||
</data>
|
||||
<data name="Snap_Upper_Right" xml:space="preserve">
|
||||
<value>Snap upper right</value>
|
||||
<data name="NoRecommendedShortcuts.Text" xml:space="preserve">
|
||||
<value>No recommended shortcuts available</value>
|
||||
</data>
|
||||
<data name="Snap_Upper_Left" xml:space="preserve">
|
||||
<value>Snap upper left</value>
|
||||
<data name="Titlebar.Title" xml:space="preserve">
|
||||
<value>Shortcut Guide</value>
|
||||
<comment>Shortcut refers to a keyboard shortcut</comment>
|
||||
</data>
|
||||
<data name="Snap_Lower_Right" xml:space="preserve">
|
||||
<value>Snap lower right</value>
|
||||
<data name="TaskbarDescriptionTxt.Text" xml:space="preserve">
|
||||
<value>In combination with the number shown above the taskbar</value>
|
||||
</data>
|
||||
<data name="Snap_Lower_Left" xml:space="preserve">
|
||||
<value>Snap lower left</value>
|
||||
<data name="UnderlinedKeyChar.Text" xml:space="preserve">
|
||||
<value>Underlined character</value>
|
||||
<comment>character meaning a letter</comment>
|
||||
</data>
|
||||
<data name="Minimize" xml:space="preserve">
|
||||
<value>Minimize</value>
|
||||
</data>
|
||||
<data name="Maximize" xml:space="preserve">
|
||||
<value>Maximize</value>
|
||||
<data name="SettingsButton.Content" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
</root>
|
||||
22
src/modules/ShortcutGuide/ShortcutGuide.Ui/app.manifest
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0"
|
||||
xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="ShortcutGuide.app"/>
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- The combination of below two tags have the following effect:
|
||||
1) Per-Monitor for >= Windows 10 Anniversary Update
|
||||
2) System < Windows 10 Anniversary Update
|
||||
-->
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2, PerMonitor</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<!-- Windows 10 -->
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB |
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB |
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.8 KiB |
@@ -1,21 +0,0 @@
|
||||
<?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>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 178 KiB |
|
Before Width: | Height: | Size: 179 KiB |
@@ -1,16 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<!--
|
||||
To customize common C++/WinRT project properties:
|
||||
* right-click the project node
|
||||
* expand the Common Properties item
|
||||
* select the C++/WinRT property page
|
||||
|
||||
For more advanced scenarios, and complete documentation, please see:
|
||||
https://github.com/Microsoft/cppwinrt/tree/master/nuget
|
||||
-->
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup />
|
||||
</Project>
|
||||
@@ -1,54 +0,0 @@
|
||||
#include <windows.h>
|
||||
#include "Generated Files/resource.h"
|
||||
#include "../../../../common/version/version.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
#include "winres.h"
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON "Shortcut-Guide.ico"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Version
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION FILE_VERSION
|
||||
PRODUCTVERSION PRODUCT_VERSION
|
||||
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS VS_FF_DEBUG
|
||||
#else
|
||||
FILEFLAGS 0x0L
|
||||
#endif
|
||||
FILEOS VOS_NT_WINDOWS32
|
||||
FILETYPE VFT_DLL
|
||||
FILESUBTYPE VFT2_UNKNOWN
|
||||
BEGIN
|
||||
BLOCK "StringFileInfo"
|
||||
BEGIN
|
||||
BLOCK "040904b0"
|
||||
BEGIN
|
||||
VALUE "CompanyName", COMPANY_NAME
|
||||
VALUE "FileDescription", FILE_DESCRIPTION
|
||||
VALUE "FileVersion", FILE_VERSION_STRING
|
||||
VALUE "InternalName", INTERNAL_NAME
|
||||
VALUE "LegalCopyright", COPYRIGHT_NOTE
|
||||
VALUE "OriginalFilename", ORIGINAL_FILENAME
|
||||
VALUE "ProductName", PRODUCT_NAME
|
||||
VALUE "ProductVersion", PRODUCT_VERSION_STRING
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
BEGIN
|
||||
VALUE "Translation", 0x409, 1200
|
||||
END
|
||||
END
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
@@ -1,193 +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.240111.5\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory) resource.base.h resource.h ShortcutGuide.base.rc ShortcutGuide.rc" />
|
||||
</Target>
|
||||
<PropertyGroup Label="Globals">
|
||||
<CppWinRTOptimized>true</CppWinRTOptimized>
|
||||
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
|
||||
<CppWinRTGenerateWindowsMetadata>true</CppWinRTGenerateWindowsMetadata>
|
||||
<MinimalCoreWin>true</MinimalCoreWin>
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{2edb3eb4-fa92-4bff-b2d8-566584837231}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ShortcutGuide</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)' == '15.0'">v141</PlatformToolset>
|
||||
<PlatformToolset Condition="'$(VisualStudioVersion)' == '16.0'">v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'" Label="Configuration">
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Release'" Label="Configuration">
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="PropertySheet.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<TargetName>PowerToys.$(MSBuildProjectName)</TargetName>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutDir>..\..\..\..\$(Platform)\$(Configuration)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>;..\..\..\common\inc;..\..\..\common\Telemetry;..\..\..\;..\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>ole32.lib;Shell32.lib;OleAut32.lib;Dbghelp.lib;Dwmapi.lib;Dcomp.lib;Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="animation.h" />
|
||||
<ClInclude Include="d2d_svg.h" />
|
||||
<ClInclude Include="d2d_text.h" />
|
||||
<ClInclude Include="d2d_window.h" />
|
||||
<ClInclude Include="Generated Files\resource.h" />
|
||||
<ClInclude Include="native_event_waiter.h" />
|
||||
<ClInclude Include="overlay_window.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
<ClInclude Include="resource.base.h" />
|
||||
<ClInclude Include="ShortcutGuideSettings.h" />
|
||||
<ClInclude Include="ShortcutGuideConstants.h" />
|
||||
<ClInclude Include="shortcut_guide.h" />
|
||||
<ClInclude Include="start_visible.h" />
|
||||
<ClInclude Include="target_state.h" />
|
||||
<ClInclude Include="tasklist_positions.h" />
|
||||
<ClInclude Include="trace.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="animation.cpp" />
|
||||
<ClCompile Include="d2d_svg.cpp" />
|
||||
<ClCompile Include="d2d_text.cpp" />
|
||||
<ClCompile Include="d2d_window.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="native_event_waiter.cpp" />
|
||||
<ClCompile Include="overlay_window.cpp" />
|
||||
<ClCompile Include="pch.cpp">
|
||||
<PrecompiledHeader Condition="'$(UsePrecompiledHeaders)' != 'false'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shortcut_guide.cpp" />
|
||||
<ClCompile Include="start_visible.cpp" />
|
||||
<ClCompile Include="target_state.cpp" />
|
||||
<ClCompile Include="tasklist_positions.cpp" />
|
||||
<ClCompile Include="trace.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
<None Include="PropertySheet.props" />
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\0.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\1.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\2.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\3.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\4.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\5.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\6.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\7.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\8.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\9.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\no_active_window.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\overlay.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\overlay_portrait.svg">
|
||||
<FileType>Document</FileType>
|
||||
<DestinationFolders>$(OutDir)\Assets\ShortcutGuide</DestinationFolders>
|
||||
</CopyFileToFolders>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\common\Display\Display.vcxproj">
|
||||
<Project>{caba8dfb-823b-4bf2-93ac-3f31984150d9}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\logger\logger.vcxproj">
|
||||
<Project>{d9b8fc84-322a-4f9f-bbb9-20915c47ddfd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\SettingsAPI\SettingsAPI.vcxproj">
|
||||
<Project>{6955446d-23f7-4023-9bb3-8657f904af99}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\Telemetry\EtwTrace\EtwTrace.vcxproj">
|
||||
<Project>{8f021b46-362b-485c-bfba-ccf83e820cbd}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\..\common\Themes\Themes.vcxproj">
|
||||
<Project>{98537082-0fdb-40de-abd8-0dc5a4269bab}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources.resx" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files\ShortcutGuide.rc" />
|
||||
<None Include="ShortcutGuide.base.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Shortcut-Guide.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="ShortcutGuide.exe.manifest" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
</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.240111.5\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.240111.5\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,141 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;svg;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Generated Files">
|
||||
<UniqueIdentifier>{cb917ac7-30da-494b-81f1-cbe4415e91f4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="animation.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d2d_svg.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d2d_text.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="d2d_window.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="native_event_waiter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="overlay_window.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="shortcut_guide.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ShortcutGuideConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="start_visible.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="target_state.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="tasklist_positions.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="trace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.base.h">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Generated Files\resource.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ShortcutGuideSettings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="animation.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d2d_svg.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d2d_text.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="d2d_window.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="native_event_waiter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="overlay_window.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="shortcut_guide.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="start_visible.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="target_state.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="tasklist_positions.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="trace.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="PropertySheet.props" />
|
||||
<None Include="ShortcutGuide.base.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CopyFileToFolders Include="Assets\ShortcutGuide\**">
|
||||
<Filter>Resource Files</Filter>
|
||||
</CopyFileToFolders>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resources.resx">
|
||||
<Filter>Resource Files</Filter>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Generated Files\ShortcutGuide.rc">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Shortcut-Guide.ico">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Manifest Include="ShortcutGuide.exe.manifest" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace ShortcutGuideConstants
|
||||
{
|
||||
// Name of the powertoy module.
|
||||
inline const std::wstring ModuleKey = L"Shortcut Guide";
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
|
||||
struct ShortcutGuideSettings
|
||||
{
|
||||
std::wstring hotkey = L"shift+win+/";
|
||||
int overlayOpacity = 90;
|
||||
std::wstring theme = L"system";
|
||||
std::wstring disabledApps = L"";
|
||||
bool shouldReactToPressedWinKey = false;
|
||||
int windowsKeyPressTimeForGlobalWindowsShortcuts = 900;
|
||||
int windowsKeyPressTimeForTaskbarIconShortcuts = 900;
|
||||
};
|
||||
@@ -1,51 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "animation.h"
|
||||
|
||||
Animation::Animation(double duration, double start, double stop) :
|
||||
duration(duration), start_value(start), end_value(stop), start(std::chrono::high_resolution_clock::now()) {}
|
||||
|
||||
void Animation::reset()
|
||||
{
|
||||
start = std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
void Animation::reset(double animation_duration)
|
||||
{
|
||||
duration = animation_duration;
|
||||
reset();
|
||||
}
|
||||
void Animation::reset(double animation_duration, double animation_start, double animation_stop)
|
||||
{
|
||||
start_value = animation_start;
|
||||
end_value = animation_stop;
|
||||
reset(animation_duration);
|
||||
}
|
||||
|
||||
static double ease_out_expo(double t)
|
||||
{
|
||||
return 1 - pow(2, -8 * t);
|
||||
}
|
||||
|
||||
double Animation::apply_animation_function(double t, AnimFunctions apply_function)
|
||||
{
|
||||
switch (apply_function)
|
||||
{
|
||||
case EASE_OUT_EXPO:
|
||||
return ease_out_expo(t);
|
||||
case LINEAR:
|
||||
default:
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
double Animation::value(AnimFunctions apply_function) const
|
||||
{
|
||||
auto anim_duration = std::chrono::high_resolution_clock::now() - start;
|
||||
double t = std::chrono::duration<double>(anim_duration).count() / duration;
|
||||
if (t >= 1)
|
||||
return end_value;
|
||||
return start_value + (end_value - start_value) * apply_animation_function(t, apply_function);
|
||||
}
|
||||
bool Animation::done() const
|
||||
{
|
||||
return std::chrono::high_resolution_clock::now() - start >= std::chrono::duration<double>(duration);
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#pragma once
|
||||
#include <chrono>
|
||||
|
||||
/*
|
||||
Usage:
|
||||
When creating animation constructor takes one parameter - how long
|
||||
should the animation take in seconds.
|
||||
|
||||
Call reset() when starting animation.
|
||||
|
||||
When rendering, call value() to get value from 0 to 1 - depending on animation
|
||||
progress.
|
||||
*/
|
||||
class Animation
|
||||
{
|
||||
public:
|
||||
enum AnimFunctions
|
||||
{
|
||||
LINEAR = 0,
|
||||
EASE_OUT_EXPO
|
||||
};
|
||||
|
||||
Animation(double duration = 1, double start = 0, double stop = 1);
|
||||
void reset();
|
||||
void reset(double animation_duration);
|
||||
void reset(double animation_duration, double animation_start, double animation_stop);
|
||||
double value(AnimFunctions apply_function) const;
|
||||
bool done() const;
|
||||
|
||||
private:
|
||||
static double apply_animation_function(double t, AnimFunctions apply_function);
|
||||
std::chrono::high_resolution_clock::time_point start;
|
||||
double start_value, end_value, duration;
|
||||
};
|
||||
@@ -1,120 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "d2d_svg.h"
|
||||
|
||||
D2DSVG& D2DSVG::load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc)
|
||||
{
|
||||
svg = nullptr;
|
||||
winrt::com_ptr<IStream> svg_stream;
|
||||
auto h = SHCreateStreamOnFileEx(filename.c_str(),
|
||||
STGM_READ,
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
FALSE,
|
||||
nullptr,
|
||||
svg_stream.put());
|
||||
winrt::check_hresult(h);
|
||||
|
||||
auto h1 = d2d_dc->CreateSvgDocument(
|
||||
svg_stream.get(),
|
||||
D2D1::SizeF(1, 1),
|
||||
svg.put());
|
||||
|
||||
winrt::check_hresult(h1);
|
||||
|
||||
winrt::com_ptr<ID2D1SvgElement> root;
|
||||
svg->GetRoot(root.put());
|
||||
float tmp;
|
||||
winrt::check_hresult(root->GetAttributeValue(L"width", &tmp));
|
||||
svg_width = static_cast<int>(tmp);
|
||||
winrt::check_hresult(root->GetAttributeValue(L"height", &tmp));
|
||||
svg_height = static_cast<int>(tmp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
D2DSVG& D2DSVG::resize(int x, int y, int width, int height, float fill, float max_scale)
|
||||
{
|
||||
// Center
|
||||
transform = D2D1::Matrix3x2F::Identity();
|
||||
transform = transform * D2D1::Matrix3x2F::Translation((width - svg_width) / 2.0f, (height - svg_height) / 2.0f);
|
||||
float h_scale = fill * height / svg_height;
|
||||
float v_scale = fill * width / svg_width;
|
||||
used_scale = std::min(h_scale, v_scale);
|
||||
if (max_scale > 0)
|
||||
{
|
||||
used_scale = std::min(used_scale, max_scale);
|
||||
}
|
||||
transform = transform * D2D1::Matrix3x2F::Scale(used_scale, used_scale, D2D1::Point2F(width / 2.0f, height / 2.0f));
|
||||
transform = transform * D2D1::Matrix3x2F::Translation(static_cast<float>(x), static_cast<float>(y));
|
||||
return *this;
|
||||
}
|
||||
|
||||
D2DSVG& D2DSVG::recolor(uint32_t oldcolor, uint32_t newcolor)
|
||||
{
|
||||
auto new_color = D2D1::ColorF(newcolor & 0xFFFFFF, 1);
|
||||
auto old_color = D2D1::ColorF(oldcolor & 0xFFFFFF, 1);
|
||||
std::function<void(ID2D1SvgElement * element)> recurse = [&](ID2D1SvgElement* element) {
|
||||
if (!element)
|
||||
return;
|
||||
if (element->IsAttributeSpecified(L"fill"))
|
||||
{
|
||||
D2D1_COLOR_F elem_fill;
|
||||
winrt::com_ptr<ID2D1SvgPaint> paint;
|
||||
element->GetAttributeValue(L"fill", paint.put());
|
||||
paint->GetColor(&elem_fill);
|
||||
if (elem_fill.r == old_color.r && elem_fill.g == old_color.g && elem_fill.b == old_color.b)
|
||||
{
|
||||
winrt::check_hresult(element->SetAttributeValue(L"fill", new_color));
|
||||
}
|
||||
}
|
||||
winrt::com_ptr<ID2D1SvgElement> sub;
|
||||
element->GetFirstChild(sub.put());
|
||||
while (sub)
|
||||
{
|
||||
recurse(sub.get());
|
||||
winrt::com_ptr<ID2D1SvgElement> next;
|
||||
element->GetNextChild(sub.get(), next.put());
|
||||
sub = next;
|
||||
}
|
||||
};
|
||||
winrt::com_ptr<ID2D1SvgElement> root;
|
||||
svg->GetRoot(root.put());
|
||||
recurse(root.get());
|
||||
return *this;
|
||||
}
|
||||
|
||||
D2DSVG& D2DSVG::render(ID2D1DeviceContext5* d2d_dc)
|
||||
{
|
||||
D2D1_MATRIX_3X2_F current;
|
||||
d2d_dc->GetTransform(¤t);
|
||||
d2d_dc->SetTransform(transform * current);
|
||||
d2d_dc->DrawSvgDocument(svg.get());
|
||||
d2d_dc->SetTransform(current);
|
||||
return *this;
|
||||
}
|
||||
|
||||
D2DSVG& D2DSVG::toggle_element(const wchar_t* id, bool visible)
|
||||
{
|
||||
winrt::com_ptr<ID2D1SvgElement> element;
|
||||
if (svg->FindElementById(id, element.put()) != S_OK)
|
||||
return *this;
|
||||
if (!element)
|
||||
return *this;
|
||||
element->SetAttributeValue(L"display", visible ? D2D1_SVG_DISPLAY::D2D1_SVG_DISPLAY_INLINE : D2D1_SVG_DISPLAY::D2D1_SVG_DISPLAY_NONE);
|
||||
return *this;
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID2D1SvgElement> D2DSVG::find_element(const std::wstring& id)
|
||||
{
|
||||
winrt::com_ptr<ID2D1SvgElement> element;
|
||||
winrt::check_hresult(svg->FindElementById(id.c_str(), element.put()));
|
||||
return element;
|
||||
}
|
||||
|
||||
D2D1_RECT_F D2DSVG::rescale(D2D1_RECT_F rect)
|
||||
{
|
||||
D2D1_RECT_F result;
|
||||
auto src = reinterpret_cast<D2D1_POINT_2F*>(&rect);
|
||||
auto dst = reinterpret_cast<D2D1_POINT_2F*>(&result);
|
||||
dst[0] = src[0] * transform;
|
||||
dst[1] = src[1] * transform;
|
||||
return result;
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
#include <d2d1_3.h>
|
||||
#include <d2d1_3helper.h>
|
||||
#include <winrt/base.h>
|
||||
#include <string>
|
||||
|
||||
class D2DSVG
|
||||
{
|
||||
public:
|
||||
D2DSVG& load(const std::wstring& filename, ID2D1DeviceContext5* d2d_dc);
|
||||
D2DSVG& resize(int x, int y, int width, int height, float fill, float max_scale = -1.0f);
|
||||
D2DSVG& render(ID2D1DeviceContext5* d2d_dc);
|
||||
D2DSVG& recolor(uint32_t oldcolor, uint32_t newcolor);
|
||||
float get_scale() const { return used_scale; }
|
||||
int width() const { return svg_width; }
|
||||
int height() const { return svg_height; }
|
||||
D2DSVG& toggle_element(const wchar_t* id, bool visible);
|
||||
winrt::com_ptr<ID2D1SvgElement> find_element(const std::wstring& id);
|
||||
D2D1_RECT_F rescale(D2D1_RECT_F rect);
|
||||
|
||||
protected:
|
||||
float used_scale = 1.0f;
|
||||
winrt::com_ptr<ID2D1SvgDocument> svg;
|
||||
int svg_width = -1, svg_height = -1;
|
||||
D2D1::Matrix3x2F transform;
|
||||
};
|
||||
@@ -1,54 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "d2d_text.h"
|
||||
|
||||
D2DText::D2DText(float text_size, float scale)
|
||||
{
|
||||
winrt::check_hresult(DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(factory), reinterpret_cast<IUnknown**>(factory.put_void())));
|
||||
resize(text_size, scale);
|
||||
winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER));
|
||||
winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER));
|
||||
}
|
||||
|
||||
D2DText& D2DText::resize(float text_size, float scale)
|
||||
{
|
||||
format = nullptr;
|
||||
winrt::check_hresult(factory->CreateTextFormat(L"Segoe UI",
|
||||
nullptr,
|
||||
DWRITE_FONT_WEIGHT_NORMAL,
|
||||
DWRITE_FONT_STYLE_NORMAL,
|
||||
DWRITE_FONT_STRETCH_NORMAL,
|
||||
text_size * scale,
|
||||
L"en-us",
|
||||
format.put()));
|
||||
winrt::check_hresult(format->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER));
|
||||
return *this;
|
||||
}
|
||||
|
||||
D2DText& D2DText::set_alignment_left()
|
||||
{
|
||||
winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING));
|
||||
return *this;
|
||||
}
|
||||
|
||||
D2DText& D2DText::set_alignment_center()
|
||||
{
|
||||
winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER));
|
||||
return *this;
|
||||
}
|
||||
|
||||
D2DText& D2DText::set_alignment_right()
|
||||
{
|
||||
winrt::check_hresult(format->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_TRAILING));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void D2DText::write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text)
|
||||
{
|
||||
winrt::com_ptr<ID2D1SolidColorBrush> brush;
|
||||
d2d_dc->CreateSolidColorBrush(color, brush.put());
|
||||
d2d_dc->DrawText(text.c_str(),
|
||||
static_cast<UINT32>(text.length()),
|
||||
format.get(),
|
||||
rect,
|
||||
brush.get());
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
#include <winrt/base.h>
|
||||
#include <dwrite.h>
|
||||
|
||||
class D2DText
|
||||
{
|
||||
public:
|
||||
D2DText(float text_size = 15.0f, float scale = 1.0f);
|
||||
D2DText& resize(float text_size, float scale);
|
||||
D2DText& set_alignment_left();
|
||||
D2DText& set_alignment_center();
|
||||
D2DText& set_alignment_right();
|
||||
void write(ID2D1DeviceContext5* d2d_dc, D2D1_COLOR_F color, D2D1_RECT_F rect, std::wstring text);
|
||||
|
||||
private:
|
||||
winrt::com_ptr<IDWriteFactory> factory;
|
||||
winrt::com_ptr<IDWriteTextFormat> format;
|
||||
};
|
||||
@@ -1,211 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "d2d_window.h"
|
||||
|
||||
#include <common/utils/resources.h>
|
||||
|
||||
D2DWindow::D2DWindow()
|
||||
{
|
||||
static const WCHAR* class_name = L"PToyD2DPopup";
|
||||
WNDCLASS wc = {};
|
||||
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wc.hInstance = reinterpret_cast<HINSTANCE>(&__ImageBase);
|
||||
wc.lpszClassName = class_name;
|
||||
wc.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wc.lpfnWndProc = d2d_window_proc;
|
||||
RegisterClass(&wc);
|
||||
hwnd = CreateWindowExW(WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_NOREDIRECTIONBITMAP | WS_EX_LAYERED,
|
||||
wc.lpszClassName,
|
||||
L"PToyD2DPopup",
|
||||
WS_POPUP | WS_VISIBLE,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
nullptr,
|
||||
nullptr,
|
||||
wc.hInstance,
|
||||
this);
|
||||
WINRT_VERIFY(hwnd);
|
||||
}
|
||||
|
||||
void D2DWindow::show(UINT x, UINT y, UINT width, UINT height)
|
||||
{
|
||||
if (!initialized)
|
||||
{
|
||||
base_init();
|
||||
}
|
||||
base_resize(width, height);
|
||||
render_empty();
|
||||
hidden = false;
|
||||
on_show();
|
||||
SetWindowPos(hwnd, HWND_TOPMOST, x, y, width, height, 0);
|
||||
ShowWindow(hwnd, SW_SHOWNORMAL);
|
||||
SetForegroundWindow(hwnd);
|
||||
UpdateWindow(hwnd);
|
||||
}
|
||||
|
||||
void D2DWindow::hide()
|
||||
{
|
||||
hidden = true;
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
on_hide();
|
||||
}
|
||||
|
||||
void D2DWindow::initialize()
|
||||
{
|
||||
base_init();
|
||||
}
|
||||
|
||||
void D2DWindow::base_init()
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
// D2D1Factory is independent from the device, no need to recreate it if we need to recreate the device.
|
||||
if (!d2d_factory)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
D2D1_FACTORY_OPTIONS options = { D2D1_DEBUG_LEVEL_INFORMATION };
|
||||
#else
|
||||
D2D1_FACTORY_OPTIONS options = {};
|
||||
#endif
|
||||
winrt::check_hresult(D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED,
|
||||
__uuidof(d2d_factory),
|
||||
&options,
|
||||
d2d_factory.put_void()));
|
||||
}
|
||||
// For all other stuff - assign nullptr first to release the object, to reset the com_ptr.
|
||||
d2d_dc = nullptr;
|
||||
d2d_device = nullptr;
|
||||
dxgi_factory = nullptr;
|
||||
dxgi_device = nullptr;
|
||||
d3d_device = nullptr;
|
||||
winrt::check_hresult(D3D11CreateDevice(nullptr,
|
||||
D3D_DRIVER_TYPE_HARDWARE,
|
||||
nullptr,
|
||||
D3D11_CREATE_DEVICE_BGRA_SUPPORT,
|
||||
nullptr,
|
||||
0,
|
||||
D3D11_SDK_VERSION,
|
||||
d3d_device.put(),
|
||||
nullptr,
|
||||
nullptr));
|
||||
winrt::check_hresult(d3d_device->QueryInterface(__uuidof(dxgi_device), dxgi_device.put_void()));
|
||||
winrt::check_hresult(CreateDXGIFactory2(0, __uuidof(dxgi_factory), dxgi_factory.put_void()));
|
||||
winrt::check_hresult(d2d_factory->CreateDevice(dxgi_device.get(), d2d_device.put()));
|
||||
winrt::check_hresult(d2d_device->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, d2d_dc.put()));
|
||||
init();
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void D2DWindow::base_resize(UINT width, UINT height)
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
if (!initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
window_width = width;
|
||||
window_height = height;
|
||||
if (window_width == 0 || window_height == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
DXGI_SWAP_CHAIN_DESC1 sc_description = {};
|
||||
sc_description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
sc_description.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
sc_description.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
sc_description.BufferCount = 2;
|
||||
sc_description.SampleDesc.Count = 1;
|
||||
sc_description.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
|
||||
sc_description.Width = window_width;
|
||||
sc_description.Height = window_height;
|
||||
dxgi_swap_chain = nullptr;
|
||||
winrt::check_hresult(dxgi_factory->CreateSwapChainForComposition(dxgi_device.get(),
|
||||
&sc_description,
|
||||
nullptr,
|
||||
dxgi_swap_chain.put()));
|
||||
composition_device = nullptr;
|
||||
winrt::check_hresult(DCompositionCreateDevice(dxgi_device.get(),
|
||||
__uuidof(composition_device),
|
||||
composition_device.put_void()));
|
||||
|
||||
composition_target = nullptr;
|
||||
winrt::check_hresult(composition_device->CreateTargetForHwnd(hwnd, true, composition_target.put()));
|
||||
|
||||
composition_visual = nullptr;
|
||||
winrt::check_hresult(composition_device->CreateVisual(composition_visual.put()));
|
||||
winrt::check_hresult(composition_visual->SetContent(dxgi_swap_chain.get()));
|
||||
winrt::check_hresult(composition_target->SetRoot(composition_visual.get()));
|
||||
|
||||
dxgi_surface = nullptr;
|
||||
winrt::check_hresult(dxgi_swap_chain->GetBuffer(0, __uuidof(dxgi_surface), dxgi_surface.put_void()));
|
||||
D2D1_BITMAP_PROPERTIES1 properties = {};
|
||||
properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
|
||||
properties.pixelFormat.format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
properties.bitmapOptions = D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
|
||||
|
||||
d2d_bitmap = nullptr;
|
||||
winrt::check_hresult(d2d_dc->CreateBitmapFromDxgiSurface(dxgi_surface.get(),
|
||||
properties,
|
||||
d2d_bitmap.put()));
|
||||
d2d_dc->SetTarget(d2d_bitmap.get());
|
||||
resize();
|
||||
}
|
||||
|
||||
void D2DWindow::base_render()
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
if (!initialized || !d2d_dc || !d2d_bitmap)
|
||||
return;
|
||||
d2d_dc->BeginDraw();
|
||||
render(d2d_dc.get());
|
||||
winrt::check_hresult(d2d_dc->EndDraw());
|
||||
winrt::check_hresult(dxgi_swap_chain->Present(1, 0));
|
||||
winrt::check_hresult(composition_device->Commit());
|
||||
}
|
||||
|
||||
void D2DWindow::render_empty()
|
||||
{
|
||||
std::unique_lock lock(mutex);
|
||||
if (!initialized || !d2d_dc || !d2d_bitmap)
|
||||
return;
|
||||
d2d_dc->BeginDraw();
|
||||
d2d_dc->Clear();
|
||||
winrt::check_hresult(d2d_dc->EndDraw());
|
||||
winrt::check_hresult(dxgi_swap_chain->Present(1, 0));
|
||||
winrt::check_hresult(composition_device->Commit());
|
||||
}
|
||||
|
||||
D2DWindow::~D2DWindow()
|
||||
{
|
||||
ShowWindow(hwnd, SW_HIDE);
|
||||
DestroyWindow(hwnd);
|
||||
}
|
||||
|
||||
D2DWindow* D2DWindow::this_from_hwnd(HWND window)
|
||||
{
|
||||
return reinterpret_cast<D2DWindow*>(GetWindowLongPtr(window, GWLP_USERDATA));
|
||||
}
|
||||
|
||||
LRESULT __stdcall D2DWindow::d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam)
|
||||
{
|
||||
auto self = this_from_hwnd(window);
|
||||
switch (message)
|
||||
{
|
||||
case WM_NCCREATE:
|
||||
{
|
||||
auto create_struct = reinterpret_cast<CREATESTRUCT*>(lparam);
|
||||
SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(create_struct->lpCreateParams));
|
||||
return TRUE;
|
||||
}
|
||||
case WM_MOVE:
|
||||
case WM_SIZE:
|
||||
self->base_resize(static_cast<unsigned>(lparam) & 0xFFFF, static_cast<unsigned>(lparam) >> 16);
|
||||
[[fallthrough]];
|
||||
case WM_PAINT:
|
||||
self->base_render();
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return DefWindowProc(window, message, wparam, lparam);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
#pragma once
|
||||
#include <winrt/base.h>
|
||||
#include <Windows.h>
|
||||
#include <dxgi1_3.h>
|
||||
#include <d3d11_2.h>
|
||||
#include <d2d1_3.h>
|
||||
#include <d2d1_3helper.h>
|
||||
#include <d2d1helper.h>
|
||||
#include <dcomp.h>
|
||||
#include <dwmapi.h>
|
||||
#include <string>
|
||||
#include "d2d_svg.h"
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
|
||||
class D2DWindow
|
||||
{
|
||||
public:
|
||||
D2DWindow();
|
||||
void show(UINT x, UINT y, UINT width, UINT height);
|
||||
void hide();
|
||||
void initialize();
|
||||
virtual ~D2DWindow();
|
||||
|
||||
protected:
|
||||
// Implement this:
|
||||
|
||||
// Initialization - called when D2D device needs to be created.
|
||||
// When called all D2DWindow members will be initialized, including d2d_dc
|
||||
virtual void init() = 0;
|
||||
// resize - when called, window_width and window_height will have current window size
|
||||
virtual void resize() = 0;
|
||||
// render - called on WM_PAINT, BeginPaint/EndPaint is handled by D2DWindow
|
||||
virtual void render(ID2D1DeviceContext5* d2d_dc) = 0;
|
||||
// on_show, on_hide - called when the window is about to be shown or about to be hidden
|
||||
virtual void on_show() = 0;
|
||||
virtual void on_hide() = 0;
|
||||
|
||||
static LRESULT __stdcall d2d_window_proc(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
|
||||
static D2DWindow* this_from_hwnd(HWND window);
|
||||
|
||||
void base_init();
|
||||
void base_resize(UINT width, UINT height);
|
||||
void base_render();
|
||||
void render_empty();
|
||||
|
||||
std::recursive_mutex mutex;
|
||||
bool hidden = true;
|
||||
bool initialized = false;
|
||||
HWND hwnd;
|
||||
UINT window_width{};
|
||||
UINT window_height{};
|
||||
winrt::com_ptr<ID3D11Device> d3d_device;
|
||||
winrt::com_ptr<IDXGIDevice> dxgi_device;
|
||||
winrt::com_ptr<IDXGIFactory2> dxgi_factory;
|
||||
winrt::com_ptr<IDXGISwapChain1> dxgi_swap_chain;
|
||||
winrt::com_ptr<IDCompositionDevice> composition_device;
|
||||
winrt::com_ptr<IDCompositionTarget> composition_target;
|
||||
winrt::com_ptr<IDCompositionVisual> composition_visual;
|
||||
winrt::com_ptr<IDXGISurface2> dxgi_surface;
|
||||
winrt::com_ptr<ID2D1Bitmap1> d2d_bitmap;
|
||||
winrt::com_ptr<ID2D1Factory6> d2d_factory;
|
||||
winrt::com_ptr<ID2D1Device5> d2d_device;
|
||||
winrt::com_ptr<ID2D1DeviceContext5> d2d_dc;
|
||||
};
|
||||
@@ -1,144 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include <Windows.h>
|
||||
#include <common/utils/window.h>
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
#include <common/utils/ProcessWaiter.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
#include <common/utils/UnhandledExceptionHandler.h>
|
||||
#include <common/utils/logger_helper.h>
|
||||
#include <common/utils/EventWaiter.h>
|
||||
#include <common/utils/gpo.h>
|
||||
|
||||
#include <common/Telemetry/EtwTrace/EtwTrace.h>
|
||||
|
||||
#include "shortcut_guide.h"
|
||||
#include "target_state.h"
|
||||
#include "ShortcutGuideConstants.h"
|
||||
#include "trace.h"
|
||||
|
||||
const std::wstring instanceMutexName = L"Local\\PowerToys_ShortcutGuide_InstanceMutex";
|
||||
|
||||
// set current path to the executable path
|
||||
bool SetCurrentPath()
|
||||
{
|
||||
TCHAR buffer[MAX_PATH] = { 0 };
|
||||
if (!GetModuleFileName(NULL, buffer, MAX_PATH))
|
||||
{
|
||||
Logger::error(L"Failed to get module path. {}", get_last_error_or_default(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!PathRemoveFileSpec(buffer))
|
||||
{
|
||||
Logger::error(L"Failed to remove file from module path. {}", get_last_error_or_default(GetLastError()));
|
||||
return false;
|
||||
}
|
||||
|
||||
std::error_code err;
|
||||
std::filesystem::current_path(buffer, err);
|
||||
if (err.value())
|
||||
{
|
||||
Logger::error("Failed to set current path. {}", err.message());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int WINAPI wWinMain(_In_ HINSTANCE /*hInstance*/, _In_opt_ HINSTANCE /*hPrevInstance*/, _In_ PWSTR lpCmdLine, _In_ int /*nCmdShow*/)
|
||||
{
|
||||
winrt::init_apartment();
|
||||
LoggerHelpers::init_logger(ShortcutGuideConstants::ModuleKey, L"ShortcutGuide", LogSettings::shortcutGuideLoggerName);
|
||||
|
||||
Shared::Trace::ETWTrace trace;
|
||||
trace.UpdateState(true);
|
||||
|
||||
if (powertoys_gpo::getConfiguredShortcutGuideEnabledValue() == powertoys_gpo::gpo_rule_configured_disabled)
|
||||
{
|
||||
Logger::warn(L"Tried to start with a GPO policy setting the utility to always be disabled. Please contact your systems administrator.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
InitUnhandledExceptionHandler();
|
||||
Logger::trace("Starting Shortcut Guide");
|
||||
|
||||
if (!SetCurrentPath())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Trace::RegisterProvider();
|
||||
if (std::wstring(lpCmdLine).find(L' ') != std::wstring::npos)
|
||||
{
|
||||
Logger::trace("Sending settings telemetry");
|
||||
auto settings = OverlayWindow::GetSettings();
|
||||
Trace::SendSettings(settings);
|
||||
Trace::UnregisterProvider();
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto mutex = CreateMutex(nullptr, true, instanceMutexName.c_str());
|
||||
if (mutex == nullptr)
|
||||
{
|
||||
Logger::error(L"Failed to create mutex. {}", get_last_error_or_default(GetLastError()));
|
||||
}
|
||||
|
||||
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||
{
|
||||
Logger::warn(L"Shortcut Guide instance is already running");
|
||||
Trace::UnregisterProvider();
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::wstring pid = std::wstring(lpCmdLine);
|
||||
if (!pid.empty())
|
||||
{
|
||||
auto mainThreadId = GetCurrentThreadId();
|
||||
ProcessWaiter::OnProcessTerminate(pid, [mainThreadId](int err) {
|
||||
if (err != ERROR_SUCCESS)
|
||||
{
|
||||
Logger::error(L"Failed to wait for parent process exit. {}", get_last_error_or_default(err));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::trace(L"PowerToys runner exited.");
|
||||
}
|
||||
|
||||
Logger::trace(L"Exiting Shortcut Guide");
|
||||
PostThreadMessage(mainThreadId, WM_QUIT, 0, 0);
|
||||
});
|
||||
}
|
||||
|
||||
auto hwnd = GetForegroundWindow();
|
||||
auto window = OverlayWindow(hwnd);
|
||||
EventWaiter exitEventWaiter;
|
||||
if (window.IsDisabled())
|
||||
{
|
||||
Logger::trace("SG is disabled for the current foreground app. Exiting SG");
|
||||
Trace::UnregisterProvider();
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto mainThreadId = GetCurrentThreadId();
|
||||
exitEventWaiter = EventWaiter(CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT, [mainThreadId, &window](int err) {
|
||||
if (err != ERROR_SUCCESS)
|
||||
{
|
||||
Logger::error(L"Failed to wait for {} event. {}", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT, get_last_error_or_default(err));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::trace(L"{} event was signaled", CommonSharedConstants::SHORTCUT_GUIDE_EXIT_EVENT);
|
||||
}
|
||||
|
||||
window.CloseWindow(HideWindowType::THE_SHORTCUT_PRESSED, mainThreadId);
|
||||
});
|
||||
}
|
||||
|
||||
window.ShowWindow();
|
||||
run_message_loop();
|
||||
|
||||
trace.Flush();
|
||||
Trace::UnregisterProvider();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#include "pch.h"
|
||||
#include "native_event_waiter.h"
|
||||
|
||||
void NativeEventWaiter::run()
|
||||
{
|
||||
while (!aborting)
|
||||
{
|
||||
auto result = WaitForSingleObject(event_handle, timeout);
|
||||
if (!aborting && result == WAIT_OBJECT_0)
|
||||
{
|
||||
action();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NativeEventWaiter::NativeEventWaiter(const std::wstring& event_name, std::function<void()> action)
|
||||
{
|
||||
event_handle = CreateEventW(NULL, FALSE, FALSE, event_name.c_str());
|
||||
this->action = action;
|
||||
running_thread = std::thread([&]() { run(); });
|
||||
}
|
||||
|
||||
NativeEventWaiter::~NativeEventWaiter()
|
||||
{
|
||||
aborting = true;
|
||||
SetEvent(event_handle);
|
||||
running_thread.join();
|
||||
CloseHandle(event_handle);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include "pch.h"
|
||||
#include "common/interop/shared_constants.h"
|
||||
|
||||
class NativeEventWaiter
|
||||
{
|
||||
static const int timeout = 1000;
|
||||
|
||||
HANDLE event_handle = nullptr;
|
||||
std::function<void()> action = nullptr;
|
||||
std::atomic<bool> aborting = false;
|
||||
|
||||
void run();
|
||||
std::thread running_thread;
|
||||
|
||||
public:
|
||||
NativeEventWaiter(const std::wstring& event_name, std::function<void()> action);
|
||||
~NativeEventWaiter();
|
||||
};
|
||||